]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Oct 2012 02:21:15 +0000 (11:21 +0900)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Oct 2012 02:21:15 +0000 (11:21 +0900)
Pull powerpc uapi disintegration from Benjamin Herrenschmidt.

* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
  UAPI: (Scripted) Disintegrate arch/powerpc/include/asm

2182 files changed:
Documentation/ABI/testing/sysfs-block
Documentation/ABI/testing/sysfs-bus-fcoe
Documentation/DocBook/media/v4l/compat.xml
Documentation/DocBook/media/v4l/controls.xml
Documentation/DocBook/media/v4l/io.xml
Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
Documentation/DocBook/media/v4l/pixfmt.xml
Documentation/DocBook/media/v4l/subdev-formats.xml
Documentation/DocBook/media/v4l/vidioc-qbuf.xml
Documentation/DocBook/media/v4l/vidioc-querybuf.xml
Documentation/DocBook/mtdnand.tmpl
Documentation/arm/Booting
Documentation/block/biodoc.txt
Documentation/devicetree/bindings/arm/davinci/nand.txt [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/atmel-i2c.txt [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/davinci.txt [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/i2c-mxs.txt
Documentation/devicetree/bindings/i2c/nomadik.txt [new file with mode: 0644]
Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
Documentation/devicetree/bindings/mmc/atmel-hsmci.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/mmc.txt
Documentation/devicetree/bindings/mmc/pxa-mmc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/samsung-sdhci.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/sdhci-dove.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/sdhci-spear.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mtd/atmel-nand.txt
Documentation/devicetree/bindings/mtd/gpmi-nand.txt
Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mtd/mtd-physmap.txt
Documentation/devicetree/bindings/pwm/imx-pwm.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pwm/mxs-pwm.txt
Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
Documentation/devicetree/bindings/timer/brcm,bcm2835-system-timer.txt
Documentation/driver-model/devres.txt
Documentation/filesystems/nfs/nfs.txt
Documentation/filesystems/nfs/nfsd-admin-interfaces.txt [new file with mode: 0644]
Documentation/hwmon/da9052
Documentation/hwmon/max1619
Documentation/hwmon/twl4030-madc-hwmon
Documentation/kernel-parameters.txt
Documentation/leds/leds-lp5523.txt
Documentation/percpu-rw-semaphore.txt [new file with mode: 0644]
Documentation/pwm.txt
Documentation/scsi/ChangeLog.megaraid_sas
Documentation/target/tcm_mod_builder.py
Documentation/video4linux/v4l2-controls.txt
Documentation/virtual/uml/UserModeLinux-HOWTO.txt
MAINTAINERS
Makefile
arch/Kconfig
arch/alpha/Kconfig
arch/alpha/include/asm/Kbuild
arch/alpha/include/asm/exec.h [deleted file]
arch/alpha/include/asm/processor.h
arch/alpha/include/asm/thread_info.h
arch/alpha/include/asm/unistd.h
arch/alpha/kernel/alpha_ksyms.c
arch/alpha/kernel/entry.S
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/process.c
arch/alpha/kernel/ptrace.c
arch/alpha/kernel/signal.c
arch/arm/Kconfig
arch/arm/boot/compressed/.gitignore
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/head.S
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/at91sam9260.dtsi
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9g20.dtsi
arch/arm/boot/dts/at91sam9g25ek.dts
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9m10g45ek.dts
arch/arm/boot/dts/at91sam9n12.dtsi
arch/arm/boot/dts/at91sam9n12ek.dts
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/imx51.dtsi
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/omap4-panda.dts
arch/arm/boot/dts/omap4-sdp.dts
arch/arm/boot/dts/omap5-evm.dts
arch/arm/boot/dts/omap5.dtsi
arch/arm/boot/dts/spear300-evb.dts
arch/arm/boot/dts/spear320-evb.dts
arch/arm/boot/dts/tegra20-seaboard.dts
arch/arm/boot/dts/tegra20.dtsi
arch/arm/common/it8152.c
arch/arm/configs/cam60_defconfig
arch/arm/configs/corgi_defconfig
arch/arm/configs/ep93xx_defconfig
arch/arm/configs/mini2440_defconfig
arch/arm/configs/mv78xx0_defconfig
arch/arm/configs/nhk8815_defconfig
arch/arm/configs/orion5x_defconfig
arch/arm/configs/pxa3xx_defconfig
arch/arm/configs/spitz_defconfig
arch/arm/include/asm/assembler.h
arch/arm/include/asm/cacheflush.h
arch/arm/include/asm/glue-cache.h
arch/arm/include/asm/opcodes-virt.h
arch/arm/include/asm/processor.h
arch/arm/include/asm/ptrace.h
arch/arm/include/asm/system.h
arch/arm/include/asm/thread_info.h
arch/arm/include/asm/unistd.h
arch/arm/include/asm/vfpmacros.h
arch/arm/include/asm/virt.h [new file with mode: 0644]
arch/arm/kernel/Makefile
arch/arm/kernel/calls.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/head.S
arch/arm/kernel/hyp-stub.S [new file with mode: 0644]
arch/arm/kernel/process.c
arch/arm/kernel/setup.c
arch/arm/kernel/signal.c
arch/arm/kernel/smp.c
arch/arm/kernel/suspend.c
arch/arm/kernel/sys_arm.c
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91rm9200_devices.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9n12.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/at91sam9x5.c
arch/arm/mach-at91/include/mach/at91_twi.h [deleted file]
arch/arm/mach-at91/pm.c
arch/arm/mach-at91/setup.c
arch/arm/mach-clps711x/autcpu12.c
arch/arm/mach-davinci/Kconfig
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-dm646x-evm.c
arch/arm/mach-davinci/da850.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-davinci/include/mach/da8xx.h
arch/arm/mach-davinci/include/mach/mux.h
arch/arm/mach-davinci/include/mach/psc.h
arch/arm/mach-exynos/dma.c
arch/arm/mach-exynos/mach-nuri.c
arch/arm/mach-exynos/mach-origen.c
arch/arm/mach-exynos/mach-smdk4x12.c
arch/arm/mach-exynos/mach-smdkv310.c
arch/arm/mach-exynos/mach-universal_c210.c
arch/arm/mach-exynos/setup-fimd0.c
arch/arm/mach-footbridge/include/mach/irqs.h
arch/arm/mach-imx/clk-imx51-imx53.c
arch/arm/mach-integrator/include/mach/cm.h
arch/arm/mach-integrator/include/mach/platform.h
arch/arm/mach-integrator/integrator_ap.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-iop13xx/iq81340sc.c
arch/arm/mach-iop13xx/pci.c
arch/arm/mach-ks8695/include/mach/memory.h
arch/arm/mach-mv78xx0/addr-map.c
arch/arm/mach-mv78xx0/common.c
arch/arm/mach-omap1/devices.c
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-flash.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-omap3stalker.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/board-zoom-peripherals.c
arch/arm/mach-omap2/clkt_clksel.c
arch/arm/mach-omap2/clock33xx_data.c
arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/hsmmc.c
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/omap-secure.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/opp.c
arch/arm/mach-omap2/pm-debug.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/sr_device.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-omap2/twl-common.c
arch/arm/mach-pxa/cm-x2xx.c
arch/arm/mach-pxa/palmte2.c
arch/arm/mach-pxa/sharpsl_pm.c
arch/arm/mach-pxa/viper.c
arch/arm/mach-rpc/ecard.c
arch/arm/mach-s3c24xx/irq-s3c2416.c
arch/arm/mach-s3c24xx/irq-s3c2443.c
arch/arm/mach-s3c24xx/mach-smdk2416.c
arch/arm/mach-s3c24xx/simtec-usb.c
arch/arm/mach-s3c64xx/mach-anw6410.c
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-s3c64xx/mach-hmt.c
arch/arm/mach-s3c64xx/mach-mini6410.c
arch/arm/mach-s3c64xx/mach-ncp.c
arch/arm/mach-s3c64xx/mach-real6410.c
arch/arm/mach-s3c64xx/mach-smartq5.c
arch/arm/mach-s3c64xx/mach-smartq7.c
arch/arm/mach-s3c64xx/mach-smdk6410.c
arch/arm/mach-s5p64x0/mach-smdk6440.c
arch/arm/mach-s5p64x0/mach-smdk6450.c
arch/arm/mach-s5pc100/mach-smdkc100.c
arch/arm/mach-s5pv210/mach-aquila.c
arch/arm/mach-s5pv210/mach-goni.c
arch/arm/mach-s5pv210/mach-smdkv210.c
arch/arm/mach-sa1100/assabet.c
arch/arm/mach-shark/pci.c
arch/arm/mach-shmobile/include/mach/common.h
arch/arm/mach-spear13xx/spear13xx.c
arch/arm/mach-tegra/Kconfig
arch/arm/mach-ux500/Kconfig
arch/arm/mach-vt8500/include/mach/uncompress.h
arch/arm/mach-vt8500/vt8500.c
arch/arm/mm/Kconfig
arch/arm/mm/cache-fa.S
arch/arm/mm/cache-v3.S
arch/arm/mm/cache-v4.S
arch/arm/mm/cache-v4wb.S
arch/arm/mm/cache-v4wt.S
arch/arm/mm/cache-v6.S
arch/arm/mm/cache-v7.S
arch/arm/mm/proc-arm1020.S
arch/arm/mm/proc-arm1020e.S
arch/arm/mm/proc-arm1022.S
arch/arm/mm/proc-arm1026.S
arch/arm/mm/proc-arm920.S
arch/arm/mm/proc-arm922.S
arch/arm/mm/proc-arm925.S
arch/arm/mm/proc-arm926.S
arch/arm/mm/proc-arm940.S
arch/arm/mm/proc-arm946.S
arch/arm/mm/proc-feroceon.S
arch/arm/mm/proc-macros.S
arch/arm/mm/proc-mohawk.S
arch/arm/mm/proc-v7.S
arch/arm/mm/proc-xsc3.S
arch/arm/mm/proc-xscale.S
arch/arm/plat-mxc/devices/platform-mxc_nand.c
arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
arch/arm/plat-nomadik/include/plat/pincfg.h
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/counter_32k.c
arch/arm/plat-omap/i2c.c
arch/arm/plat-omap/omap-pm-noop.c
arch/arm/plat-omap/omap_device.c
arch/arm/plat-samsung/include/plat/regs-fb-v4.h [deleted file]
arch/arm/plat-samsung/setup-mipiphy.c
arch/arm64/include/asm/Kbuild
arch/arm64/include/asm/hwcap.h
arch/arm64/include/asm/ptrace.h
arch/arm64/include/asm/sigcontext.h
arch/arm64/include/asm/stat.h
arch/arm64/include/asm/unistd.h
arch/arm64/include/asm/unistd32.h
arch/arm64/include/uapi/asm/Kbuild
arch/arm64/include/uapi/asm/auxvec.h [moved from arch/arm64/include/asm/auxvec.h with 100% similarity]
arch/arm64/include/uapi/asm/bitsperlong.h [moved from arch/arm64/include/asm/bitsperlong.h with 100% similarity]
arch/arm64/include/uapi/asm/byteorder.h [moved from arch/arm64/include/asm/byteorder.h with 100% similarity]
arch/arm64/include/uapi/asm/fcntl.h [moved from arch/arm64/include/asm/fcntl.h with 100% similarity]
arch/arm64/include/uapi/asm/hwcap.h [new file with mode: 0644]
arch/arm64/include/uapi/asm/param.h [moved from arch/arm64/include/asm/param.h with 100% similarity]
arch/arm64/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/arm64/include/uapi/asm/setup.h [moved from arch/arm64/include/asm/setup.h with 100% similarity]
arch/arm64/include/uapi/asm/sigcontext.h [new file with mode: 0644]
arch/arm64/include/uapi/asm/siginfo.h [moved from arch/arm64/include/asm/siginfo.h with 100% similarity]
arch/arm64/include/uapi/asm/signal.h [moved from arch/arm64/include/asm/signal.h with 100% similarity]
arch/arm64/include/uapi/asm/stat.h [new file with mode: 0644]
arch/arm64/include/uapi/asm/statfs.h [moved from arch/arm64/include/asm/statfs.h with 100% similarity]
arch/arm64/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/arm64/kernel/entry.S
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/signal32.c
arch/arm64/kernel/sys.c
arch/arm64/kernel/sys32.S
arch/arm64/kernel/sys_compat.c
arch/avr32/include/asm/Kbuild
arch/avr32/include/asm/exec.h [deleted file]
arch/avr32/include/asm/thread_info.h
arch/avr32/kernel/process.c
arch/avr32/kernel/signal.c
arch/avr32/mach-at32ap/at32ap700x.c
arch/blackfin/configs/BF561-ACVILON_defconfig
arch/blackfin/include/asm/thread_info.h
arch/blackfin/kernel/process.c
arch/blackfin/kernel/signal.c
arch/c6x/Kconfig
arch/c6x/include/asm/Kbuild
arch/c6x/include/asm/exec.h [deleted file]
arch/c6x/include/asm/processor.h
arch/c6x/include/asm/ptrace.h
arch/c6x/include/asm/syscalls.h
arch/c6x/include/asm/thread_info.h
arch/c6x/include/uapi/asm/Kbuild
arch/c6x/include/uapi/asm/byteorder.h [moved from arch/c6x/include/asm/byteorder.h with 100% similarity]
arch/c6x/include/uapi/asm/kvm_para.h [moved from arch/c6x/include/asm/kvm_para.h with 100% similarity]
arch/c6x/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/c6x/include/uapi/asm/setup.h [moved from arch/c6x/include/asm/setup.h with 100% similarity]
arch/c6x/include/uapi/asm/sigcontext.h [moved from arch/c6x/include/asm/sigcontext.h with 100% similarity]
arch/c6x/include/uapi/asm/swab.h [moved from arch/c6x/include/asm/swab.h with 100% similarity]
arch/c6x/include/uapi/asm/unistd.h [moved from arch/c6x/include/asm/unistd.h with 92% similarity]
arch/c6x/kernel/asm-offsets.c
arch/c6x/kernel/entry.S
arch/c6x/kernel/process.c
arch/cris/arch-v10/kernel/process.c
arch/cris/arch-v32/kernel/process.c
arch/cris/include/asm/Kbuild
arch/cris/include/asm/exec.h [deleted file]
arch/cris/include/asm/thread_info.h
arch/frv/Kconfig
arch/frv/include/asm/Kbuild
arch/frv/include/asm/exec.h [deleted file]
arch/frv/include/asm/processor.h
arch/frv/include/asm/ptrace.h
arch/frv/include/asm/thread_info.h
arch/frv/include/asm/unistd.h
arch/frv/kernel/Makefile
arch/frv/kernel/entry.S
arch/frv/kernel/frv_ksyms.c
arch/frv/kernel/kernel_execve.S [deleted file]
arch/frv/kernel/kernel_thread.S [deleted file]
arch/frv/kernel/process.c
arch/frv/kernel/signal.c
arch/h8300/include/asm/Kbuild
arch/h8300/include/asm/exec.h [deleted file]
arch/h8300/include/asm/thread_info.h
arch/h8300/kernel/process.c
arch/h8300/kernel/signal.c
arch/hexagon/include/asm/thread_info.h
arch/hexagon/kernel/signal.c
arch/hexagon/kernel/syscall.c
arch/ia64/Kconfig
arch/ia64/include/asm/Kbuild
arch/ia64/include/asm/exec.h [deleted file]
arch/ia64/include/asm/gcc_intrin.h
arch/ia64/include/asm/intrinsics.h
arch/ia64/include/asm/kvm_para.h
arch/ia64/include/asm/mman.h
arch/ia64/include/asm/param.h
arch/ia64/include/asm/perfmon.h
arch/ia64/include/asm/ptrace.h
arch/ia64/include/asm/siginfo.h
arch/ia64/include/asm/signal.h
arch/ia64/include/asm/termios.h
arch/ia64/include/asm/thread_info.h
arch/ia64/include/asm/types.h
arch/ia64/include/asm/unistd.h
arch/ia64/include/asm/ustack.h
arch/ia64/include/uapi/asm/Kbuild
arch/ia64/include/uapi/asm/auxvec.h [moved from arch/ia64/include/asm/auxvec.h with 100% similarity]
arch/ia64/include/uapi/asm/bitsperlong.h [moved from arch/ia64/include/asm/bitsperlong.h with 100% similarity]
arch/ia64/include/uapi/asm/break.h [moved from arch/ia64/include/asm/break.h with 100% similarity]
arch/ia64/include/uapi/asm/byteorder.h [moved from arch/ia64/include/asm/byteorder.h with 100% similarity]
arch/ia64/include/uapi/asm/cmpxchg.h [moved from arch/ia64/include/asm/cmpxchg.h with 100% similarity]
arch/ia64/include/uapi/asm/errno.h [moved from arch/ia64/include/asm/errno.h with 100% similarity]
arch/ia64/include/uapi/asm/fcntl.h [moved from arch/ia64/include/asm/fcntl.h with 100% similarity]
arch/ia64/include/uapi/asm/fpu.h [moved from arch/ia64/include/asm/fpu.h with 100% similarity]
arch/ia64/include/uapi/asm/gcc_intrin.h [new file with mode: 0644]
arch/ia64/include/uapi/asm/ia64regs.h [moved from arch/ia64/include/asm/ia64regs.h with 100% similarity]
arch/ia64/include/uapi/asm/intel_intrin.h [moved from arch/ia64/include/asm/intel_intrin.h with 100% similarity]
arch/ia64/include/uapi/asm/intrinsics.h [new file with mode: 0644]
arch/ia64/include/uapi/asm/ioctl.h [moved from arch/ia64/include/asm/ioctl.h with 100% similarity]
arch/ia64/include/uapi/asm/ioctls.h [moved from arch/ia64/include/asm/ioctls.h with 100% similarity]
arch/ia64/include/uapi/asm/ipcbuf.h [moved from arch/ia64/include/asm/ipcbuf.h with 100% similarity]
arch/ia64/include/uapi/asm/kvm.h [moved from arch/ia64/include/asm/kvm.h with 100% similarity]
arch/ia64/include/uapi/asm/kvm_para.h [new file with mode: 0644]
arch/ia64/include/uapi/asm/mman.h [new file with mode: 0644]
arch/ia64/include/uapi/asm/msgbuf.h [moved from arch/ia64/include/asm/msgbuf.h with 100% similarity]
arch/ia64/include/uapi/asm/param.h [new file with mode: 0644]
arch/ia64/include/uapi/asm/perfmon.h [new file with mode: 0644]
arch/ia64/include/uapi/asm/perfmon_default_smpl.h [moved from arch/ia64/include/asm/perfmon_default_smpl.h with 100% similarity]
arch/ia64/include/uapi/asm/poll.h [moved from arch/ia64/include/asm/poll.h with 100% similarity]
arch/ia64/include/uapi/asm/posix_types.h [moved from arch/ia64/include/asm/posix_types.h with 100% similarity]
arch/ia64/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/ia64/include/uapi/asm/ptrace_offsets.h [moved from arch/ia64/include/asm/ptrace_offsets.h with 100% similarity]
arch/ia64/include/uapi/asm/resource.h [moved from arch/ia64/include/asm/resource.h with 100% similarity]
arch/ia64/include/uapi/asm/rse.h [moved from arch/ia64/include/asm/rse.h with 100% similarity]
arch/ia64/include/uapi/asm/sembuf.h [moved from arch/ia64/include/asm/sembuf.h with 100% similarity]
arch/ia64/include/uapi/asm/setup.h [moved from arch/ia64/include/asm/setup.h with 100% similarity]
arch/ia64/include/uapi/asm/shmbuf.h [moved from arch/ia64/include/asm/shmbuf.h with 100% similarity]
arch/ia64/include/uapi/asm/sigcontext.h [moved from arch/ia64/include/asm/sigcontext.h with 100% similarity]
arch/ia64/include/uapi/asm/siginfo.h [new file with mode: 0644]
arch/ia64/include/uapi/asm/signal.h [new file with mode: 0644]
arch/ia64/include/uapi/asm/socket.h [moved from arch/ia64/include/asm/socket.h with 100% similarity]
arch/ia64/include/uapi/asm/sockios.h [moved from arch/ia64/include/asm/sockios.h with 100% similarity]
arch/ia64/include/uapi/asm/stat.h [moved from arch/ia64/include/asm/stat.h with 100% similarity]
arch/ia64/include/uapi/asm/statfs.h [moved from arch/ia64/include/asm/statfs.h with 100% similarity]
arch/ia64/include/uapi/asm/swab.h [moved from arch/ia64/include/asm/swab.h with 100% similarity]
arch/ia64/include/uapi/asm/termbits.h [moved from arch/ia64/include/asm/termbits.h with 100% similarity]
arch/ia64/include/uapi/asm/termios.h [new file with mode: 0644]
arch/ia64/include/uapi/asm/types.h [new file with mode: 0644]
arch/ia64/include/uapi/asm/ucontext.h [moved from arch/ia64/include/asm/ucontext.h with 100% similarity]
arch/ia64/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/ia64/include/uapi/asm/ustack.h [new file with mode: 0644]
arch/ia64/kernel/process.c
arch/ia64/kernel/signal.c
arch/ia64/kernel/time.c
arch/m32r/include/asm/Kbuild
arch/m32r/include/asm/exec.h [deleted file]
arch/m32r/include/asm/thread_info.h
arch/m32r/kernel/process.c
arch/m32r/kernel/signal.c
arch/m68k/Kconfig
arch/m68k/include/asm/Kbuild
arch/m68k/include/asm/exec.h [deleted file]
arch/m68k/include/asm/processor.h
arch/m68k/include/asm/ptrace.h
arch/m68k/include/asm/unistd.h
arch/m68k/kernel/entry.S
arch/m68k/kernel/process.c
arch/m68k/kernel/sys_m68k.c
arch/microblaze/include/asm/Kbuild
arch/microblaze/include/asm/exec.h [deleted file]
arch/microblaze/include/asm/thread_info.h
arch/microblaze/kernel/signal.c
arch/microblaze/kernel/sys_microblaze.c
arch/mips/configs/rb532_defconfig
arch/mips/include/asm/mach-jz4740/platform.h
arch/mips/include/asm/mach-jz4740/timer.h
arch/mips/include/asm/thread_info.h
arch/mips/jz4740/Kconfig
arch/mips/jz4740/Makefile
arch/mips/jz4740/board-qi_lb60.c
arch/mips/jz4740/platform.c
arch/mips/jz4740/pwm.c [deleted file]
arch/mips/jz4740/time.c
arch/mips/jz4740/timer.c
arch/mips/jz4740/timer.h [deleted file]
arch/mips/kernel/kgdb.c
arch/mips/kernel/linux32.c
arch/mips/kernel/syscall.c
arch/mn10300/Kconfig
arch/mn10300/include/asm/Kbuild
arch/mn10300/include/asm/exec.h [deleted file]
arch/mn10300/include/asm/frame.inc
arch/mn10300/include/asm/processor.h
arch/mn10300/include/asm/ptrace.h
arch/mn10300/include/asm/thread_info.h
arch/mn10300/include/asm/unistd.h
arch/mn10300/kernel/Makefile
arch/mn10300/kernel/entry.S
arch/mn10300/kernel/internal.h
arch/mn10300/kernel/kernel_execve.S [deleted file]
arch/mn10300/kernel/kthread.S [deleted file]
arch/mn10300/kernel/process.c
arch/mn10300/kernel/signal.c
arch/openrisc/include/asm/thread_info.h
arch/openrisc/kernel/process.c
arch/parisc/hpux/fs.c
arch/parisc/hpux/gate.S
arch/parisc/include/asm/Kbuild
arch/parisc/include/asm/exec.h [deleted file]
arch/parisc/include/asm/thread_info.h
arch/parisc/kernel/process.c
arch/parisc/kernel/signal.c
arch/parisc/kernel/sys_parisc32.c
arch/parisc/kernel/syscall.S
arch/powerpc/Kconfig
arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
arch/powerpc/configs/mpc83xx_defconfig
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/ptrace.h
arch/powerpc/include/asm/syscalls.h
arch/powerpc/include/asm/thread_info.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/misc.S
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/misc_64.S
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/sys_ppc32.c
arch/powerpc/kernel/time.c
arch/powerpc/platforms/pseries/eeh_event.c
arch/powerpc/platforms/pseries/hotplug-memory.c
arch/s390/Kconfig
arch/s390/Kconfig.debug
arch/s390/include/asm/Kbuild
arch/s390/include/asm/chpid.h
arch/s390/include/asm/cmb.h
arch/s390/include/asm/css_chars.h
arch/s390/include/asm/debug.h
arch/s390/include/asm/kvm_para.h
arch/s390/include/asm/mman.h
arch/s390/include/asm/page.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/ptrace.h
arch/s390/include/asm/schid.h
arch/s390/include/asm/setup.h
arch/s390/include/asm/signal.h
arch/s390/include/asm/termios.h
arch/s390/include/asm/thread_info.h
arch/s390/include/asm/types.h
arch/s390/include/asm/unistd.h
arch/s390/include/uapi/asm/Kbuild
arch/s390/include/uapi/asm/auxvec.h [moved from arch/s390/include/asm/auxvec.h with 100% similarity]
arch/s390/include/uapi/asm/bitsperlong.h [moved from arch/s390/include/asm/bitsperlong.h with 100% similarity]
arch/s390/include/uapi/asm/byteorder.h [moved from arch/s390/include/asm/byteorder.h with 100% similarity]
arch/s390/include/uapi/asm/chpid.h [new file with mode: 0644]
arch/s390/include/uapi/asm/chsc.h [moved from arch/s390/include/asm/chsc.h with 92% similarity]
arch/s390/include/uapi/asm/cmb.h [new file with mode: 0644]
arch/s390/include/uapi/asm/dasd.h [moved from arch/s390/include/asm/dasd.h with 100% similarity]
arch/s390/include/uapi/asm/debug.h [new file with mode: 0644]
arch/s390/include/uapi/asm/errno.h [moved from arch/s390/include/asm/errno.h with 100% similarity]
arch/s390/include/uapi/asm/fcntl.h [moved from arch/s390/include/asm/fcntl.h with 100% similarity]
arch/s390/include/uapi/asm/ioctl.h [moved from arch/s390/include/asm/ioctl.h with 100% similarity]
arch/s390/include/uapi/asm/ioctls.h [moved from arch/s390/include/asm/ioctls.h with 100% similarity]
arch/s390/include/uapi/asm/ipcbuf.h [moved from arch/s390/include/asm/ipcbuf.h with 100% similarity]
arch/s390/include/uapi/asm/kvm.h [moved from arch/s390/include/asm/kvm.h with 100% similarity]
arch/s390/include/uapi/asm/kvm_para.h [new file with mode: 0644]
arch/s390/include/uapi/asm/kvm_virtio.h [moved from arch/s390/include/asm/kvm_virtio.h with 100% similarity]
arch/s390/include/uapi/asm/mman.h [new file with mode: 0644]
arch/s390/include/uapi/asm/monwriter.h [moved from arch/s390/include/asm/monwriter.h with 100% similarity]
arch/s390/include/uapi/asm/msgbuf.h [moved from arch/s390/include/asm/msgbuf.h with 100% similarity]
arch/s390/include/uapi/asm/param.h [moved from arch/s390/include/asm/param.h with 100% similarity]
arch/s390/include/uapi/asm/poll.h [moved from arch/s390/include/asm/poll.h with 100% similarity]
arch/s390/include/uapi/asm/posix_types.h [moved from arch/s390/include/asm/posix_types.h with 100% similarity]
arch/s390/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/s390/include/uapi/asm/qeth.h [moved from arch/s390/include/asm/qeth.h with 100% similarity]
arch/s390/include/uapi/asm/resource.h [moved from arch/s390/include/asm/resource.h with 100% similarity]
arch/s390/include/uapi/asm/schid.h [new file with mode: 0644]
arch/s390/include/uapi/asm/sembuf.h [moved from arch/s390/include/asm/sembuf.h with 100% similarity]
arch/s390/include/uapi/asm/setup.h [new file with mode: 0644]
arch/s390/include/uapi/asm/shmbuf.h [moved from arch/s390/include/asm/shmbuf.h with 100% similarity]
arch/s390/include/uapi/asm/sigcontext.h [moved from arch/s390/include/asm/sigcontext.h with 100% similarity]
arch/s390/include/uapi/asm/siginfo.h [moved from arch/s390/include/asm/siginfo.h with 100% similarity]
arch/s390/include/uapi/asm/signal.h [new file with mode: 0644]
arch/s390/include/uapi/asm/socket.h [moved from arch/s390/include/asm/socket.h with 100% similarity]
arch/s390/include/uapi/asm/sockios.h [moved from arch/s390/include/asm/sockios.h with 100% similarity]
arch/s390/include/uapi/asm/stat.h [moved from arch/s390/include/asm/stat.h with 100% similarity]
arch/s390/include/uapi/asm/statfs.h [moved from arch/s390/include/asm/statfs.h with 100% similarity]
arch/s390/include/uapi/asm/swab.h [moved from arch/s390/include/asm/swab.h with 100% similarity]
arch/s390/include/uapi/asm/tape390.h [moved from arch/s390/include/asm/tape390.h with 100% similarity]
arch/s390/include/uapi/asm/termbits.h [moved from arch/s390/include/asm/termbits.h with 100% similarity]
arch/s390/include/uapi/asm/termios.h [new file with mode: 0644]
arch/s390/include/uapi/asm/types.h [new file with mode: 0644]
arch/s390/include/uapi/asm/ucontext.h [moved from arch/s390/include/asm/ucontext.h with 100% similarity]
arch/s390/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/s390/include/uapi/asm/vtoc.h [moved from arch/s390/include/asm/vtoc.h with 100% similarity]
arch/s390/include/uapi/asm/zcrypt.h [moved from arch/s390/include/asm/zcrypt.h with 100% similarity]
arch/s390/kernel/compat_linux.c
arch/s390/kernel/compat_linux.h
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/early.c
arch/s390/kernel/entry.S
arch/s390/kernel/entry.h
arch/s390/kernel/entry64.S
arch/s390/kernel/head.S
arch/s390/kernel/head31.S
arch/s390/kernel/head64.S
arch/s390/kernel/module.c
arch/s390/kernel/process.c
arch/s390/kernel/setup.c
arch/s390/kernel/time.c
arch/s390/mm/Makefile
arch/s390/mm/dump_pagetables.c [new file with mode: 0644]
arch/s390/mm/pageattr.c
arch/s390/mm/vmem.c
arch/score/include/asm/thread_info.h
arch/score/kernel/signal.c
arch/score/kernel/sys_score.c
arch/sh/include/asm/Kbuild
arch/sh/include/asm/exec.h [deleted file]
arch/sh/include/asm/thread_info.h
arch/sh/kernel/process_32.c
arch/sh/kernel/process_64.c
arch/sh/kernel/signal_32.c
arch/sh/kernel/signal_64.c
arch/sparc/include/asm/Kbuild
arch/sparc/include/asm/exec.h [deleted file]
arch/sparc/include/asm/fbio.h
arch/sparc/include/asm/ioctls.h
arch/sparc/include/asm/mman.h
arch/sparc/include/asm/psr.h
arch/sparc/include/asm/ptrace.h
arch/sparc/include/asm/setup.h
arch/sparc/include/asm/sigcontext.h
arch/sparc/include/asm/siginfo.h
arch/sparc/include/asm/signal.h
arch/sparc/include/asm/termbits.h
arch/sparc/include/asm/termios.h
arch/sparc/include/asm/thread_info_32.h
arch/sparc/include/asm/thread_info_64.h
arch/sparc/include/asm/traps.h
arch/sparc/include/asm/uaccess_64.h
arch/sparc/include/asm/unistd.h
arch/sparc/include/uapi/asm/Kbuild
arch/sparc/include/uapi/asm/apc.h [moved from arch/sparc/include/asm/apc.h with 100% similarity]
arch/sparc/include/uapi/asm/asi.h [moved from arch/sparc/include/asm/asi.h with 100% similarity]
arch/sparc/include/uapi/asm/auxvec.h [moved from arch/sparc/include/asm/auxvec.h with 100% similarity]
arch/sparc/include/uapi/asm/bitsperlong.h [moved from arch/sparc/include/asm/bitsperlong.h with 100% similarity]
arch/sparc/include/uapi/asm/byteorder.h [moved from arch/sparc/include/asm/byteorder.h with 100% similarity]
arch/sparc/include/uapi/asm/display7seg.h [moved from arch/sparc/include/asm/display7seg.h with 100% similarity]
arch/sparc/include/uapi/asm/envctrl.h [moved from arch/sparc/include/asm/envctrl.h with 100% similarity]
arch/sparc/include/uapi/asm/errno.h [moved from arch/sparc/include/asm/errno.h with 100% similarity]
arch/sparc/include/uapi/asm/fbio.h [new file with mode: 0644]
arch/sparc/include/uapi/asm/fcntl.h [moved from arch/sparc/include/asm/fcntl.h with 100% similarity]
arch/sparc/include/uapi/asm/ioctl.h [moved from arch/sparc/include/asm/ioctl.h with 100% similarity]
arch/sparc/include/uapi/asm/ioctls.h [new file with mode: 0644]
arch/sparc/include/uapi/asm/ipcbuf.h [moved from arch/sparc/include/asm/ipcbuf.h with 100% similarity]
arch/sparc/include/uapi/asm/jsflash.h [moved from arch/sparc/include/asm/jsflash.h with 100% similarity]
arch/sparc/include/uapi/asm/kvm_para.h [moved from arch/sparc/include/asm/kvm_para.h with 100% similarity]
arch/sparc/include/uapi/asm/mman.h [new file with mode: 0644]
arch/sparc/include/uapi/asm/msgbuf.h [moved from arch/sparc/include/asm/msgbuf.h with 100% similarity]
arch/sparc/include/uapi/asm/openpromio.h [moved from arch/sparc/include/asm/openpromio.h with 100% similarity]
arch/sparc/include/uapi/asm/param.h [moved from arch/sparc/include/asm/param.h with 100% similarity]
arch/sparc/include/uapi/asm/perfctr.h [moved from arch/sparc/include/asm/perfctr.h with 100% similarity]
arch/sparc/include/uapi/asm/poll.h [moved from arch/sparc/include/asm/poll.h with 100% similarity]
arch/sparc/include/uapi/asm/posix_types.h [moved from arch/sparc/include/asm/posix_types.h with 100% similarity]
arch/sparc/include/uapi/asm/psr.h [new file with mode: 0644]
arch/sparc/include/uapi/asm/psrcompat.h [moved from arch/sparc/include/asm/psrcompat.h with 100% similarity]
arch/sparc/include/uapi/asm/pstate.h [moved from arch/sparc/include/asm/pstate.h with 100% similarity]
arch/sparc/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/sparc/include/uapi/asm/resource.h [moved from arch/sparc/include/asm/resource.h with 100% similarity]
arch/sparc/include/uapi/asm/sembuf.h [moved from arch/sparc/include/asm/sembuf.h with 100% similarity]
arch/sparc/include/uapi/asm/setup.h [new file with mode: 0644]
arch/sparc/include/uapi/asm/shmbuf.h [moved from arch/sparc/include/asm/shmbuf.h with 100% similarity]
arch/sparc/include/uapi/asm/sigcontext.h [new file with mode: 0644]
arch/sparc/include/uapi/asm/siginfo.h [new file with mode: 0644]
arch/sparc/include/uapi/asm/signal.h [new file with mode: 0644]
arch/sparc/include/uapi/asm/socket.h [moved from arch/sparc/include/asm/socket.h with 100% similarity]
arch/sparc/include/uapi/asm/sockios.h [moved from arch/sparc/include/asm/sockios.h with 100% similarity]
arch/sparc/include/uapi/asm/stat.h [moved from arch/sparc/include/asm/stat.h with 100% similarity]
arch/sparc/include/uapi/asm/statfs.h [moved from arch/sparc/include/asm/statfs.h with 100% similarity]
arch/sparc/include/uapi/asm/swab.h [moved from arch/sparc/include/asm/swab.h with 100% similarity]
arch/sparc/include/uapi/asm/termbits.h [new file with mode: 0644]
arch/sparc/include/uapi/asm/termios.h [new file with mode: 0644]
arch/sparc/include/uapi/asm/traps.h [new file with mode: 0644]
arch/sparc/include/uapi/asm/types.h [moved from arch/sparc/include/asm/types.h with 100% similarity]
arch/sparc/include/uapi/asm/uctx.h [moved from arch/sparc/include/asm/uctx.h with 100% similarity]
arch/sparc/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/sparc/include/uapi/asm/utrap.h [moved from arch/sparc/include/asm/utrap.h with 100% similarity]
arch/sparc/include/uapi/asm/watchdog.h [moved from arch/sparc/include/asm/watchdog.h with 100% similarity]
arch/sparc/kernel/process_32.c
arch/sparc/kernel/process_64.c
arch/sparc/kernel/sys_sparc32.c
arch/sparc/kernel/syscalls.S
arch/sparc/kernel/traps_64.c
arch/sparc/mm/fault_64.c
arch/tile/include/arch/Kbuild
arch/tile/include/arch/spr_def.h
arch/tile/include/asm/Kbuild
arch/tile/include/asm/hardwall.h
arch/tile/include/asm/ptrace.h
arch/tile/include/asm/setup.h
arch/tile/include/asm/signal.h
arch/tile/include/asm/unistd.h
arch/tile/include/uapi/arch/Kbuild
arch/tile/include/uapi/arch/abi.h [moved from arch/tile/include/arch/abi.h with 100% similarity]
arch/tile/include/uapi/arch/chip.h [moved from arch/tile/include/arch/chip.h with 100% similarity]
arch/tile/include/uapi/arch/chip_tile64.h [moved from arch/tile/include/arch/chip_tile64.h with 100% similarity]
arch/tile/include/uapi/arch/chip_tilegx.h [moved from arch/tile/include/arch/chip_tilegx.h with 100% similarity]
arch/tile/include/uapi/arch/chip_tilepro.h [moved from arch/tile/include/arch/chip_tilepro.h with 100% similarity]
arch/tile/include/uapi/arch/icache.h [moved from arch/tile/include/arch/icache.h with 100% similarity]
arch/tile/include/uapi/arch/interrupts.h [moved from arch/tile/include/arch/interrupts.h with 100% similarity]
arch/tile/include/uapi/arch/interrupts_32.h [moved from arch/tile/include/arch/interrupts_32.h with 100% similarity]
arch/tile/include/uapi/arch/interrupts_64.h [moved from arch/tile/include/arch/interrupts_64.h with 100% similarity]
arch/tile/include/uapi/arch/opcode.h [moved from arch/tile/include/arch/opcode.h with 100% similarity]
arch/tile/include/uapi/arch/opcode_tilegx.h [moved from arch/tile/include/arch/opcode_tilegx.h with 100% similarity]
arch/tile/include/uapi/arch/opcode_tilepro.h [moved from arch/tile/include/arch/opcode_tilepro.h with 100% similarity]
arch/tile/include/uapi/arch/sim.h [moved from arch/tile/include/arch/sim.h with 100% similarity]
arch/tile/include/uapi/arch/sim_def.h [moved from arch/tile/include/arch/sim_def.h with 100% similarity]
arch/tile/include/uapi/arch/spr_def.h [new file with mode: 0644]
arch/tile/include/uapi/arch/spr_def_32.h [moved from arch/tile/include/arch/spr_def_32.h with 98% similarity]
arch/tile/include/uapi/arch/spr_def_64.h [moved from arch/tile/include/arch/spr_def_64.h with 98% similarity]
arch/tile/include/uapi/asm/Kbuild
arch/tile/include/uapi/asm/auxvec.h [moved from arch/tile/include/asm/auxvec.h with 100% similarity]
arch/tile/include/uapi/asm/bitsperlong.h [moved from arch/tile/include/asm/bitsperlong.h with 100% similarity]
arch/tile/include/uapi/asm/byteorder.h [moved from arch/tile/include/asm/byteorder.h with 100% similarity]
arch/tile/include/uapi/asm/cachectl.h [moved from arch/tile/include/asm/cachectl.h with 100% similarity]
arch/tile/include/uapi/asm/hardwall.h [new file with mode: 0644]
arch/tile/include/uapi/asm/kvm_para.h [moved from arch/tile/include/asm/kvm_para.h with 100% similarity]
arch/tile/include/uapi/asm/mman.h [moved from arch/tile/include/asm/mman.h with 100% similarity]
arch/tile/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/tile/include/uapi/asm/setup.h [moved from arch/tile/include/asm/exec.h with 81% similarity]
arch/tile/include/uapi/asm/sigcontext.h [moved from arch/tile/include/asm/sigcontext.h with 100% similarity]
arch/tile/include/uapi/asm/siginfo.h [moved from arch/tile/include/asm/siginfo.h with 100% similarity]
arch/tile/include/uapi/asm/signal.h [new file with mode: 0644]
arch/tile/include/uapi/asm/stat.h [moved from arch/tile/include/asm/stat.h with 100% similarity]
arch/tile/include/uapi/asm/swab.h [moved from arch/tile/include/asm/swab.h with 100% similarity]
arch/tile/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/tile/kernel/compat_signal.c
arch/tile/kernel/process.c
arch/tile/kernel/signal.c
arch/um/drivers/chan_kern.c
arch/um/drivers/chan_user.c
arch/um/drivers/chan_user.h
arch/um/drivers/cow_sys.h
arch/um/drivers/daemon.h
arch/um/drivers/daemon_kern.c
arch/um/drivers/daemon_user.c
arch/um/drivers/fd.c
arch/um/drivers/harddog_user.c
arch/um/drivers/hostaudio_kern.c
arch/um/drivers/line.c
arch/um/drivers/line.h
arch/um/drivers/mconsole.h
arch/um/drivers/mconsole_kern.c
arch/um/drivers/mconsole_kern.h
arch/um/drivers/mmapper_kern.c
arch/um/drivers/net_kern.c
arch/um/drivers/net_user.c
arch/um/drivers/null.c
arch/um/drivers/pcap_kern.c
arch/um/drivers/pcap_user.c
arch/um/drivers/pcap_user.h
arch/um/drivers/port_kern.c
arch/um/drivers/port_user.c
arch/um/drivers/pty.c
arch/um/drivers/random.c
arch/um/drivers/slip_common.c
arch/um/drivers/slip_kern.c
arch/um/drivers/slip_user.c
arch/um/drivers/slirp_kern.c
arch/um/drivers/slirp_user.c
arch/um/drivers/ssl.c
arch/um/drivers/stdio_console.c
arch/um/drivers/tty.c
arch/um/drivers/ubd_kern.c
arch/um/drivers/ubd_user.c
arch/um/drivers/umcast.h
arch/um/drivers/umcast_kern.c
arch/um/drivers/umcast_user.c
arch/um/drivers/vde_kern.c
arch/um/drivers/vde_user.c
arch/um/drivers/xterm.c
arch/um/drivers/xterm_kern.c
arch/um/include/asm/dma.h
arch/um/include/asm/mmu.h
arch/um/include/asm/page.h
arch/um/include/asm/pgtable.h
arch/um/include/asm/processor-generic.h
arch/um/include/asm/ptrace-generic.h
arch/um/include/asm/smp.h
arch/um/include/asm/sysrq.h [moved from arch/um/include/shared/sysrq.h with 100% similarity]
arch/um/include/asm/thread_info.h
arch/um/include/shared/arch.h
arch/um/include/shared/as-layout.h
arch/um/include/shared/irq_kern.h
arch/um/include/shared/irq_user.h
arch/um/include/shared/kern_util.h
arch/um/include/shared/longjmp.h
arch/um/include/shared/os.h
arch/um/include/shared/registers.h
arch/um/include/shared/skas/skas.h
arch/um/include/shared/skas_ptrace.h
arch/um/kernel/asm-offsets.c
arch/um/kernel/config.c.in
arch/um/kernel/dyn.lds.S
arch/um/kernel/early_printk.c
arch/um/kernel/exec.c
arch/um/kernel/gmon_syms.c
arch/um/kernel/gprof_syms.c
arch/um/kernel/initrd.c
arch/um/kernel/internal.h [deleted file]
arch/um/kernel/irq.c
arch/um/kernel/ksyms.c
arch/um/kernel/mem.c
arch/um/kernel/process.c
arch/um/kernel/reboot.c
arch/um/kernel/sigio.c
arch/um/kernel/signal.c
arch/um/kernel/skas/clone.c
arch/um/kernel/skas/mmu.c
arch/um/kernel/skas/process.c
arch/um/kernel/skas/syscall.c
arch/um/kernel/skas/uaccess.c
arch/um/kernel/smp.c
arch/um/kernel/syscall.c
arch/um/kernel/sysrq.c
arch/um/kernel/time.c
arch/um/kernel/tlb.c
arch/um/kernel/trap.c
arch/um/kernel/um_arch.c
arch/um/kernel/umid.c
arch/um/kernel/uml.lds.S
arch/um/os-Linux/aio.c
arch/um/os-Linux/drivers/etap.h
arch/um/os-Linux/drivers/ethertap_kern.c
arch/um/os-Linux/drivers/ethertap_user.c
arch/um/os-Linux/drivers/tuntap.h
arch/um/os-Linux/drivers/tuntap_kern.c
arch/um/os-Linux/drivers/tuntap_user.c
arch/um/os-Linux/elf_aux.c
arch/um/os-Linux/execvp.c
arch/um/os-Linux/file.c
arch/um/os-Linux/helper.c
arch/um/os-Linux/irq.c
arch/um/os-Linux/main.c
arch/um/os-Linux/mem.c
arch/um/os-Linux/process.c
arch/um/os-Linux/registers.c
arch/um/os-Linux/sigio.c
arch/um/os-Linux/signal.c
arch/um/os-Linux/skas/mem.c
arch/um/os-Linux/skas/process.c
arch/um/os-Linux/start_up.c
arch/um/os-Linux/time.c
arch/um/os-Linux/tty.c
arch/um/os-Linux/umid.c
arch/um/os-Linux/user_syms.c
arch/um/os-Linux/util.c
arch/um/sys-ppc/miscthings.c
arch/um/sys-ppc/ptrace.c
arch/um/sys-ppc/ptrace_user.c
arch/um/sys-ppc/shared/sysdep/ptrace.h
arch/um/sys-ppc/sigcontext.c
arch/um/sys-ppc/sysrq.c
arch/unicore32/Kconfig
arch/unicore32/include/asm/Kbuild
arch/unicore32/include/asm/exec.h [deleted file]
arch/unicore32/include/asm/thread_info.h
arch/unicore32/include/mach/regs-ost.h
arch/unicore32/kernel/Makefile
arch/unicore32/kernel/entry.S
arch/unicore32/kernel/pwm.c [deleted file]
arch/unicore32/kernel/signal.c
arch/unicore32/kernel/sys.c
arch/x86/Kconfig
arch/x86/ia32/ia32entry.S
arch/x86/ia32/sys_ia32.c
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/sys_ia32.h
arch/x86/include/asm/syscalls.h
arch/x86/include/asm/thread_info.h
arch/x86/include/asm/unistd.h
arch/x86/include/asm/vgtod.h
arch/x86/kernel/Makefile
arch/x86/kernel/asm-offsets.c
arch/x86/kernel/cpu/Makefile
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/cpu/perf_event_amd_ibs.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_knc.c [new file with mode: 0644]
arch/x86/kernel/cpu/perfctr-watchdog.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/kgdb.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/setup.c
arch/x86/kernel/signal.c
arch/x86/kernel/sys_i386_32.c [deleted file]
arch/x86/kernel/vm86_32.c
arch/x86/kernel/vsyscall_64.c
arch/x86/syscalls/syscall_32.tbl
arch/x86/um/Kconfig
arch/x86/um/asm/checksum.h
arch/x86/um/asm/checksum_32.h
arch/x86/um/asm/checksum_64.h
arch/x86/um/asm/elf.h
arch/x86/um/asm/ptrace.h
arch/x86/um/asm/ptrace_32.h [deleted file]
arch/x86/um/asm/ptrace_64.h [deleted file]
arch/x86/um/bugs_32.c
arch/x86/um/bugs_64.c
arch/x86/um/fault.c
arch/x86/um/ldt.c
arch/x86/um/mem_64.c
arch/x86/um/os-Linux/registers.c
arch/x86/um/os-Linux/task_size.c
arch/x86/um/os-Linux/tls.c
arch/x86/um/ptrace_32.c
arch/x86/um/ptrace_user.c
arch/x86/um/shared/sysdep/ptrace.h
arch/x86/um/shared/sysdep/stub.h
arch/x86/um/shared/sysdep/syscalls_32.h
arch/x86/um/signal.c
arch/x86/um/stub_32.S
arch/x86/um/stub_64.S
arch/x86/um/stub_segv.c
arch/x86/um/sys_call_table_32.c
arch/x86/um/sysrq_32.c
arch/x86/um/sysrq_64.c
arch/x86/um/tls_32.c
arch/x86/um/tls_64.c
arch/x86/vdso/vclock_gettime.c
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/xtensa/include/asm/Kbuild
arch/xtensa/include/asm/exec.h [deleted file]
arch/xtensa/include/asm/thread_info.h
arch/xtensa/kernel/process.c
arch/xtensa/kernel/signal.c
block/blk-core.c
block/blk-lib.c
block/blk-merge.c
block/blk-settings.c
block/blk-sysfs.c
block/blk-tag.c
block/blk.h
block/elevator.c
block/ioctl.c
drivers/block/drbd/drbd_main.c
drivers/block/osdblk.c
drivers/block/pktcdvd.c
drivers/char/ds1620.c
drivers/char/nwflash.c
drivers/char/raw.c
drivers/cpufreq/omap-cpufreq.c
drivers/dma/Kconfig
drivers/dma/Makefile
drivers/dma/amba-pl08x.c
drivers/dma/dw_dmac.c
drivers/dma/dw_dmac_regs.h
drivers/dma/edma.c [new file with mode: 0644]
drivers/dma/ioat/dma_v2.c
drivers/dma/ioat/pci.c
drivers/dma/mmp_pdma.c [new file with mode: 0644]
drivers/dma/mmp_tdma.c
drivers/dma/mxs-dma.c
drivers/dma/pl330.c
drivers/dma/sirf-dma.c
drivers/dma/ste_dma40.c
drivers/dma/tegra20-apb-dma.c
drivers/firewire/core-cdev.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/nouveau/core/core/parent.c
drivers/gpu/drm/nouveau/core/include/core/parent.h
drivers/gpu/drm/nouveau/core/include/subdev/timer.h
drivers/gpu/drm/nouveau/core/subdev/bios/base.c
drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c
drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
drivers/hwmon/acpi_power_meter.c
drivers/hwmon/adm9240.c
drivers/hwmon/adt7411.c
drivers/hwmon/adt7462.c
drivers/hwmon/adt7475.c
drivers/hwmon/applesmc.c
drivers/hwmon/asus_atk0110.c
drivers/hwmon/da9052-hwmon.c
drivers/hwmon/emc1403.c
drivers/hwmon/emc6w201.c
drivers/hwmon/hih6130.c
drivers/hwmon/i5k_amb.c
drivers/hwmon/ibmaem.c
drivers/hwmon/ibmpex.c
drivers/hwmon/ina2xx.c
drivers/hwmon/k8temp.c
drivers/hwmon/lineage-pem.c
drivers/hwmon/lm92.c
drivers/hwmon/lm93.c
drivers/hwmon/ltc4151.c
drivers/hwmon/ltc4215.c
drivers/hwmon/ltc4245.c
drivers/hwmon/ltc4261.c
drivers/hwmon/max16065.c
drivers/hwmon/max1619.c
drivers/hwmon/max6642.c
drivers/hwmon/pmbus/pmbus_core.c
drivers/hwmon/s3c-hwmon.c
drivers/hwmon/sht21.c
drivers/hwmon/smm665.c
drivers/hwmon/thmc50.c
drivers/hwmon/tmp102.c
drivers/hwmon/ultra45_env.c
drivers/hwmon/w83791d.c
drivers/hwmon/w83792d.c
drivers/hwmon/w83793.c
drivers/hwmon/w83795.c
drivers/hwmon/w83l786ng.c
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-at91.c
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-nomadik.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-rcar.c [new file with mode: 0644]
drivers/i2c/busses/i2c-s3c2410.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/netlink.c
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/input/evdev.c
drivers/input/input.c
drivers/input/joydev.c
drivers/input/keyboard/samsung-keypad.c
drivers/input/mousedev.c
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/isdn/i4l/isdn_ppp.c
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/leds/led-class.c
drivers/leds/led-core.c
drivers/leds/led-triggers.c
drivers/leds/leds-clevo-mail.c
drivers/leds/leds-gpio.c
drivers/leds/leds-lm3530.c
drivers/leds/leds-lm3556.c [deleted file]
drivers/leds/leds-lm355x.c [new file with mode: 0644]
drivers/leds/leds-lm3642.c [new file with mode: 0644]
drivers/leds/leds-lp5523.c
drivers/leds/leds-pca9633.c
drivers/leds/leds-wm8350.c
drivers/leds/leds.h
drivers/md/Kconfig
drivers/md/Makefile
drivers/md/dm-bio-prison.c [new file with mode: 0644]
drivers/md/dm-bio-prison.h [new file with mode: 0644]
drivers/md/dm-bufio.c
drivers/md/dm-crypt.c
drivers/md/dm-io.c
drivers/md/dm-mpath.c
drivers/md/dm-thin.c
drivers/md/dm-verity.c
drivers/md/dm.c
drivers/md/md.c
drivers/md/persistent-data/dm-space-map-common.c
drivers/md/raid0.c
drivers/media/dvb-core/dvb_frontend.c
drivers/media/dvb-core/dvb_frontend.h
drivers/media/dvb-frontends/a8293.c
drivers/media/dvb-frontends/af9013.c
drivers/media/dvb-frontends/af9033.c
drivers/media/dvb-frontends/bcm3510.c
drivers/media/dvb-frontends/cx24110.c
drivers/media/dvb-frontends/cxd2820r_core.c
drivers/media/dvb-frontends/drxd_hard.c
drivers/media/dvb-frontends/ds3000.c
drivers/media/dvb-frontends/dvb_dummy_fe.c
drivers/media/dvb-frontends/isl6405.c
drivers/media/dvb-frontends/isl6421.c
drivers/media/dvb-frontends/itd1000.c
drivers/media/dvb-frontends/lg2160.c
drivers/media/dvb-frontends/lnbp21.c
drivers/media/dvb-frontends/lnbp22.c
drivers/media/dvb-frontends/s5h1432.c
drivers/media/dvb-frontends/s921.c
drivers/media/dvb-frontends/si21xx.c
drivers/media/dvb-frontends/sp8870.c
drivers/media/dvb-frontends/sp887x.c
drivers/media/dvb-frontends/stb6100.c
drivers/media/dvb-frontends/stv0299.c
drivers/media/dvb-frontends/stv0900_core.c
drivers/media/dvb-frontends/tda665x.c
drivers/media/dvb-frontends/tda8083.c
drivers/media/i2c/cx25840/cx25840-core.c
drivers/media/i2c/m5mols/m5mols.h
drivers/media/i2c/m5mols/m5mols_capture.c
drivers/media/i2c/m5mols/m5mols_core.c
drivers/media/i2c/m5mols/m5mols_reg.h
drivers/media/i2c/mt9p031.c
drivers/media/i2c/mt9t001.c
drivers/media/i2c/mt9v032.c
drivers/media/i2c/soc_camera/ov2640.c
drivers/media/i2c/ths7303.c
drivers/media/i2c/tvp514x.c
drivers/media/pci/bt8xx/bttv-driver.c
drivers/media/pci/bt8xx/bttvp.h
drivers/media/pci/bt8xx/dst_ca.c
drivers/media/pci/cx23885/altera-ci.c
drivers/media/pci/cx23885/cimax2.c
drivers/media/pci/cx23885/cx23885-cards.c
drivers/media/pci/cx23885/cx23885-video.c
drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c
drivers/media/pci/cx25821/cx25821-video-upstream.c
drivers/media/pci/cx88/cx88-blackbird.c
drivers/media/pci/cx88/cx88-dvb.c
drivers/media/pci/cx88/cx88-mpeg.c
drivers/media/pci/cx88/cx88-tvaudio.c
drivers/media/pci/cx88/cx88-video.c
drivers/media/pci/saa7134/saa7134-video.c
drivers/media/platform/Kconfig
drivers/media/platform/davinci/vpbe.c
drivers/media/platform/davinci/vpbe_display.c
drivers/media/platform/davinci/vpbe_venc.c
drivers/media/platform/davinci/vpfe_capture.c
drivers/media/platform/davinci/vpif_capture.c
drivers/media/platform/davinci/vpif_capture.h
drivers/media/platform/davinci/vpif_display.c
drivers/media/platform/davinci/vpif_display.h
drivers/media/platform/exynos-gsc/gsc-regs.c
drivers/media/platform/fsl-viu.c
drivers/media/platform/mem2mem_testdev.c
drivers/media/platform/omap/omap_vout.c
drivers/media/platform/omap3isp/ispreg.h
drivers/media/platform/s5p-fimc/fimc-capture.c
drivers/media/platform/s5p-fimc/fimc-core.c
drivers/media/platform/s5p-fimc/fimc-core.h
drivers/media/platform/s5p-fimc/fimc-m2m.c
drivers/media/platform/s5p-fimc/fimc-reg.c
drivers/media/platform/s5p-fimc/fimc-reg.h
drivers/media/platform/s5p-fimc/mipi-csis.c
drivers/media/platform/s5p-g2d/g2d.c
drivers/media/platform/s5p-jpeg/jpeg-core.c
drivers/media/platform/s5p-mfc/Makefile
drivers/media/platform/s5p-mfc/regs-mfc-v6.h [new file with mode: 0644]
drivers/media/platform/s5p-mfc/regs-mfc.h
drivers/media/platform/s5p-mfc/s5p_mfc.c
drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c [new file with mode: 0644]
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h [new file with mode: 0644]
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c [new file with mode: 0644]
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h [new file with mode: 0644]
drivers/media/platform/s5p-mfc/s5p_mfc_common.h
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
drivers/media/platform/s5p-mfc/s5p_mfc_dec.h
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
drivers/media/platform/s5p-mfc/s5p_mfc_enc.h
drivers/media/platform/s5p-mfc/s5p_mfc_intr.c
drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c [new file with mode: 0644]
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h [moved from drivers/media/platform/s5p-mfc/s5p_mfc_shm.h with 76% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c [new file with mode: 0644]
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h [new file with mode: 0644]
drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
drivers/media/platform/s5p-mfc/s5p_mfc_shm.c [deleted file]
drivers/media/platform/soc_camera/mx2_camera.c
drivers/media/platform/soc_camera/soc_camera.c
drivers/media/radio/si470x/radio-si470x-i2c.c
drivers/media/radio/si470x/radio-si470x-usb.c
drivers/media/radio/si4713-i2c.c
drivers/media/rc/ene_ir.c
drivers/media/rc/iguanair.c
drivers/media/rc/ir-lirc-codec.c
drivers/media/rc/keymaps/rc-msi-digivox-ii.c
drivers/media/rc/nuvoton-cir.c
drivers/media/rc/redrat3.c
drivers/media/rc/winbond-cir.c
drivers/media/tuners/mt2063.c
drivers/media/tuners/mt2063.h
drivers/media/tuners/tda18271-common.c
drivers/media/usb/dvb-usb-v2/af9015.c
drivers/media/usb/dvb-usb-v2/af9035.c
drivers/media/usb/dvb-usb/a800.c
drivers/media/usb/dvb-usb/cinergyT2-core.c
drivers/media/usb/dvb-usb/dibusb-common.c
drivers/media/usb/dvb-usb/digitv.c
drivers/media/usb/dvb-usb/dtt200u.c
drivers/media/usb/dvb-usb/m920x.c
drivers/media/usb/dvb-usb/technisat-usb2.c
drivers/media/usb/em28xx/em28xx-cards.c
drivers/media/usb/em28xx/em28xx-dvb.c
drivers/media/usb/stk1160/stk1160-core.c
drivers/media/usb/stk1160/stk1160-v4l.c
drivers/media/usb/stk1160/stk1160.h
drivers/media/usb/uvc/uvc_queue.c
drivers/media/usb/uvc/uvc_video.c
drivers/media/usb/uvc/uvcvideo.h
drivers/media/v4l2-core/v4l2-ctrls.c
drivers/media/v4l2-core/v4l2-ioctl.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/mmc/core/core.c
drivers/mmc/core/debugfs.c
drivers/mmc/core/mmc.c
drivers/mmc/core/mmc_ops.c
drivers/mmc/core/sdio_bus.c
drivers/mmc/core/slot-gpio.c
drivers/mmc/host/Kconfig
drivers/mmc/host/Makefile
drivers/mmc/host/atmel-mci-regs.h
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/bfin_sdh.c
drivers/mmc/host/davinci_mmc.c
drivers/mmc/host/dw_mmc-exynos.c [new file with mode: 0644]
drivers/mmc/host/dw_mmc-pci.c
drivers/mmc/host/dw_mmc-pltfm.c
drivers/mmc/host/dw_mmc-pltfm.h [new file with mode: 0644]
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/dw_mmc.h
drivers/mmc/host/mmc_spi.c
drivers/mmc/host/mmci.c
drivers/mmc/host/mxcmmc.c
drivers/mmc/host/mxs-mmc.c
drivers/mmc/host/omap.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/pxamci.c
drivers/mmc/host/sdhci-dove.c
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci-pltfm.c
drivers/mmc/host/sdhci-pxav2.c
drivers/mmc/host/sdhci-pxav3.c
drivers/mmc/host/sdhci-s3c.c
drivers/mmc/host/sdhci-spear.c
drivers/mmc/host/sdhci-tegra.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sh_mmcif.c
drivers/mmc/host/via-sdmmc.c
drivers/mmc/host/vub300.c
drivers/mtd/Kconfig
drivers/mtd/Makefile
drivers/mtd/bcm47xxpart.c [new file with mode: 0644]
drivers/mtd/chips/Kconfig
drivers/mtd/chips/cfi_cmdset_0001.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/cmdlinepart.c
drivers/mtd/devices/Kconfig
drivers/mtd/devices/Makefile
drivers/mtd/devices/bcm47xxsflash.c [new file with mode: 0644]
drivers/mtd/devices/doc2001plus.c
drivers/mtd/devices/docg3.c
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/spear_smi.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/Makefile
drivers/mtd/maps/autcpu12-nvram.c
drivers/mtd/maps/pci.c
drivers/mtd/maps/physmap_of.c
drivers/mtd/maps/rbtx4939-flash.c
drivers/mtd/maps/uclinux.c
drivers/mtd/maps/wr_sbc82xx_flash.c [deleted file]
drivers/mtd/mtdchar.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdoops.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/ams-delta.c
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/atmel_nand_ecc.h
drivers/mtd/nand/au1550nd.c
drivers/mtd/nand/bcm_umi_bch.c [deleted file]
drivers/mtd/nand/bcm_umi_nand.c [deleted file]
drivers/mtd/nand/bf5xx_nand.c
drivers/mtd/nand/cafe_nand.c
drivers/mtd/nand/cmx270_nand.c
drivers/mtd/nand/davinci_nand.c
drivers/mtd/nand/denali.c
drivers/mtd/nand/diskonchip.c
drivers/mtd/nand/docg4.c
drivers/mtd/nand/fsl_elbc_nand.c
drivers/mtd/nand/fsl_ifc_nand.c
drivers/mtd/nand/gpio.c
drivers/mtd/nand/gpmi-nand/gpmi-lib.c
drivers/mtd/nand/gpmi-nand/gpmi-nand.c
drivers/mtd/nand/gpmi-nand/gpmi-nand.h
drivers/mtd/nand/gpmi-nand/gpmi-regs.h
drivers/mtd/nand/lpc32xx_mlc.c [new file with mode: 0644]
drivers/mtd/nand/lpc32xx_slc.c [new file with mode: 0644]
drivers/mtd/nand/mpc5121_nfc.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_bbt.c
drivers/mtd/nand/nand_bcm_umi.c [deleted file]
drivers/mtd/nand/nand_bcm_umi.h [deleted file]
drivers/mtd/nand/nand_ids.c
drivers/mtd/nand/nandsim.c
drivers/mtd/nand/ndfc.c
drivers/mtd/nand/nuc900_nand.c
drivers/mtd/nand/omap2.c
drivers/mtd/nand/orion_nand.c
drivers/mtd/nand/plat_nand.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/mtd/nand/r852.c
drivers/mtd/nand/s3c2410.c
drivers/mtd/nand/sh_flctl.c
drivers/mtd/nand/socrates_nand.c
drivers/mtd/nand/tmio_nand.c
drivers/mtd/nand/txx9ndfmc.c
drivers/mtd/nand/xway_nand.c [new file with mode: 0644]
drivers/mtd/sm_ftl.c
drivers/mtd/tests/Makefile
drivers/mtd/tests/mtd_nandbiterrs.c [new file with mode: 0644]
drivers/mtd/tests/mtd_nandecctest.c
drivers/mtd/tests/mtd_speedtest.c
drivers/mtd/tests/mtd_stresstest.c
drivers/net/ethernet/amd/amd8111e.c
drivers/net/ethernet/amd/au1000_eth.c
drivers/net/ethernet/calxeda/xgmac.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/dec/tulip/dmfe.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/gianfar.h
drivers/net/ethernet/freescale/ucc_geth.c
drivers/net/ethernet/freescale/ucc_geth.h
drivers/net/ethernet/intel/e1000e/e1000.h
drivers/net/ethernet/intel/e1000e/hw.h
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/jme.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/marvell/skge.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/natsemi/natsemi.c
drivers/net/ethernet/natsemi/xtsonic.c
drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/sfc/ptp.c
drivers/net/ethernet/sis/sis900.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/sun/niu.c
drivers/net/ethernet/sun/sungem.c
drivers/net/irda/irtty-sir.c
drivers/net/irda/mcs7780.c
drivers/net/irda/pxaficp_ir.c
drivers/net/irda/sa1100_ir.c
drivers/net/irda/sh_irda.c
drivers/net/irda/sh_sir.c
drivers/net/phy/mdio_bus.c
drivers/net/usb/cdc_eem.c
drivers/net/usb/kaweth.c
drivers/net/usb/mcs7830.c
drivers/net/usb/usbnet.c
drivers/net/vxlan.c
drivers/net/wan/farsync.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath9k/beacon.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/carl9170/carl9170.h
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/join.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/sta_cmdresp.c
drivers/net/wireless/mwifiex/sta_event.c
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/xen-netback/netback.c
drivers/pinctrl/pinctrl-nomadik-db8500.c
drivers/pinctrl/pinctrl-nomadik-db8540.c
drivers/pinctrl/pinctrl-nomadik.c
drivers/pinctrl/pinctrl-nomadik.h
drivers/power/avs/smartreflex.c
drivers/pwm/Kconfig
drivers/pwm/Makefile
drivers/pwm/core.c
drivers/pwm/pwm-ab8500.c [moved from drivers/misc/ab8500-pwm.c with 52% similarity]
drivers/pwm/pwm-bfin.c
drivers/pwm/pwm-imx.c
drivers/pwm/pwm-jz4740.c [new file with mode: 0644]
drivers/pwm/pwm-puv3.c [new file with mode: 0644]
drivers/pwm/pwm-pxa.c
drivers/pwm/pwm-samsung.c
drivers/pwm/pwm-tiecap.c
drivers/pwm/pwm-tiehrpwm.c
drivers/rapidio/rio-scan.c
drivers/rapidio/rio.c
drivers/rtc/Kconfig
drivers/s390/block/dcssblk.c
drivers/s390/crypto/zcrypt_pcixcc.c
drivers/scsi/bfa/bfa_core.c
drivers/scsi/bfa/bfa_defs.h
drivers/scsi/bfa/bfa_defs_svc.h
drivers/scsi/bfa/bfa_fc.h
drivers/scsi/bfa/bfa_fcbuild.c
drivers/scsi/bfa/bfa_fcpim.c
drivers/scsi/bfa/bfa_fcpim.h
drivers/scsi/bfa/bfa_fcs.c
drivers/scsi/bfa/bfa_fcs.h
drivers/scsi/bfa/bfa_fcs_lport.c
drivers/scsi/bfa/bfa_fcs_rport.c
drivers/scsi/bfa/bfa_ioc.c
drivers/scsi/bfa/bfa_ioc.h
drivers/scsi/bfa/bfa_ioc_ct.c
drivers/scsi/bfa/bfa_modules.h
drivers/scsi/bfa/bfa_port.c
drivers/scsi/bfa/bfa_port.h
drivers/scsi/bfa/bfa_svc.c
drivers/scsi/bfa/bfa_svc.h
drivers/scsi/bfa/bfad.c
drivers/scsi/bfa/bfad_bsg.c
drivers/scsi/bfa/bfad_bsg.h
drivers/scsi/bfa/bfad_drv.h
drivers/scsi/bfa/bfi.h
drivers/scsi/bfa/bfi_ms.h
drivers/scsi/bfa/bfi_reg.h
drivers/scsi/fcoe/fcoe.c
drivers/scsi/fcoe/fcoe.h
drivers/scsi/libfc/fc_fcp.c
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli4.h
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fp.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/megaraid/megaraid_sas_fusion.h
drivers/scsi/mvumi.c
drivers/scsi/mvumi.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_error.c
drivers/scsi/storvsc_drv.c
drivers/scsi/virtio_scsi.c
drivers/spi/Kconfig
drivers/spi/spi-davinci.c
drivers/staging/omapdrm/omap_drv.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target.h
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_core.h
drivers/target/iscsi/iscsi_target_erl0.c
drivers/target/iscsi/iscsi_target_erl1.c
drivers/target/iscsi/iscsi_target_erl1.h
drivers/target/iscsi/iscsi_target_erl2.c
drivers/target/iscsi/iscsi_target_erl2.h
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_nego.c
drivers/target/iscsi/iscsi_target_parameters.c
drivers/target/iscsi/iscsi_target_parameters.h
drivers/target/iscsi/iscsi_target_seq_pdu_list.c
drivers/target/iscsi/iscsi_target_tmr.c
drivers/target/iscsi/iscsi_target_tpg.c
drivers/target/iscsi/iscsi_target_tq.c
drivers/target/iscsi/iscsi_target_tq.h
drivers/target/iscsi/iscsi_target_util.c
drivers/target/iscsi/iscsi_target_util.h
drivers/target/loopback/tcm_loop.c
drivers/target/sbp/sbp_target.c
drivers/target/target_core_alua.c
drivers/target/target_core_configfs.c
drivers/target/target_core_device.c
drivers/target/target_core_fabric_configfs.c
drivers/target/target_core_fabric_lib.c
drivers/target/target_core_file.c
drivers/target/target_core_file.h
drivers/target/target_core_iblock.c
drivers/target/target_core_pr.c
drivers/target/target_core_pscsi.c
drivers/target/target_core_sbc.c
drivers/target/target_core_spc.c
drivers/target/target_core_stat.c
drivers/target/target_core_tpg.c
drivers/target/target_core_transport.c
drivers/target/tcm_fc/tfc_cmd.c
drivers/target/tcm_fc/tfc_conf.c
drivers/target/tcm_fc/tfc_io.c
drivers/target/tcm_fc/tfc_sess.c
drivers/tty/hvc/hvc_xen.c
drivers/tty/serial/kgdboc.c
drivers/tty/vt/vt.c
drivers/usb/class/cdc-acm.c
drivers/usb/gadget/tcm_usb_gadget.c
drivers/vfio/pci/vfio_pci.c
drivers/vfio/pci/vfio_pci_intrs.c
drivers/vhost/tcm_vhost.c
drivers/vhost/tcm_vhost.h
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/amifb.c
drivers/video/arcfb.c
drivers/video/atmel_lcdfb.c
drivers/video/backlight/pwm_bl.c
drivers/video/bf537-lq035.c
drivers/video/bf54x-lq043fb.c
drivers/video/bfin-lq035q1-fb.c
drivers/video/bfin-t350mcqb-fb.c
drivers/video/bw2.c
drivers/video/cg3.c
drivers/video/cobalt_lcdfb.c
drivers/video/console/font_mini_4x6.c
drivers/video/console/font_sun8x16.c
drivers/video/cyber2000fb.c
drivers/video/da8xx-fb.c
drivers/video/ep93xx-fb.c
drivers/video/exynos/exynos_dp_core.c
drivers/video/exynos/exynos_dp_core.h
drivers/video/exynos/exynos_dp_reg.c
drivers/video/exynos/exynos_dp_reg.h
drivers/video/exynos/exynos_mipi_dsi.c
drivers/video/exynos/exynos_mipi_dsi_common.c
drivers/video/fsl-diu-fb.c
drivers/video/gbefb.c
drivers/video/hpfb.c
drivers/video/imxfb.c
drivers/video/jz4740_fb.c
drivers/video/mb862xx/mb862xxfbdrv.c
drivers/video/mbx/mbxfb.c
drivers/video/msm/mddi.c
drivers/video/msm/mddi_client_nt35399.c
drivers/video/msm/mdp.c
drivers/video/msm/mdp_hw.h
drivers/video/mx3fb.c
drivers/video/nuc900fb.c
drivers/video/omap/hwa742.c
drivers/video/omap/lcd_palmte.c
drivers/video/omap/omapfb_main.c
drivers/video/omap2/displays/panel-acx565akm.c
drivers/video/omap2/displays/panel-generic-dpi.c
drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
drivers/video/omap2/displays/panel-n8x0.c
drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
drivers/video/omap2/displays/panel-picodlp.c
drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
drivers/video/omap2/displays/panel-taal.c
drivers/video/omap2/displays/panel-tfp410.c
drivers/video/omap2/displays/panel-tpo-td043mtea1.c
drivers/video/omap2/dss/Kconfig
drivers/video/omap2/dss/Makefile
drivers/video/omap2/dss/apply.c
drivers/video/omap2/dss/core.c
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/dispc.h
drivers/video/omap2/dss/display.c
drivers/video/omap2/dss/dpi.c
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/dss.h
drivers/video/omap2/dss/dss_features.c
drivers/video/omap2/dss/dss_features.h
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/dss/hdmi_panel.c
drivers/video/omap2/dss/manager-sysfs.c [new file with mode: 0644]
drivers/video/omap2/dss/manager.c
drivers/video/omap2/dss/output.c [new file with mode: 0644]
drivers/video/omap2/dss/overlay-sysfs.c [new file with mode: 0644]
drivers/video/omap2/dss/overlay.c
drivers/video/omap2/dss/rfbi.c
drivers/video/omap2/dss/sdi.c
drivers/video/omap2/dss/venc.c
drivers/video/omap2/dss/venc_panel.c [new file with mode: 0644]
drivers/video/omap2/omapfb/omapfb-ioctl.c
drivers/video/omap2/omapfb/omapfb-main.c
drivers/video/omap2/omapfb/omapfb.h
drivers/video/omap2/vram.c
drivers/video/pnx4008/Makefile [deleted file]
drivers/video/pnx4008/dum.h [deleted file]
drivers/video/pnx4008/fbcommon.h [deleted file]
drivers/video/pnx4008/pnxrgbfb.c [deleted file]
drivers/video/pnx4008/sdum.c [deleted file]
drivers/video/pnx4008/sdum.h [deleted file]
drivers/video/ps3fb.c
drivers/video/s3c-fb.c
drivers/video/s3c2410fb.c
drivers/video/savage/savagefb_driver.c
drivers/video/sis/initextlfb.c
drivers/video/sunxvr1000.c
drivers/video/sunxvr2500.c
drivers/video/sunxvr500.c
drivers/video/udlfb.c
drivers/video/uvesafb.c
drivers/video/vermilion/vermilion.c
drivers/video/via/via_clock.c
drivers/xen/xenbus/xenbus_xs.c
fs/9p/v9fs.c
fs/9p/vfs_inode.c
fs/autofs4/root.c
fs/binfmt_elf.c
fs/binfmt_elf_fdpic.c
fs/bio-integrity.c
fs/bio.c
fs/block_dev.c
fs/btrfs/backref.c
fs/btrfs/backref.h
fs/btrfs/btrfs_inode.h
fs/btrfs/check-integrity.c
fs/btrfs/compression.c
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/delayed-inode.c
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/extent_map.c
fs/btrfs/extent_map.h
fs/btrfs/file-item.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/hash.h
fs/btrfs/inode-item.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ordered-data.c
fs/btrfs/ordered-data.h
fs/btrfs/qgroup.c
fs/btrfs/relocation.c
fs/btrfs/root-tree.c
fs/btrfs/scrub.c
fs/btrfs/send.c
fs/btrfs/send.h
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/btrfs/tree-log.c
fs/btrfs/ulist.c
fs/btrfs/ulist.h
fs/btrfs/volumes.c
fs/btrfs/zlib.c
fs/ceph/export.c
fs/cifs/cifs_unicode.c
fs/cifs/connect.c
fs/cifs/transport.c
fs/compat.c
fs/exec.c
fs/exofs/ore.c
fs/exofs/super.c
fs/ext3/super.c
fs/fat/dir.c
fs/fat/fat.h
fs/fat/inode.c
fs/fat/namei_msdos.c
fs/fat/namei_vfat.c
fs/file.c
fs/file_table.c
fs/filesystems.c
fs/fs-writeback.c
fs/gfs2/export.c
fs/hostfs/hostfs.h
fs/hostfs/hostfs_kern.c
fs/hostfs/hostfs_user.c
fs/hpfs/super.c
fs/hppfs/hppfs.c
fs/internal.h
fs/isofs/export.c
fs/jffs2/super.c
fs/jffs2/wbuf.c
fs/lockd/mon.c
fs/lockd/netns.h
fs/lockd/svc.c
fs/locks.c
fs/namei.c
fs/namespace.c
fs/nfs/Kconfig
fs/nfs/blocklayout/blocklayout.c
fs/nfs/blocklayout/blocklayout.h
fs/nfs/blocklayout/blocklayoutdev.c
fs/nfs/blocklayout/extents.c
fs/nfs/callback.c
fs/nfs/callback.h
fs/nfs/callback_proc.c
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/getroot.c
fs/nfs/idmap.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/netns.h
fs/nfs/nfs4_fs.h
fs/nfs/nfs4client.c
fs/nfs/nfs4file.c
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4filelayout.h
fs/nfs/nfs4filelayoutdev.c
fs/nfs/nfs4namespace.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4sysctl.c
fs/nfs/nfs4xdr.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/pagelist.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/pnfs_dev.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/nfs2acl.c
fs/nfsd/nfs3proc.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4idmap.c
fs/nfsd/nfs4proc.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/open.c
fs/proc/base.c
fs/quota/quota.c
fs/reiserfs/inode.c
fs/super.c
fs/sysv/balloc.c
fs/sysv/ialloc.c
fs/sysv/inode.c
fs/sysv/super.c
fs/sysv/sysv.h
fs/ufs/balloc.c
fs/ufs/ialloc.c
fs/ufs/super.c
fs/ufs/ufs.h
fs/xattr.c
fs/xfs/xfs_export.c
include/linux/alarmtimer.h
include/linux/audit.h
include/linux/bcma/bcma_driver_chipcommon.h
include/linux/binfmts.h
include/linux/bio.h
include/linux/blk_types.h
include/linux/blkdev.h
include/linux/caif/Kbuild
include/linux/can/Kbuild
include/linux/clocksource.h
include/linux/compat.h
include/linux/compiler-gcc4.h
include/linux/console.h
include/linux/dvb/version.h
include/linux/dw_dmac.h
include/linux/edma.h [new file with mode: 0644]
include/linux/fs.h
include/linux/fsnotify.h
include/linux/i2c-algo-pca.h
include/linux/i2c-omap.h
include/linux/i2c/i2c-rcar.h [new file with mode: 0644]
include/linux/if_link.h
include/linux/if_vlan.h
include/linux/input.h
include/linux/isdn/Kbuild
include/linux/jiffies.h
include/linux/leds-lp5523.h
include/linux/leds.h
include/linux/lglock.h
include/linux/memcontrol.h
include/linux/mmc/Kbuild
include/linux/mmc/card.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/mtd/bbm.h
include/linux/mtd/lpc32xx_mlc.h [new file with mode: 0644]
include/linux/mtd/lpc32xx_slc.h [new file with mode: 0644]
include/linux/mtd/mtd.h
include/linux/mtd/nand.h
include/linux/mtd/sh_flctl.h
include/linux/netdevice.h
include/linux/netfilter/Kbuild
include/linux/netfilter/ipset/Kbuild
include/linux/netfilter/ipset/ip_set.h
include/linux/netfilter/ipset/ip_set_bitmap.h
include/linux/netfilter/ipset/ip_set_hash.h
include/linux/netfilter/ipset/ip_set_list.h
include/linux/netfilter/nf_conntrack_common.h
include/linux/netfilter/nf_conntrack_ftp.h
include/linux/netfilter/nf_conntrack_tcp.h
include/linux/netfilter/nfnetlink.h
include/linux/netfilter/nfnetlink_acct.h
include/linux/netfilter/x_tables.h
include/linux/netfilter/xt_hashlimit.h
include/linux/netfilter/xt_physdev.h
include/linux/netfilter_arp/Kbuild
include/linux/netfilter_arp/arp_tables.h
include/linux/netfilter_bridge/Kbuild
include/linux/netfilter_bridge/ebt_802_3.h
include/linux/netfilter_bridge/ebtables.h
include/linux/netfilter_ipv4/Kbuild
include/linux/netfilter_ipv4/ip_tables.h
include/linux/netfilter_ipv6/Kbuild
include/linux/netfilter_ipv6/ip6_tables.h
include/linux/netlink.h
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h
include/linux/nfs_xdr.h
include/linux/nfsd/Kbuild
include/linux/nfsd/debug.h
include/linux/nfsd/export.h
include/linux/nfsd/nfsfh.h
include/linux/nfsd/stats.h
include/linux/of_mdio.h
include/linux/pageblock-flags.h
include/linux/percpu-rwsem.h [new file with mode: 0644]
include/linux/perf_event.h
include/linux/platform_data/i2c-nomadik.h
include/linux/platform_data/leds-lm3556.h [deleted file]
include/linux/platform_data/leds-lm355x.h [new file with mode: 0644]
include/linux/platform_data/leds-lm3642.h [new file with mode: 0644]
include/linux/platform_data/leds-pca9633.h [new file with mode: 0644]
include/linux/platform_data/mipi-csis.h
include/linux/platform_data/mmp_dma.h [new file with mode: 0644]
include/linux/platform_data/pxa_sdhci.h
include/linux/ptrace.h
include/linux/pwm.h
include/linux/rio.h
include/linux/scatterlist.h
include/linux/sched.h
include/linux/security.h
include/linux/skbuff.h
include/linux/sunrpc/Kbuild
include/linux/sunrpc/clnt.h
include/linux/sunrpc/debug.h
include/linux/sunrpc/svc_xprt.h
include/linux/sunrpc/svcsock.h
include/linux/sunrpc/xprt.h
include/linux/syscalls.h
include/linux/tc_act/Kbuild
include/linux/tc_ematch/Kbuild
include/linux/timekeeper_internal.h [new file with mode: 0644]
include/linux/usb/usbnet.h
include/linux/v4l2-controls.h
include/linux/v4l2-mediabus.h
include/linux/videodev2.h
include/linux/virtio_scsi.h
include/linux/wimax/Kbuild
include/media/davinci/vpbe.h
include/media/davinci/vpbe_types.h
include/media/davinci/vpbe_venc.h
include/media/davinci/vpif_types.h
include/media/s5p_fimc.h
include/media/v4l2-ctrls.h
include/media/v4l2-subdev.h
include/mtd/Kbuild
include/net/flow.h
include/net/route.h
include/rdma/rdma_netlink.h
include/scsi/fc/fc_fcp.h
include/scsi/libfcoe.h
include/scsi/scsi_cmnd.h
include/target/target_core_backend.h
include/target/target_core_fabric.h
include/trace/events/btrfs.h
include/uapi/linux/caif/Kbuild
include/uapi/linux/caif/caif_socket.h [moved from include/linux/caif/caif_socket.h with 100% similarity]
include/uapi/linux/caif/if_caif.h [moved from include/linux/caif/if_caif.h with 100% similarity]
include/uapi/linux/can/Kbuild
include/uapi/linux/can/bcm.h [moved from include/linux/can/bcm.h with 100% similarity]
include/uapi/linux/can/error.h [moved from include/linux/can/error.h with 100% similarity]
include/uapi/linux/can/gw.h [moved from include/linux/can/gw.h with 100% similarity]
include/uapi/linux/can/netlink.h [moved from include/linux/can/netlink.h with 100% similarity]
include/uapi/linux/can/raw.h [moved from include/linux/can/raw.h with 100% similarity]
include/uapi/linux/isdn/Kbuild
include/uapi/linux/isdn/capicmd.h [moved from include/linux/isdn/capicmd.h with 100% similarity]
include/uapi/linux/mmc/Kbuild
include/uapi/linux/mmc/ioctl.h [moved from include/linux/mmc/ioctl.h with 100% similarity]
include/uapi/linux/netfilter/Kbuild
include/uapi/linux/netfilter/ipset/Kbuild
include/uapi/linux/netfilter/ipset/ip_set.h [new file with mode: 0644]
include/uapi/linux/netfilter/ipset/ip_set_bitmap.h [new file with mode: 0644]
include/uapi/linux/netfilter/ipset/ip_set_hash.h [new file with mode: 0644]
include/uapi/linux/netfilter/ipset/ip_set_list.h [new file with mode: 0644]
include/uapi/linux/netfilter/nf_conntrack_common.h [new file with mode: 0644]
include/uapi/linux/netfilter/nf_conntrack_ftp.h [new file with mode: 0644]
include/uapi/linux/netfilter/nf_conntrack_sctp.h [moved from include/linux/netfilter/nf_conntrack_sctp.h with 100% similarity]
include/uapi/linux/netfilter/nf_conntrack_tcp.h [new file with mode: 0644]
include/uapi/linux/netfilter/nf_conntrack_tuple_common.h [moved from include/linux/netfilter/nf_conntrack_tuple_common.h with 100% similarity]
include/uapi/linux/netfilter/nf_nat.h [moved from include/linux/netfilter/nf_nat.h with 100% similarity]
include/uapi/linux/netfilter/nfnetlink.h [new file with mode: 0644]
include/uapi/linux/netfilter/nfnetlink_acct.h [new file with mode: 0644]
include/uapi/linux/netfilter/nfnetlink_compat.h [moved from include/linux/netfilter/nfnetlink_compat.h with 100% similarity]
include/uapi/linux/netfilter/nfnetlink_conntrack.h [moved from include/linux/netfilter/nfnetlink_conntrack.h with 100% similarity]
include/uapi/linux/netfilter/nfnetlink_cthelper.h [moved from include/linux/netfilter/nfnetlink_cthelper.h with 100% similarity]
include/uapi/linux/netfilter/nfnetlink_cttimeout.h [moved from include/linux/netfilter/nfnetlink_cttimeout.h with 100% similarity]
include/uapi/linux/netfilter/nfnetlink_log.h [moved from include/linux/netfilter/nfnetlink_log.h with 100% similarity]
include/uapi/linux/netfilter/nfnetlink_queue.h [moved from include/linux/netfilter/nfnetlink_queue.h with 100% similarity]
include/uapi/linux/netfilter/x_tables.h [new file with mode: 0644]
include/uapi/linux/netfilter/xt_AUDIT.h [moved from include/linux/netfilter/xt_AUDIT.h with 100% similarity]
include/uapi/linux/netfilter/xt_CHECKSUM.h [moved from include/linux/netfilter/xt_CHECKSUM.h with 100% similarity]
include/uapi/linux/netfilter/xt_CLASSIFY.h [moved from include/linux/netfilter/xt_CLASSIFY.h with 100% similarity]
include/uapi/linux/netfilter/xt_CONNMARK.h [moved from include/linux/netfilter/xt_CONNMARK.h with 100% similarity]
include/uapi/linux/netfilter/xt_CONNSECMARK.h [moved from include/linux/netfilter/xt_CONNSECMARK.h with 100% similarity]
include/uapi/linux/netfilter/xt_CT.h [moved from include/linux/netfilter/xt_CT.h with 100% similarity]
include/uapi/linux/netfilter/xt_DSCP.h [moved from include/linux/netfilter/xt_DSCP.h with 100% similarity]
include/uapi/linux/netfilter/xt_IDLETIMER.h [moved from include/linux/netfilter/xt_IDLETIMER.h with 100% similarity]
include/uapi/linux/netfilter/xt_LED.h [moved from include/linux/netfilter/xt_LED.h with 100% similarity]
include/uapi/linux/netfilter/xt_LOG.h [moved from include/linux/netfilter/xt_LOG.h with 100% similarity]
include/uapi/linux/netfilter/xt_MARK.h [moved from include/linux/netfilter/xt_MARK.h with 100% similarity]
include/uapi/linux/netfilter/xt_NFLOG.h [moved from include/linux/netfilter/xt_NFLOG.h with 100% similarity]
include/uapi/linux/netfilter/xt_NFQUEUE.h [moved from include/linux/netfilter/xt_NFQUEUE.h with 100% similarity]
include/uapi/linux/netfilter/xt_RATEEST.h [moved from include/linux/netfilter/xt_RATEEST.h with 100% similarity]
include/uapi/linux/netfilter/xt_SECMARK.h [moved from include/linux/netfilter/xt_SECMARK.h with 100% similarity]
include/uapi/linux/netfilter/xt_TCPMSS.h [moved from include/linux/netfilter/xt_TCPMSS.h with 100% similarity]
include/uapi/linux/netfilter/xt_TCPOPTSTRIP.h [moved from include/linux/netfilter/xt_TCPOPTSTRIP.h with 100% similarity]
include/uapi/linux/netfilter/xt_TEE.h [moved from include/linux/netfilter/xt_TEE.h with 100% similarity]
include/uapi/linux/netfilter/xt_TPROXY.h [moved from include/linux/netfilter/xt_TPROXY.h with 100% similarity]
include/uapi/linux/netfilter/xt_addrtype.h [moved from include/linux/netfilter/xt_addrtype.h with 100% similarity]
include/uapi/linux/netfilter/xt_cluster.h [moved from include/linux/netfilter/xt_cluster.h with 100% similarity]
include/uapi/linux/netfilter/xt_comment.h [moved from include/linux/netfilter/xt_comment.h with 100% similarity]
include/uapi/linux/netfilter/xt_connbytes.h [moved from include/linux/netfilter/xt_connbytes.h with 100% similarity]
include/uapi/linux/netfilter/xt_connlimit.h [moved from include/linux/netfilter/xt_connlimit.h with 100% similarity]
include/uapi/linux/netfilter/xt_connmark.h [moved from include/linux/netfilter/xt_connmark.h with 100% similarity]
include/uapi/linux/netfilter/xt_conntrack.h [moved from include/linux/netfilter/xt_conntrack.h with 100% similarity]
include/uapi/linux/netfilter/xt_cpu.h [moved from include/linux/netfilter/xt_cpu.h with 100% similarity]
include/uapi/linux/netfilter/xt_dccp.h [moved from include/linux/netfilter/xt_dccp.h with 100% similarity]
include/uapi/linux/netfilter/xt_devgroup.h [moved from include/linux/netfilter/xt_devgroup.h with 100% similarity]
include/uapi/linux/netfilter/xt_dscp.h [moved from include/linux/netfilter/xt_dscp.h with 100% similarity]
include/uapi/linux/netfilter/xt_ecn.h [moved from include/linux/netfilter/xt_ecn.h with 100% similarity]
include/uapi/linux/netfilter/xt_esp.h [moved from include/linux/netfilter/xt_esp.h with 100% similarity]
include/uapi/linux/netfilter/xt_hashlimit.h [new file with mode: 0644]
include/uapi/linux/netfilter/xt_helper.h [moved from include/linux/netfilter/xt_helper.h with 100% similarity]
include/uapi/linux/netfilter/xt_iprange.h [moved from include/linux/netfilter/xt_iprange.h with 100% similarity]
include/uapi/linux/netfilter/xt_ipvs.h [moved from include/linux/netfilter/xt_ipvs.h with 100% similarity]
include/uapi/linux/netfilter/xt_length.h [moved from include/linux/netfilter/xt_length.h with 100% similarity]
include/uapi/linux/netfilter/xt_limit.h [moved from include/linux/netfilter/xt_limit.h with 100% similarity]
include/uapi/linux/netfilter/xt_mac.h [moved from include/linux/netfilter/xt_mac.h with 100% similarity]
include/uapi/linux/netfilter/xt_mark.h [moved from include/linux/netfilter/xt_mark.h with 100% similarity]
include/uapi/linux/netfilter/xt_multiport.h [moved from include/linux/netfilter/xt_multiport.h with 100% similarity]
include/uapi/linux/netfilter/xt_nfacct.h [moved from include/linux/netfilter/xt_nfacct.h with 100% similarity]
include/uapi/linux/netfilter/xt_osf.h [moved from include/linux/netfilter/xt_osf.h with 100% similarity]
include/uapi/linux/netfilter/xt_owner.h [moved from include/linux/netfilter/xt_owner.h with 100% similarity]
include/uapi/linux/netfilter/xt_physdev.h [new file with mode: 0644]
include/uapi/linux/netfilter/xt_pkttype.h [moved from include/linux/netfilter/xt_pkttype.h with 100% similarity]
include/uapi/linux/netfilter/xt_policy.h [moved from include/linux/netfilter/xt_policy.h with 100% similarity]
include/uapi/linux/netfilter/xt_quota.h [moved from include/linux/netfilter/xt_quota.h with 100% similarity]
include/uapi/linux/netfilter/xt_rateest.h [moved from include/linux/netfilter/xt_rateest.h with 100% similarity]
include/uapi/linux/netfilter/xt_realm.h [moved from include/linux/netfilter/xt_realm.h with 100% similarity]
include/uapi/linux/netfilter/xt_recent.h [moved from include/linux/netfilter/xt_recent.h with 100% similarity]
include/uapi/linux/netfilter/xt_sctp.h [moved from include/linux/netfilter/xt_sctp.h with 100% similarity]
include/uapi/linux/netfilter/xt_set.h [moved from include/linux/netfilter/xt_set.h with 100% similarity]
include/uapi/linux/netfilter/xt_socket.h [moved from include/linux/netfilter/xt_socket.h with 100% similarity]
include/uapi/linux/netfilter/xt_state.h [moved from include/linux/netfilter/xt_state.h with 100% similarity]
include/uapi/linux/netfilter/xt_statistic.h [moved from include/linux/netfilter/xt_statistic.h with 100% similarity]
include/uapi/linux/netfilter/xt_string.h [moved from include/linux/netfilter/xt_string.h with 100% similarity]
include/uapi/linux/netfilter/xt_tcpmss.h [moved from include/linux/netfilter/xt_tcpmss.h with 100% similarity]
include/uapi/linux/netfilter/xt_tcpudp.h [moved from include/linux/netfilter/xt_tcpudp.h with 100% similarity]
include/uapi/linux/netfilter/xt_time.h [moved from include/linux/netfilter/xt_time.h with 100% similarity]
include/uapi/linux/netfilter/xt_u32.h [moved from include/linux/netfilter/xt_u32.h with 100% similarity]
include/uapi/linux/netfilter_arp/Kbuild
include/uapi/linux/netfilter_arp/arp_tables.h [new file with mode: 0644]
include/uapi/linux/netfilter_arp/arpt_mangle.h [moved from include/linux/netfilter_arp/arpt_mangle.h with 100% similarity]
include/uapi/linux/netfilter_bridge/Kbuild
include/uapi/linux/netfilter_bridge/ebt_802_3.h [new file with mode: 0644]
include/uapi/linux/netfilter_bridge/ebt_among.h [moved from include/linux/netfilter_bridge/ebt_among.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebt_arp.h [moved from include/linux/netfilter_bridge/ebt_arp.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebt_arpreply.h [moved from include/linux/netfilter_bridge/ebt_arpreply.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebt_ip.h [moved from include/linux/netfilter_bridge/ebt_ip.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebt_ip6.h [moved from include/linux/netfilter_bridge/ebt_ip6.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebt_limit.h [moved from include/linux/netfilter_bridge/ebt_limit.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebt_log.h [moved from include/linux/netfilter_bridge/ebt_log.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebt_mark_m.h [moved from include/linux/netfilter_bridge/ebt_mark_m.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebt_mark_t.h [moved from include/linux/netfilter_bridge/ebt_mark_t.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebt_nat.h [moved from include/linux/netfilter_bridge/ebt_nat.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebt_nflog.h [moved from include/linux/netfilter_bridge/ebt_nflog.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebt_pkttype.h [moved from include/linux/netfilter_bridge/ebt_pkttype.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebt_redirect.h [moved from include/linux/netfilter_bridge/ebt_redirect.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebt_stp.h [moved from include/linux/netfilter_bridge/ebt_stp.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebt_ulog.h [moved from include/linux/netfilter_bridge/ebt_ulog.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebt_vlan.h [moved from include/linux/netfilter_bridge/ebt_vlan.h with 100% similarity]
include/uapi/linux/netfilter_bridge/ebtables.h [new file with mode: 0644]
include/uapi/linux/netfilter_ipv4/Kbuild
include/uapi/linux/netfilter_ipv4/ip_tables.h [new file with mode: 0644]
include/uapi/linux/netfilter_ipv4/ipt_CLUSTERIP.h [moved from include/linux/netfilter_ipv4/ipt_CLUSTERIP.h with 100% similarity]
include/uapi/linux/netfilter_ipv4/ipt_ECN.h [moved from include/linux/netfilter_ipv4/ipt_ECN.h with 100% similarity]
include/uapi/linux/netfilter_ipv4/ipt_LOG.h [moved from include/linux/netfilter_ipv4/ipt_LOG.h with 100% similarity]
include/uapi/linux/netfilter_ipv4/ipt_REJECT.h [moved from include/linux/netfilter_ipv4/ipt_REJECT.h with 100% similarity]
include/uapi/linux/netfilter_ipv4/ipt_TTL.h [moved from include/linux/netfilter_ipv4/ipt_TTL.h with 100% similarity]
include/uapi/linux/netfilter_ipv4/ipt_ULOG.h [moved from include/linux/netfilter_ipv4/ipt_ULOG.h with 100% similarity]
include/uapi/linux/netfilter_ipv4/ipt_ah.h [moved from include/linux/netfilter_ipv4/ipt_ah.h with 100% similarity]
include/uapi/linux/netfilter_ipv4/ipt_ecn.h [moved from include/linux/netfilter_ipv4/ipt_ecn.h with 100% similarity]
include/uapi/linux/netfilter_ipv4/ipt_ttl.h [moved from include/linux/netfilter_ipv4/ipt_ttl.h with 100% similarity]
include/uapi/linux/netfilter_ipv6/Kbuild
include/uapi/linux/netfilter_ipv6/ip6_tables.h [new file with mode: 0644]
include/uapi/linux/netfilter_ipv6/ip6t_HL.h [moved from include/linux/netfilter_ipv6/ip6t_HL.h with 100% similarity]
include/uapi/linux/netfilter_ipv6/ip6t_LOG.h [moved from include/linux/netfilter_ipv6/ip6t_LOG.h with 100% similarity]
include/uapi/linux/netfilter_ipv6/ip6t_NPT.h [moved from include/linux/netfilter_ipv6/ip6t_NPT.h with 100% similarity]
include/uapi/linux/netfilter_ipv6/ip6t_REJECT.h [moved from include/linux/netfilter_ipv6/ip6t_REJECT.h with 100% similarity]
include/uapi/linux/netfilter_ipv6/ip6t_ah.h [moved from include/linux/netfilter_ipv6/ip6t_ah.h with 100% similarity]
include/uapi/linux/netfilter_ipv6/ip6t_frag.h [moved from include/linux/netfilter_ipv6/ip6t_frag.h with 100% similarity]
include/uapi/linux/netfilter_ipv6/ip6t_hl.h [moved from include/linux/netfilter_ipv6/ip6t_hl.h with 100% similarity]
include/uapi/linux/netfilter_ipv6/ip6t_ipv6header.h [moved from include/linux/netfilter_ipv6/ip6t_ipv6header.h with 100% similarity]
include/uapi/linux/netfilter_ipv6/ip6t_mh.h [moved from include/linux/netfilter_ipv6/ip6t_mh.h with 100% similarity]
include/uapi/linux/netfilter_ipv6/ip6t_opts.h [moved from include/linux/netfilter_ipv6/ip6t_opts.h with 100% similarity]
include/uapi/linux/netfilter_ipv6/ip6t_rt.h [moved from include/linux/netfilter_ipv6/ip6t_rt.h with 100% similarity]
include/uapi/linux/nfsd/Kbuild
include/uapi/linux/nfsd/cld.h [moved from include/linux/nfsd/cld.h with 100% similarity]
include/uapi/linux/nfsd/debug.h [new file with mode: 0644]
include/uapi/linux/nfsd/export.h [new file with mode: 0644]
include/uapi/linux/nfsd/nfsfh.h [new file with mode: 0644]
include/uapi/linux/nfsd/stats.h [new file with mode: 0644]
include/uapi/linux/sunrpc/Kbuild
include/uapi/linux/sunrpc/debug.h [new file with mode: 0644]
include/uapi/linux/tc_act/Kbuild
include/uapi/linux/tc_act/tc_csum.h [moved from include/linux/tc_act/tc_csum.h with 100% similarity]
include/uapi/linux/tc_act/tc_gact.h [moved from include/linux/tc_act/tc_gact.h with 100% similarity]
include/uapi/linux/tc_act/tc_ipt.h [moved from include/linux/tc_act/tc_ipt.h with 100% similarity]
include/uapi/linux/tc_act/tc_mirred.h [moved from include/linux/tc_act/tc_mirred.h with 100% similarity]
include/uapi/linux/tc_act/tc_nat.h [moved from include/linux/tc_act/tc_nat.h with 100% similarity]
include/uapi/linux/tc_act/tc_pedit.h [moved from include/linux/tc_act/tc_pedit.h with 100% similarity]
include/uapi/linux/tc_act/tc_skbedit.h [moved from include/linux/tc_act/tc_skbedit.h with 100% similarity]
include/uapi/linux/tc_ematch/Kbuild
include/uapi/linux/tc_ematch/tc_em_cmp.h [moved from include/linux/tc_ematch/tc_em_cmp.h with 100% similarity]
include/uapi/linux/tc_ematch/tc_em_meta.h [moved from include/linux/tc_ematch/tc_em_meta.h with 100% similarity]
include/uapi/linux/tc_ematch/tc_em_nbyte.h [moved from include/linux/tc_ematch/tc_em_nbyte.h with 100% similarity]
include/uapi/linux/tc_ematch/tc_em_text.h [moved from include/linux/tc_ematch/tc_em_text.h with 100% similarity]
include/uapi/linux/wimax/Kbuild
include/uapi/linux/wimax/i2400m.h [moved from include/linux/wimax/i2400m.h with 100% similarity]
include/uapi/mtd/Kbuild
include/uapi/mtd/inftl-user.h [moved from include/mtd/inftl-user.h with 100% similarity]
include/uapi/mtd/mtd-abi.h [moved from include/mtd/mtd-abi.h with 100% similarity]
include/uapi/mtd/mtd-user.h [moved from include/mtd/mtd-user.h with 100% similarity]
include/uapi/mtd/nftl-user.h [moved from include/mtd/nftl-user.h with 100% similarity]
include/uapi/mtd/ubi-user.h [moved from include/mtd/ubi-user.h with 100% similarity]
include/uapi/xen/Kbuild
include/uapi/xen/evtchn.h [moved from include/xen/evtchn.h with 100% similarity]
include/uapi/xen/privcmd.h [moved from include/xen/privcmd.h with 100% similarity]
include/video/omapdss.h
include/video/samsung_fimd.h [moved from arch/arm/plat-samsung/include/plat/regs-fb.h with 73% similarity]
include/xen/Kbuild
include/xen/interface/hvm/hvm_op.h
init/Kconfig
init/do_mounts.c
init/do_mounts_initrd.c
init/main.c
ipc/mqueue.c
kernel/acct.c
kernel/audit.c
kernel/audit.h
kernel/audit_watch.c
kernel/auditfilter.c
kernel/auditsc.c
kernel/debug/debug_core.c
kernel/debug/kdb/kdb_bt.c
kernel/debug/kdb/kdb_io.c
kernel/debug/kdb/kdb_main.c
kernel/events/core.c
kernel/fork.c
kernel/irq/irqdomain.c
kernel/kmod.c
kernel/kthread.c
kernel/rcutree.c
kernel/rcutree.h
kernel/sched/core.c
kernel/time.c
kernel/time/Kconfig
kernel/time/alarmtimer.c
kernel/time/jiffies.c
kernel/time/tick-sched.c
kernel/time/timekeeping.c
kernel/timer.c
lib/kasprintf.c
lib/scatterlist.c
mm/backing-dev.c
mm/page-writeback.c
mm/shmem.c
mm/slab_common.c
mm/swapfile.c
net/8021q/vlan_core.c
net/9p/client.c
net/9p/trans_fd.c
net/bridge/br_netfilter.c
net/core/dev.c
net/core/neighbour.c
net/core/pktgen.c
net/core/skbuff.c
net/core/utils.c
net/ipv4/fib_frontend.c
net/ipv4/fib_semantics.c
net/ipv4/inet_connection_sock.c
net/ipv4/ip_forward.c
net/ipv4/ip_output.c
net/ipv4/ip_vti.c
net/ipv4/route.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_ipv4.c
net/ipv4/xfrm4_policy.c
net/ipv6/af_inet6.c
net/ipv6/tcp_ipv6.c
net/mac80211/mesh_sync.c
net/mac80211/status.c
net/mac80211/tx.c
net/netfilter/ipvs/ip_vs_xmit.c
net/netlink/af_netlink.c
net/rds/send.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/clnt.c
net/sunrpc/rpc_pipe.c
net/sunrpc/sched.c
net/sunrpc/svc_xprt.c
net/sunrpc/svcsock.c
net/sunrpc/xdr.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/svc_rdma_transport.c
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtsock.c
scripts/Makefile.modinst
scripts/Makefile.modpost
scripts/coccicheck
scripts/coccinelle/api/ptr_ret.cocci
scripts/coccinelle/tests/odd_ptr_err.cocci [new file with mode: 0644]
scripts/kconfig/Makefile
scripts/kconfig/conf.c
scripts/kconfig/expr.h
scripts/kconfig/lkc_proto.h
scripts/kconfig/lxdialog/dialog.h
scripts/kconfig/lxdialog/textbox.c
scripts/kconfig/lxdialog/util.c
scripts/kconfig/mconf.c
scripts/kconfig/menu.c
scripts/kconfig/nconf.c
scripts/kernel-doc
scripts/mod/modpost.c
scripts/package/buildtar
scripts/tags.sh
security/capability.c
security/security.c
security/selinux/hooks.c
security/smack/smack_lsm.c
security/tomoyo/common.h
security/tomoyo/mount.c
security/tomoyo/tomoyo.c
sound/oss/waveartist.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/usb/quirks-table.h
tools/perf/Makefile
tools/perf/bash_completion
tools/perf/builtin-buildid-cache.c
tools/perf/builtin-buildid-list.c
tools/perf/builtin-diff.c
tools/perf/builtin-evlist.c
tools/perf/builtin-help.c
tools/perf/builtin-inject.c
tools/perf/builtin-kmem.c
tools/perf/builtin-kvm.c
tools/perf/builtin-lock.c
tools/perf/builtin-probe.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/builtin-timechart.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/perf.c
tools/perf/ui/browsers/hists.c
tools/perf/ui/gtk/browser.c
tools/perf/ui/gtk/util.c
tools/perf/ui/helpline.h
tools/perf/ui/hist.c
tools/perf/ui/setup.c
tools/perf/ui/stdio/hist.c
tools/perf/util/annotate.h
tools/perf/util/cache.h
tools/perf/util/debug.c
tools/perf/util/debug.h
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/generate-cmdlist.sh
tools/perf/util/hist.c
tools/perf/util/hist.h
tools/perf/util/include/linux/rbtree.h
tools/perf/util/include/linux/rbtree_augmented.h [new file with mode: 0644]
tools/perf/util/map.c
tools/perf/util/parse-options.c
tools/perf/util/parse-options.h
tools/perf/util/path.c
tools/perf/util/perf_regs.h
tools/perf/util/sort.h
tools/perf/util/symbol.h
tools/perf/util/unwind.h
tools/perf/util/util.c
tools/testing/ktest/ktest.pl

index c1eb41cb9876083d3df79a6a995b692762acd21b..279da08f754192c07ba10c47eb0a4ea8e8c95892 100644 (file)
@@ -206,3 +206,17 @@ Description:
                when a discarded area is read the discard_zeroes_data
                parameter will be set to one. Otherwise it will be 0 and
                the result of reading a discarded area is undefined.
+
+What:          /sys/block/<disk>/queue/write_same_max_bytes
+Date:          January 2012
+Contact:       Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+               Some devices support a write same operation in which a
+               single data block can be written to a range of several
+               contiguous blocks on storage. This can be used to wipe
+               areas on disk or to initialize drives in a RAID
+               configuration. write_same_max_bytes indicates how many
+               bytes can be written in a single write same command. If
+               write_same_max_bytes is 0, write same is not supported
+               by the device.
+
index 469d09c02f6b7257e28160e63b56fba9ce50669a..50e2a80ea28ff496daf775dd9624934641dd2ea5 100644 (file)
@@ -9,19 +9,19 @@ Attributes:
                          this value will change the dev_loss_tmo for all
                          FCFs discovered by this controller.
 
-       lesb_link_fail:   Link Error Status Block (LESB) link failure count.
+       lesb/link_fail:   Link Error Status Block (LESB) link failure count.
 
-       lesb_vlink_fail:  Link Error Status Block (LESB) virtual link
+       lesb/vlink_fail:  Link Error Status Block (LESB) virtual link
                          failure count.
 
-       lesb_miss_fka:    Link Error Status Block (LESB) missed FCoE
+       lesb/miss_fka:    Link Error Status Block (LESB) missed FCoE
                          Initialization Protocol (FIP) Keep-Alives (FKA).
 
-       lesb_symb_err:    Link Error Status Block (LESB) symbolic error count.
+       lesb/symb_err:    Link Error Status Block (LESB) symbolic error count.
 
-       lesb_err_block:   Link Error Status Block (LESB) block error count.
+       lesb/err_block:   Link Error Status Block (LESB) block error count.
 
-       lesb_fcs_error:   Link Error Status Block (LESB) Fibre Channel
+       lesb/fcs_error:   Link Error Status Block (LESB) Fibre Channel
                          Serivces error count.
 
 Notes: ctlr_X (global increment starting at 0)
index c6ae4c9d0e0c6f0ae6f9661f916bb73e3d7fc89f..4fdf6b562d1cedb819c258f99820edfa4fafc7b3 100644 (file)
@@ -2582,6 +2582,10 @@ ioctls.</para>
         <listitem>
          <para>Support for frequency band enumeration: &VIDIOC-ENUM-FREQ-BANDS; ioctl.</para>
         </listitem>
+        <listitem>
+         <para>Vendor and device specific media bus pixel formats.
+           <xref linkend="v4l2-mbus-vendor-spec-fmts" />.</para>
+        </listitem>
       </itemizedlist>
     </section>
 
index 272a5f71850934e23a3c6e7ca7b5d8cc60b9784c..7fe5be1d3bbb14f58eb5ea60f32fa43b17bda894 100644 (file)
@@ -1586,7 +1586,6 @@ frame counter of the frame that is currently displayed (decoded). This value is
 the decoder is started.</entry>
              </row>
 
-
              <row><entry></entry></row>
              <row>
                <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE</constant>&nbsp;</entry>
@@ -2269,6 +2268,14 @@ encoder or editing process may produce.".
 Applicable to the MPEG1, MPEG2, MPEG4 encoders.</entry>
              </row>
 
+             <row><entry></entry></row>
+             <row id="v4l2-mpeg-video-vbv-delay">
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VBV_DELAY</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row><row><entry spanname="descr">Sets the initial delay in milliseconds for
+VBV buffer control.</entry>
+             </row>
+
              <row><entry></entry></row>
              <row>
                <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE</constant>&nbsp;</entry>
@@ -2334,6 +2341,265 @@ Applicable to the MPEG4 decoder.</entry>
              </row><row><entry spanname="descr">vop_time_increment value for MPEG4. Applicable to the MPEG4 encoder.</entry>
              </row>
 
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">Enable generation of frame packing supplemental enhancement information in the encoded bitstream.
+The frame packing SEI message contains the arrangement of L and R planes for 3D viewing. Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">Sets current frame as frame0 in frame packing SEI.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row id="v4l2-mpeg-video-h264-sei-fp-arrangement-type">
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_h264_sei_fp_arrangement_type</entry>
+             </row>
+             <row><entry spanname="descr">Frame packing arrangement type for H264 SEI.
+Applicable to the H264 encoder.
+Possible values are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_CHEKERBOARD</constant>&nbsp;</entry>
+                     <entry>Pixels are alternatively from L and R.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_COLUMN</constant>&nbsp;</entry>
+                     <entry>L and R are interlaced by column.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_ROW</constant>&nbsp;</entry>
+                     <entry>L and R are interlaced by row.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE</constant>&nbsp;</entry>
+                     <entry>L is on the left, R on the right.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TOP_BOTTOM</constant>&nbsp;</entry>
+                     <entry>L is on top, R on bottom.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TEMPORAL</constant>&nbsp;</entry>
+                     <entry>One view per frame.</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">Enables flexible macroblock ordering in the encoded bitstream. It is a technique
+used for restructuring the ordering of macroblocks in pictures. Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row id="v4l2-mpeg-video-h264-fmo-map-type">
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_h264_fmo_map_type</entry>
+             </row>
+             <row><entry spanname="descr">When using FMO, the map type divides the image in different scan patterns of macroblocks.
+Applicable to the H264 encoder.
+Possible values are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES</constant>&nbsp;</entry>
+                     <entry>Slices are interleaved one after other with macroblocks in run length order.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES</constant>&nbsp;</entry>
+                     <entry>Scatters the macroblocks based on a mathematical function known to both encoder and decoder.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_FOREGROUND_WITH_LEFT_OVER</constant>&nbsp;</entry>
+                     <entry>Macroblocks arranged in rectangular areas or regions of interest.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_BOX_OUT</constant>&nbsp;</entry>
+                     <entry>Slice groups grow in a cyclic way from centre to outwards.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN</constant>&nbsp;</entry>
+                     <entry>Slice groups grow in raster scan pattern from left to right.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN</constant>&nbsp;</entry>
+                     <entry>Slice groups grow in wipe scan pattern from top to bottom.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_EXPLICIT</constant>&nbsp;</entry>
+                     <entry>User defined map type.</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Number of slice groups in FMO.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row id="v4l2-mpeg-video-h264-fmo-change-direction">
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_h264_fmo_change_dir</entry>
+             </row>
+             <row><entry spanname="descr">Specifies a direction of the slice group change for raster and wipe maps.
+Applicable to the H264 encoder.
+Possible values are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT</constant>&nbsp;</entry>
+                     <entry>Raster scan or wipe right.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_LEFT</constant>&nbsp;</entry>
+                     <entry>Reverse raster scan or wipe left.</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Specifies the size of the first slice group for raster and wipe map.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Specifies the number of consecutive macroblocks for the interleaved map.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_ASO</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">Enables arbitrary slice ordering in encoded bitstream.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row><row><entry spanname="descr">Specifies the slice order in ASO. Applicable to the H264 encoder.
+The supplied 32-bit integer is interpreted as follows (bit
+0 = least significant bit):</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry>Bit 0:15</entry>
+                     <entry>Slice ID</entry>
+                   </row>
+                   <row>
+                     <entry>Bit 16:32</entry>
+                     <entry>Slice position or order</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING</constant>&nbsp;</entry>
+               <entry>boolean</entry>
+             </row>
+             <row><entry spanname="descr">Enables H264 hierarchical coding.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row id="v4l2-mpeg-video-h264-hierarchical-coding-type">
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE</constant>&nbsp;</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_h264_hierarchical_coding_type</entry>
+             </row>
+             <row><entry spanname="descr">Specifies the hierarchical coding type.
+Applicable to the H264 encoder.
+Possible values are:</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B</constant>&nbsp;</entry>
+                     <entry>Hierarchical B coding.</entry>
+                   </row>
+                   <row>
+                     <entry><constant>V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P</constant>&nbsp;</entry>
+                     <entry>Hierarchical P coding.</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row>
+             <row><entry spanname="descr">Specifies the number of hierarchical coding layers.
+Applicable to the H264 encoder.</entry>
+             </row>
+
+             <row><entry></entry></row>
+             <row>
+               <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP</constant>&nbsp;</entry>
+               <entry>integer</entry>
+             </row><row><entry spanname="descr">Specifies a user defined QP for each layer. Applicable to the H264 encoder.
+The supplied 32-bit integer is interpreted as follows (bit
+0 = least significant bit):</entry>
+             </row>
+             <row>
+               <entrytbl spanname="descr" cols="2">
+                 <tbody valign="top">
+                   <row>
+                     <entry>Bit 0:15</entry>
+                     <entry>QP value</entry>
+                   </row>
+                   <row>
+                     <entry>Bit 16:32</entry>
+                     <entry>Layer number</entry>
+                   </row>
+                 </tbody>
+               </entrytbl>
+             </row>
+
            </tbody>
          </tgroup>
        </table>
@@ -4267,6 +4533,16 @@ interface and may change in the future.</para>
            pixels / second.
            </entry>
          </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_TEST_PATTERN</constant></entry>
+           <entry>menu</entry>
+         </row>
+         <row id="v4l2-test-pattern">
+           <entry spanname="descr"> Some capture/display/sensor devices have
+           the capability to generate test pattern images. These hardware
+           specific test patterns can be used to test if a device is working
+           properly.</entry>
+         </row>
          <row><entry></entry></row>
        </tbody>
       </tgroup>
index 97f785add841c602d179a2b131060994deeaa26d..b5d1cbdc558bdfa5cfbd6e451425dabc5456b0ce 100644 (file)
@@ -677,8 +677,10 @@ memory, set by the application. See <xref linkend="userp" /> for details.
            <entry><structfield>length</structfield></entry>
            <entry></entry>
            <entry>Size of the buffer (not the payload) in bytes for the
-           single-planar API. For the multi-planar API should contain the
-           number of elements in the <structfield>planes</structfield> array.
+           single-planar API. For the multi-planar API the application sets
+           this to the number of elements in the <structfield>planes</structfield>
+           array. The driver will fill in the actual number of valid elements in
+           that array.
            </entry>
          </row>
          <row>
index 5274c24d11e0a94ce55a05d166580f5cda50196f..a990b34d911a123f775f20001f9e9629947276b2 100644 (file)
@@ -1,11 +1,13 @@
-    <refentry id="V4L2-PIX-FMT-NV12M">
+    <refentry>
       <refmeta>
-       <refentrytitle>V4L2_PIX_FMT_NV12M ('NM12')</refentrytitle>
+       <refentrytitle>V4L2_PIX_FMT_NV12M ('NM12'), V4L2_PIX_FMT_NV21M ('NM21'), V4L2_PIX_FMT_NV12MT_16X16</refentrytitle>
        &manvol;
       </refmeta>
       <refnamediv>
-       <refname> <constant>V4L2_PIX_FMT_NV12M</constant></refname>
-       <refpurpose>Variation of <constant>V4L2_PIX_FMT_NV12</constant> with planes
+       <refname id="V4L2-PIX-FMT-NV12M"><constant>V4L2_PIX_FMT_NV12M</constant></refname>
+       <refname id="V4L2-PIX-FMT-NV21M"><constant>V4L2_PIX_FMT_NV21M</constant></refname>
+       <refname id="V4L2-PIX-FMT-NV12MT_16X16"><constant>V4L2_PIX_FMT_NV12MT_16X16</constant></refname>
+       <refpurpose>Variation of <constant>V4L2_PIX_FMT_NV12</constant> and <constant>V4L2_PIX_FMT_NV21</constant> with planes
          non contiguous in memory. </refpurpose>
       </refnamediv>
       <refsect1>
@@ -22,7 +24,12 @@ The CbCr plane is the same width, in bytes, as the Y plane (and of the image),
 but is half as tall in pixels. Each CbCr pair belongs to four pixels. For example,
 Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
 Y'<subscript>00</subscript>, Y'<subscript>01</subscript>,
-Y'<subscript>10</subscript>, Y'<subscript>11</subscript>. </para>
+Y'<subscript>10</subscript>, Y'<subscript>11</subscript>.
+<constant>V4L2_PIX_FMT_NV12MT_16X16</constant> is the tiled version of
+<constant>V4L2_PIX_FMT_NV12M</constant> with 16x16 macroblock tiles. Here pixels
+are arranged in 16x16 2D tiles and tiles are arranged in linear order in memory.
+<constant>V4L2_PIX_FMT_NV21M</constant> is the same as <constant>V4L2_PIX_FMT_NV12M</constant>
+except the Cb and Cr bytes are swapped, the CrCb plane starts with a Cr byte.</para>
 
        <para><constant>V4L2_PIX_FMT_NV12M</constant> is intended to be
 used only in drivers and applications that support the multi-planar API,
index 1ddbfabe31953b34fa8f51a8dc7c515daca39a06..bf94f417592cac290670f4e65ace3a54fc1eb173 100644 (file)
@@ -758,6 +758,11 @@ extended control <constant>V4L2_CID_MPEG_STREAM_TYPE</constant>, see
                <entry>'AVC1'</entry>
                <entry>H264 video elementary stream without start codes.</entry>
          </row>
+         <row id="V4L2-PIX-FMT-H264-MVC">
+               <entry><constant>V4L2_PIX_FMT_H264_MVC</constant></entry>
+               <entry>'MVC'</entry>
+               <entry>H264 MVC video elementary stream.</entry>
+         </row>
          <row id="V4L2-PIX-FMT-H263">
                <entry><constant>V4L2_PIX_FMT_H263</constant></entry>
                <entry>'H263'</entry>
@@ -793,6 +798,11 @@ extended control <constant>V4L2_CID_MPEG_STREAM_TYPE</constant>, see
                <entry>'VC1L'</entry>
                <entry>VC1, SMPTE 421M Annex L compliant stream.</entry>
          </row>
+         <row id="V4L2-PIX-FMT-VP8">
+               <entry><constant>V4L2_PIX_FMT_VP8</constant></entry>
+               <entry>'VP8'</entry>
+               <entry>VP8 video elementary stream.</entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
@@ -996,6 +1006,34 @@ the other bits are set to 0.</entry>
            <entry>Old 6-bit greyscale format. Only the most significant 6 bits of each byte are used,
 the other bits are set to 0.</entry>
          </row>
+         <row id="V4L2-PIX-FMT-S5C-UYVY-JPG">
+           <entry><constant>V4L2_PIX_FMT_S5C_UYVY_JPG</constant></entry>
+           <entry>'S5CI'</entry>
+           <entry>Two-planar format used by Samsung S5C73MX cameras. The
+first plane contains interleaved JPEG and UYVY image data, followed by meta data
+in form of an array of offsets to the UYVY data blocks. The actual pointer array
+follows immediately the interleaved JPEG/UYVY data, the number of entries in
+this array equals the height of the UYVY image. Each entry is a 4-byte unsigned
+integer in big endian order and it's an offset to a single pixel line of the
+UYVY image. The first plane can start either with JPEG or UYVY data chunk. The
+size of a single UYVY block equals the UYVY image's width multiplied by 2. The
+size of a JPEG chunk depends on the image and can vary with each line.
+<para>The second plane, at an offset of 4084 bytes, contains a 4-byte offset to
+the pointer array in the first plane. This offset is followed by a 4-byte value
+indicating size of the pointer array. All numbers in the second plane are also
+in big endian order. Remaining data in the second plane is undefined. The
+information in the second plane allows to easily find location of the pointer
+array, which can be different for each frame. The size of the pointer array is
+constant for given UYVY image height.</para>
+<para>In order to extract UYVY and JPEG frames an application can initially set
+a data pointer to the start of first plane and then add an offset from the first
+entry of the pointers table. Such a pointer indicates start of an UYVY image
+pixel line. Whole UYVY line can be copied to a separate buffer. These steps
+should be repeated for each line, i.e. the number of entries in the pointer
+array. Anything what's in between the UYVY lines is JPEG data and should be
+concatenated to form the JPEG stream. </para>
+</entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
index 49c532ebbbbefe3a6aac004dd4192936ec14e880..a0a936455faef1c68d59f5997b8697b7ad1e2d65 100644 (file)
        </tgroup>
       </table>
     </section>
+
+    <section id="v4l2-mbus-vendor-spec-fmts">
+      <title>Vendor and Device Specific Formats</title>
+
+      <note>
+       <title>Experimental</title>
+       <para>This is an <link linkend="experimental">experimental</link>
+interface and may change in the future.</para>
+      </note>
+
+      <para>This section lists complex data formats that are either vendor or
+       device specific.
+      </para>
+
+      <para>The following table lists the existing vendor and device specific
+       formats.</para>
+
+      <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-vendor-specific">
+       <title>Vendor and device specific formats</title>
+       <tgroup cols="3">
+         <colspec colname="id" align="left" />
+         <colspec colname="code" align="left"/>
+         <colspec colname="remarks" align="left"/>
+         <thead>
+           <row>
+             <entry>Identifier</entry>
+             <entry>Code</entry>
+             <entry>Comments</entry>
+           </row>
+         </thead>
+         <tbody valign="top">
+           <row id="V4L2-MBUS-FMT-S5C-UYVY-JPEG-1X8">
+             <entry>V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8</entry>
+             <entry>0x5001</entry>
+             <entry>
+               Interleaved raw UYVY and JPEG image format with embedded
+               meta-data used by Samsung S3C73MX camera sensors.
+             </entry>
+           </row>
+         </tbody>
+       </tgroup>
+      </table>
+    </section>
+
   </section>
 </section>
index 6a821a65a5aec9ce1e196261c5149b666f2e4c2e..2d37abefce13e90144941af12cc2baa71f78a700 100644 (file)
@@ -121,8 +121,7 @@ remaining fields or returns an error code. The driver may also set
 field. It indicates a non-critical (recoverable) streaming error. In such case
 the application may continue as normal, but should be aware that data in the
 dequeued buffer might be corrupted. When using the multi-planar API, the
-planes array does not have to be passed; the <structfield>m.planes</structfield>
-member must be set to NULL in that case.</para>
+planes array must be passed in as well.</para>
 
     <para>By default <constant>VIDIOC_DQBUF</constant> blocks when no
 buffer is in the outgoing queue. When the
index 6e414d7b6df759f83f45ad34256c5ace012a6543..a597155c052d723b7b5c5867f67c564dd2eacebe 100644 (file)
@@ -48,8 +48,8 @@
   <refsect1>
     <title>Description</title>
 
-    <para>This ioctl is part of the <link linkend="mmap">memory
-mapping</link> I/O method. It can be used to query the status of a
+    <para>This ioctl is part of the <link linkend="mmap">streaming
+</link> I/O method. It can be used to query the status of a
 buffer at any time after buffers have been allocated with the
 &VIDIOC-REQBUFS; ioctl.</para>
 
@@ -71,6 +71,7 @@ the structure.</para>
 
     <para>In the <structfield>flags</structfield> field the
 <constant>V4L2_BUF_FLAG_MAPPED</constant>,
+<constant>V4L2_BUF_FLAG_PREPARED</constant>,
 <constant>V4L2_BUF_FLAG_QUEUED</constant> and
 <constant>V4L2_BUF_FLAG_DONE</constant> flags will be valid. The
 <structfield>memory</structfield> field will be set to the current
@@ -79,8 +80,10 @@ contains the offset of the buffer from the start of the device memory,
 the <structfield>length</structfield> field its size. For the multi-planar API,
 fields <structfield>m.mem_offset</structfield> and
 <structfield>length</structfield> in the <structfield>m.planes</structfield>
-array elements will be used instead. The driver may or may not set the remaining
-fields and flags, they are meaningless in this context.</para>
+array elements will be used instead and the <structfield>length</structfield>
+field of &v4l2-buffer; is set to the number of filled-in array elements.
+The driver may or may not set the remaining fields and flags, they are
+meaningless in this context.</para>
 
     <para>The <structname>v4l2_buffer</structname> structure is
     specified in <xref linkend="buffer" />.</para>
index e0aedb7a782718c445d48f8f42ee9e14a3d5a33a..fe122d6e686f50e873d637d3f08929d042df4335 100644 (file)
@@ -1216,8 +1216,6 @@ in this page</entry>
 #define        NAND_BBT_LASTBLOCK      0x00000010
 /* The bbt is at the given page, else we must scan for the bbt */
 #define NAND_BBT_ABSPAGE       0x00000020
-/* The bbt is at the given page, else we must scan for the bbt */
-#define NAND_BBT_SEARCH                0x00000040
 /* bbt is stored per chip on multichip devices */
 #define NAND_BBT_PERCHIP       0x00000080
 /* bbt has a version counter at offset veroffs */
index a341d87d276eb1bf3904aec38896f87174b36561..0c1f475fdf36e140d28bcdc26d880546f8a8bdc4 100644 (file)
@@ -154,13 +154,33 @@ In either case, the following conditions must be met:
 
 - CPU mode
   All forms of interrupts must be disabled (IRQs and FIQs)
-  The CPU must be in SVC mode.  (A special exception exists for Angel)
+
+  For CPUs which do not include the ARM virtualization extensions, the
+  CPU must be in SVC mode.  (A special exception exists for Angel)
+
+  CPUs which include support for the virtualization extensions can be
+  entered in HYP mode in order to enable the kernel to make full use of
+  these extensions.  This is the recommended boot method for such CPUs,
+  unless the virtualisations are already in use by a pre-installed
+  hypervisor.
+
+  If the kernel is not entered in HYP mode for any reason, it must be
+  entered in SVC mode.
 
 - Caches, MMUs
   The MMU must be off.
   Instruction cache may be on or off.
   Data cache must be off.
 
+  If the kernel is entered in HYP mode, the above requirements apply to
+  the HYP mode configuration in addition to the ordinary PL1 (privileged
+  kernel modes) configuration.  In addition, all traps into the
+  hypervisor must be disabled, and PL1 access must be granted for all
+  peripherals and CPU resources for which this is architecturally
+  possible.  Except for entering in HYP mode, the system configuration
+  should be such that a kernel which does not include support for the
+  virtualization extensions can boot correctly without extra help.
+
 - The boot loader is expected to call the kernel image by jumping
   directly to the first instruction of the kernel image.
 
index e418dc0a7086631488963786f9ddb0f3d897b147..8df5e8e6dceba06846042d0c6155fd4e986addd8 100644 (file)
@@ -465,7 +465,6 @@ struct bio {
        bio_end_io_t    *bi_end_io;  /* bi_end_io (bio) */
        atomic_t                bi_cnt;      /* pin count: free when it hits zero */
        void             *bi_private;
-       bio_destructor_t *bi_destructor; /* bi_destructor (bio) */
 };
 
 With this multipage bio design:
@@ -647,10 +646,6 @@ for a non-clone bio. There are the 6 pools setup for different size biovecs,
 so bio_alloc(gfp_mask, nr_iovecs) will allocate a vec_list of the
 given size from these slabs.
 
-The bi_destructor() routine takes into account the possibility of the bio
-having originated from a different source (see later discussions on
-n/w to block transfers and kvec_cb)
-
 The bio_get() routine may be used to hold an extra reference on a bio prior
 to i/o submission, if the bio fields are likely to be accessed after the
 i/o is issued (since the bio may otherwise get freed in case i/o completion
diff --git a/Documentation/devicetree/bindings/arm/davinci/nand.txt b/Documentation/devicetree/bindings/arm/davinci/nand.txt
new file mode 100644 (file)
index 0000000..e37241f
--- /dev/null
@@ -0,0 +1,51 @@
+* Texas Instruments Davinci NAND
+
+This file provides information, what the device node for the
+davinci nand interface contain.
+
+Required properties:
+- compatible: "ti,davinci-nand";
+- reg : contain 2 offset/length values:
+        - offset and length for the access window
+        - offset and length for accessing the aemif control registers
+- ti,davinci-chipselect: Indicates on the davinci_nand driver which
+                         chipselect is used for accessing the nand.
+
+Recommended properties :
+- ti,davinci-mask-ale: mask for ale
+- ti,davinci-mask-cle: mask for cle
+- ti,davinci-mask-chipsel: mask for chipselect
+- ti,davinci-ecc-mode: ECC mode valid values for davinci driver:
+               - "none"
+               - "soft"
+               - "hw"
+- ti,davinci-ecc-bits: used ECC bits, currently supported 1 or 4.
+- ti,davinci-nand-buswidth: buswidth 8 or 16
+- ti,davinci-nand-use-bbt: use flash based bad block table support.
+
+Example (enbw_cmc board):
+aemif@60000000 {
+       compatible = "ti,davinci-aemif";
+       #address-cells = <2>;
+       #size-cells = <1>;
+       reg = <0x68000000 0x80000>;
+       ranges = <2 0 0x60000000 0x02000000
+                 3 0 0x62000000 0x02000000
+                 4 0 0x64000000 0x02000000
+                 5 0 0x66000000 0x02000000
+                 6 0 0x68000000 0x02000000>;
+       nand@3,0 {
+               compatible = "ti,davinci-nand";
+               reg = <3 0x0 0x807ff
+                       6 0x0 0x8000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ti,davinci-chipselect = <1>;
+               ti,davinci-mask-ale = <0>;
+               ti,davinci-mask-cle = <0>;
+               ti,davinci-mask-chipsel = <0>;
+               ti,davinci-ecc-mode = "hw";
+               ti,davinci-ecc-bits = <4>;
+               ti,davinci-nand-use-bbt;
+       };
+};
diff --git a/Documentation/devicetree/bindings/i2c/atmel-i2c.txt b/Documentation/devicetree/bindings/i2c/atmel-i2c.txt
new file mode 100644 (file)
index 0000000..b689a0d
--- /dev/null
@@ -0,0 +1,30 @@
+I2C for Atmel platforms
+
+Required properties :
+- compatible : Must be "atmel,at91rm9200-i2c", "atmel,at91sam9261-i2c",
+     "atmel,at91sam9260-i2c", "atmel,at91sam9g20-i2c", "atmel,at91sam9g10-i2c"
+     or "atmel,at91sam9x5-i2c"
+- reg: physical base address of the controller and length of memory mapped
+     region.
+- interrupts: interrupt number to the cpu.
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties:
+- Child nodes conforming to i2c bus binding
+
+Examples :
+
+i2c0: i2c@fff84000 {
+       compatible = "atmel,at91sam9g20-i2c";
+       reg = <0xfff84000 0x100>;
+       interrupts = <12 4 6>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       24c512@50 {
+               compatible = "24c512";
+               reg = <0x50>;
+               pagesize = <128>;
+       }
+}
diff --git a/Documentation/devicetree/bindings/i2c/davinci.txt b/Documentation/devicetree/bindings/i2c/davinci.txt
new file mode 100644 (file)
index 0000000..2dc935b
--- /dev/null
@@ -0,0 +1,28 @@
+* Texas Instruments Davinci I2C
+
+This file provides information, what the device node for the
+davinci i2c interface contain.
+
+Required properties:
+- compatible: "ti,davinci-i2c";
+- reg : Offset and length of the register set for the device
+
+Recommended properties :
+- interrupts : standard interrupt property.
+- clock-frequency : desired I2C bus clock frequency in Hz.
+
+Example (enbw_cmc board):
+       i2c@1c22000 {
+               compatible = "ti,davinci-i2c";
+               reg = <0x22000 0x1000>;
+               clock-frequency = <100000>;
+               interrupts = <15>;
+               interrupt-parent = <&intc>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               dtt@48 {
+                       compatible = "national,lm75";
+                       reg = <0x48>;
+               };
+       };
index 30ac3a0557f7d8c99a3660cbaf6ef2d718f3f3a9..7a3fe9e5f4cbb1a95cd23f2241f649afb4e3df87 100644 (file)
@@ -6,6 +6,7 @@ Required properties:
 - interrupts: Should contain ERROR and DMA interrupts
 - clock-frequency: Desired I2C bus clock frequency in Hz.
                    Only 100000Hz and 400000Hz modes are supported.
+- fsl,i2c-dma-channel: APBX DMA channel for the I2C
 
 Examples:
 
@@ -16,4 +17,5 @@ i2c0: i2c@80058000 {
        reg = <0x80058000 2000>;
        interrupts = <111 68>;
        clock-frequency = <100000>;
+       fsl,i2c-dma-channel = <6>;
 };
diff --git a/Documentation/devicetree/bindings/i2c/nomadik.txt b/Documentation/devicetree/bindings/i2c/nomadik.txt
new file mode 100644 (file)
index 0000000..72065b0
--- /dev/null
@@ -0,0 +1,23 @@
+I2C for Nomadik based systems
+
+Required (non-standard) properties:
+ - Nil
+
+Recommended (non-standard) properties:
+ - clock-frequency : Maximum bus clock frequency for the device
+
+Optional (non-standard) properties:
+ - Nil
+
+Example :
+
+i2c@80004000 {
+        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c";
+        reg = <0x80004000 0x1000>;
+        interrupts = <0 21 0x4>;
+        #address-cells = <1>;
+        #size-cells = <0>;
+        v-i2c-supply = <&db8500_vape_reg>;
+
+        clock-frequency = <400000>;
+};
index 548892c08c598990c01964a86728420a7ad0967b..7da578d72123374f74e1d41575dc316c34a5fa9d 100644 (file)
@@ -7,7 +7,7 @@ as "armctrl" in the SoC documentation, hence naming of this binding.
 
 Required properties:
 
-- compatible : should be "brcm,bcm2835-armctrl-ic.txt"
+- compatible : should be "brcm,bcm2835-armctrl-ic"
 - reg : Specifies base physical address and size of the registers.
 - interrupt-controller : Identifies the node as an interrupt controller
 - #interrupt-cells : Specifies the number of cells needed to encode an
diff --git a/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt b/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt
new file mode 100644 (file)
index 0000000..0a85c70
--- /dev/null
@@ -0,0 +1,68 @@
+* Atmel High Speed MultiMedia Card Interface
+
+This controller on atmel products provides an interface for MMC, SD and SDIO
+types of memory cards.
+
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the atmel-mci driver.
+
+1) MCI node
+
+Required properties:
+- compatible: should be "atmel,hsmci"
+- #address-cells: should be one. The cell is the slot id.
+- #size-cells: should be zero.
+- at least one slot node
+
+The node contains child nodes for each slot that the platform uses
+
+Example MCI node:
+
+mmc0: mmc@f0008000 {
+       compatible = "atmel,hsmci";
+       reg = <0xf0008000 0x600>;
+       interrupts = <12 4>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       [ child node definitions...]
+};
+
+2) slot nodes
+
+Required properties:
+- reg: should contain the slot id.
+- bus-width: number of data lines connected to the controller
+
+Optional properties:
+- cd-gpios: specify GPIOs for card detection
+- cd-inverted: invert the value of external card detect gpio line
+- wp-gpios: specify GPIOs for write protection
+
+Example slot node:
+
+slot@0 {
+       reg = <0>;
+       bus-width = <4>;
+       cd-gpios = <&pioD 15 0>
+       cd-inverted;
+};
+
+Example full MCI node:
+mmc0: mmc@f0008000 {
+       compatible = "atmel,hsmci";
+       reg = <0xf0008000 0x600>;
+       interrupts = <12 4>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+       slot@0 {
+               reg = <0>;
+               bus-width = <4>;
+               cd-gpios = <&pioD 15 0>
+               cd-inverted;
+       };
+       slot@1 {
+               reg = <1>;
+               bus-width = <4>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
new file mode 100644 (file)
index 0000000..7927689
--- /dev/null
@@ -0,0 +1,87 @@
+* Samsung Exynos specific extensions to the Synopsis Designware Mobile
+  Storage Host Controller
+
+The Synopsis designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsis dw mshc controller properties described
+by synposis-dw-mshc.txt and the properties used by the Samsung Exynos specific
+extensions to the Synopsis Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be
+       - "samsung,exynos4210-dw-mshc": for controllers with Samsung Exynos4210
+         specific extentions.
+       - "samsung,exynos4412-dw-mshc": for controllers with Samsung Exynos4412
+         specific extentions.
+       - "samsung,exynos5250-dw-mshc": for controllers with Samsung Exynos5250
+         specific extentions.
+
+* samsung,dw-mshc-ciu-div: Specifies the divider value for the card interface
+  unit (ciu) clock. This property is applicable only for Exynos5 SoC's and
+  ignored for Exynos4 SoC's. The valid range of divider value is 0 to 7.
+
+* samsung,dw-mshc-sdr-timing: Specifies the value of CIU clock phase shift value
+  in transmit mode and CIU clock phase shift value in receive mode for single
+  data rate mode operation. Refer notes below for the order of the cells and the
+  valid values.
+
+* samsung,dw-mshc-ddr-timing: Specifies the value of CUI clock phase shift value
+  in transmit mode and CIU clock phase shift value in receive mode for double
+  data rate mode operation. Refer notes below for the order of the cells and the
+  valid values.
+
+  Notes for the sdr-timing and ddr-timing values:
+
+    The order of the cells should be
+      - First Cell: CIU clock phase shift value for tx mode.
+      - Second Cell: CIU clock phase shift value for rx mode.
+
+    Valid values for SDR and DDR CIU clock timing for Exynos5250:
+      - valid value for tx phase shift and rx phase shift is 0 to 7.
+      - when CIU clock divider value is set to 3, all possible 8 phase shift
+        values can be used.
+      - if CIU clock divider value is 0 (that is divide by 1), both tx and rx
+        phase shift clocks should be 0.
+
+Required properties for a slot:
+
+* gpios: specifies a list of gpios used for command, clock and data bus. The
+  first gpio is the command line and the second gpio is the clock line. The
+  rest of the gpios (depending on the bus-width property) are the data lines in
+  no particular order. The format of the gpio specifier depends on the gpio
+  controller.
+
+Example:
+
+  The MSHC controller node can be split into two portions, SoC specific and
+  board specific portions as listed below.
+
+       dwmmc0@12200000 {
+               compatible = "samsung,exynos5250-dw-mshc";
+               reg = <0x12200000 0x1000>;
+               interrupts = <0 75 0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       dwmmc0@12200000 {
+               num-slots = <1>;
+               supports-highspeed;
+               broken-cd;
+               fifo-depth = <0x80>;
+               card-detect-delay = <200>;
+               samsung,dw-mshc-ciu-div = <3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
+
+               slot@0 {
+                       reg = <0>;
+                       bus-width = <8>;
+                       gpios = <&gpc0 0 2 0 3>, <&gpc0 1 2 0 3>,
+                               <&gpc1 0 2 3 3>, <&gpc1 1 2 3 3>,
+                               <&gpc1 2 2 3 3>, <&gpc1 3 2 3 3>,
+                               <&gpc0 3 2 3 3>, <&gpc0 4 2 3 3>,
+                               <&gpc0 5 2 3 3>, <&gpc0 6 2 3 3>;
+               };
+       };
index 8a6811f4a02f5759e2a793506f1cef40b756e2d8..8e2e0ba2f486c57ca3505e44fa85effd369c4495 100644 (file)
@@ -9,12 +9,17 @@ Interpreted by the OF core:
 Required properties:
 - bus-width: Number of data lines, can be <1>, <4>, or <8>
 
+Card detection:
+If no property below is supplied, standard SDHCI card detect is used.
+Only one of the properties in this section should be supplied:
+  - broken-cd: There is no card detection available; polling must be used.
+  - cd-gpios: Specify GPIOs for card detection, see gpio binding
+  - non-removable: non-removable slot (like eMMC); assume always present.
+
 Optional properties:
-- cd-gpios: Specify GPIOs for card detection, see gpio binding
 - wp-gpios: Specify GPIOs for write protection, see gpio binding
 - cd-inverted: when present, polarity on the cd gpio line is inverted
 - wp-inverted: when present, polarity on the wp gpio line is inverted
-- non-removable: non-removable slot (like eMMC)
 - max-frequency: maximum operating clock frequency
 
 Example:
diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
new file mode 100644 (file)
index 0000000..b7025de
--- /dev/null
@@ -0,0 +1,25 @@
+* PXA MMC drivers
+
+Driver bindings for the PXA MCI (MMC/SDIO) interfaces
+
+Required properties:
+- compatible: Should be "marvell,pxa-mmc".
+- vmmc-supply: A regulator for VMMC
+
+Optional properties:
+- marvell,detect-delay-ms: sets the detection delay timeout in ms.
+- marvell,gpio-power: GPIO spec for the card power enable pin
+
+This file documents differences between the core properties in mmc.txt
+and the properties used by the pxa-mmc driver.
+
+Examples:
+
+mmc0: mmc@41100000 {
+       compatible = "marvell,pxa-mmc";
+       reg = <0x41100000 0x1000>;
+       interrupts = <23>;
+       cd-gpios = <&gpio 23 0>;
+       wp-gpios = <&gpio 24 0>;
+};
+
diff --git a/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
new file mode 100644 (file)
index 0000000..630a7d7
--- /dev/null
@@ -0,0 +1,53 @@
+* Samsung's SDHCI Controller device tree bindings
+
+Samsung's SDHCI controller is used as a connectivity interface with external
+MMC, SD and eMMC storage mediums. This file documents differences between the
+core mmc properties described by mmc.txt and the properties used by the
+Samsung implmentation of the SDHCI controller.
+
+Note: The mmc core bindings documentation states that if none of the core
+card-detect bindings are used, then the standard sdhci card detect mechanism
+is used. The Samsung's SDHCI controller bindings extends this as listed below.
+
+[A] The property "samsung,cd-pinmux-gpio" can be used as stated in the
+    "Optional Board Specific Properties" section below.
+
+[B] If core card-detect bindings and "samsung,cd-pinmux-gpio" property
+    is not specified, it is assumed that there is no card detection
+    mechanism used.
+
+Required SoC Specific Properties:
+- compatible: should be one of the following
+  - "samsung,s3c6410-sdhci": For controllers compatible with s3c6410 sdhci
+    controller.
+  - "samsung,exynos4210-sdhci": For controllers compatible with Exynos4 sdhci
+    controller.
+
+Required Board Specific Properties:
+- gpios: Should specify the gpios used for clock, command and data lines. The
+  gpio specifier format depends on the gpio controller.
+
+Optional Board Specific Properties:
+- samsung,cd-pinmux-gpio: Specifies the card detect line that is routed
+  through a pinmux to the card-detect pin of the card slot. This property
+  should be used only if none of the mmc core card-detect properties are
+  used.
+
+Example:
+       sdhci@12530000 {
+               compatible = "samsung,exynos4210-sdhci";
+               reg = <0x12530000 0x100>;
+               interrupts = <0 75 0>;
+               bus-width = <4>;
+               cd-gpios = <&gpk2 2 2 3 3>;
+               gpios = <&gpk2 0 2 0 3>,  /* clock line */
+                       <&gpk2 1 2 0 3>,  /* command line */
+                       <&gpk2 3 2 3 3>,  /* data line 0 */
+                       <&gpk2 4 2 3 3>,  /* data line 1 */
+                       <&gpk2 5 2 3 3>,  /* data line 2 */
+                       <&gpk2 6 2 3 3>;  /* data line 3 */
+       };
+
+       Note: This example shows both SoC specific and board specific properties
+       in a single device node. The properties can be actually be seperated
+       into SoC specific node and board specific node.
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-dove.txt b/Documentation/devicetree/bindings/mmc/sdhci-dove.txt
new file mode 100644 (file)
index 0000000..ae9aab9
--- /dev/null
@@ -0,0 +1,14 @@
+* Marvell sdhci-dove controller
+
+This file documents differences between the core properties in mmc.txt
+and the properties used by the sdhci-pxav2 and sdhci-pxav3 drivers.
+
+- compatible: Should be "marvell,dove-sdhci".
+
+Example:
+
+sdio0: sdio@92000 {
+       compatible = "marvell,dove-sdhci";
+       reg = <0x92000 0x100>;
+       interrupts = <35>;
+};
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-spear.txt b/Documentation/devicetree/bindings/mmc/sdhci-spear.txt
new file mode 100644 (file)
index 0000000..fd3643e
--- /dev/null
@@ -0,0 +1,18 @@
+* SPEAr SDHCI Controller
+
+This file documents differences between the core properties in mmc.txt
+and the properties used by the sdhci-spear driver.
+
+Required properties:
+- compatible: "st,spear300-sdhci"
+
+Optional properties:
+- cd-gpios: card detect gpio, with zero flags.
+
+Example:
+
+       sdhci@fc000000 {
+               compatible = "st,spear300-sdhci";
+               reg = <0xfc000000 0x1000>;
+               cd-gpios = <&gpio0 6 0>;
+       };
diff --git a/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt
new file mode 100644 (file)
index 0000000..06cd32d
--- /dev/null
@@ -0,0 +1,79 @@
+* Synopsis Designware Mobile Storage Host Controller
+
+The Synopsis designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core mmc properties described by mmc.txt and the
+properties used by the Synopsis Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be
+       - snps,dw-mshc: for controllers compliant with synopsis dw-mshc.
+* #address-cells: should be 1.
+* #size-cells: should be 0.
+
+# Slots: The slot specific information are contained within child-nodes with
+  each child-node representing a supported slot. There should be atleast one
+  child node representing a card slot. The name of the child node representing
+  the slot is recommended to be slot@n where n is the unique number of the slot
+  connnected to the controller. The following are optional properties which
+  can be included in the slot child node.
+
+       * reg: specifies the physical slot number. The valid values of this
+         property is 0 to (num-slots -1), where num-slots is the value
+         specified by the num-slots property.
+
+       * bus-width: as documented in mmc core bindings.
+
+       * wp-gpios: specifies the write protect gpio line. The format of the
+         gpio specifier depends on the gpio controller. If the write-protect
+         line is not available, this property is optional.
+
+Optional properties:
+
+* num-slots: specifies the number of slots supported by the controller.
+  The number of physical slots actually used could be equal or less than the
+  value specified by num-slots. If this property is not specified, the value
+  of num-slot property is assumed to be 1.
+
+* fifo-depth: The maximum size of the tx/rx fifo's. If this property is not
+  specified, the default value of the fifo size is determined from the
+  controller registers.
+
+* card-detect-delay: Delay in milli-seconds before detecting card after card
+  insert event. The default value is 0.
+
+* supports-highspeed: Enables support for high speed cards (upto 50MHz)
+
+* broken-cd: as documented in mmc core bindings.
+
+Aliases:
+
+- All the MSHC controller nodes should be represented in the aliases node using
+  the following format 'mshc{n}' where n is a unique number for the alias.
+
+Example:
+
+The MSHC controller node can be split into two portions, SoC specific and
+board specific portions as listed below.
+
+       dwmmc0@12200000 {
+               compatible = "snps,dw-mshc";
+               reg = <0x12200000 0x1000>;
+               interrupts = <0 75 0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       dwmmc0@12200000 {
+               num-slots = <1>;
+               supports-highspeed;
+               broken-cd;
+               fifo-depth = <0x80>;
+               card-detect-delay = <200>;
+
+               slot@0 {
+                       reg = <0>;
+                       bus-width = <8>;
+               };
+       };
index a20069502f5aaeeb85c45978bcf13c67f598e962..d555421ea49f8237d5a8a0c1822facd379b60f1b 100644 (file)
@@ -3,7 +3,9 @@ Atmel NAND flash
 Required properties:
 - compatible : "atmel,at91rm9200-nand".
 - reg : should specify localbus address and size used for the chip,
-       and if availlable the ECC.
+       and hardware ECC controller if available.
+       If the hardware ECC is PMECC, it should contain address and size for
+       PMECC, PMECC Error Location controller and ROM which has lookup tables.
 - atmel,nand-addr-offset : offset for the address latch.
 - atmel,nand-cmd-offset : offset for the command latch.
 - #address-cells, #size-cells : Must be present if the device has sub-nodes
@@ -16,6 +18,15 @@ Optional properties:
 - nand-ecc-mode : String, operation mode of the NAND ecc mode, soft by default.
   Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first",
   "soft_bch".
+- atmel,has-pmecc : boolean to enable Programmable Multibit ECC hardware.
+  Only supported by at91sam9x5 or later sam9 product.
+- atmel,pmecc-cap : error correct capability for Programmable Multibit ECC
+  Controller. Supported values are: 2, 4, 8, 12, 24.
+- atmel,pmecc-sector-size : sector size for ECC computation. Supported values
+  are: 512, 1024.
+- atmel,pmecc-lookup-table-offset : includes two offsets of lookup table in ROM
+  for different sector size. First one is for sector size 512, the next is for
+  sector size 1024.
 - nand-bus-width : 8 or 16 bus width if not present 8
 - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false
 
@@ -39,3 +50,30 @@ nand0: nand@40000000,0 {
                ...
        };
 };
+
+/* for PMECC supported chips */
+nand0: nand@40000000 {
+       compatible = "atmel,at91rm9200-nand";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       reg = < 0x40000000 0x10000000   /* bus addr & size */
+               0xffffe000 0x00000600   /* PMECC addr & size */
+               0xffffe600 0x00000200   /* PMECC ERRLOC addr & size */
+               0x00100000 0x00100000   /* ROM addr & size */
+               >;
+       atmel,nand-addr-offset = <21>;  /* ale */
+       atmel,nand-cmd-offset = <22>;   /* cle */
+       nand-on-flash-bbt;
+       nand-ecc-mode = "hw";
+       atmel,has-pmecc;        /* enable PMECC */
+       atmel,pmecc-cap = <2>;
+       atmel,pmecc-sector-size = <512>;
+       atmel,pmecc-lookup-table-offset = <0x8000 0x10000>;
+       gpios = <&pioD 5 0      /* rdy */
+                &pioD 4 0      /* nce */
+                0              /* cd */
+               >;
+       partition@0 {
+               ...
+       };
+};
index 1a5bbd346d223a4d3d0429b7abd57595b025763b..3fb3f9015365d0c15d1b4219838d6d16bef9cc53 100644 (file)
@@ -12,6 +12,10 @@ Required properties:
   - interrupt-names : The interrupt names "gpmi-dma", "bch";
   - fsl,gpmi-dma-channel : Should contain the dma channel it uses.
 
+Optional properties:
+  - nand-on-flash-bbt: boolean to enable on flash bbt option if not
+                       present false
+
 The device tree may optionally contain sub-nodes describing partitions of the
 address space. See partition.txt for more detail.
 
diff --git a/Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt b/Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt
new file mode 100644 (file)
index 0000000..d0a3725
--- /dev/null
@@ -0,0 +1,50 @@
+NXP LPC32xx SoC NAND MLC controller
+
+Required properties:
+- compatible: "nxp,lpc3220-mlc"
+- reg: Address and size of the controller
+- interrupts: The NAND interrupt specification
+- gpios: GPIO specification for NAND write protect
+
+The following required properties are very controller specific. See the LPC32xx
+User Manual 7.5.14 MLC NAND Timing Register (the values here are specified in
+Hz, to make them independent of actual clock speed and to provide for good
+accuracy:)
+- nxp,tcea_delay: TCEA_DELAY
+- nxp,busy_delay: BUSY_DELAY
+- nxp,nand_ta: NAND_TA
+- nxp,rd_high: RD_HIGH
+- nxp,rd_low: RD_LOW
+- nxp,wr_high: WR_HIGH
+- nxp,wr_low: WR_LOW
+
+Optional subnodes:
+- Partitions, see Documentation/devicetree/bindings/mtd/partition.txt
+
+Example:
+
+       mlc: flash@200A8000 {
+               compatible = "nxp,lpc3220-mlc";
+               reg = <0x200A8000 0x11000>;
+               interrupts = <11 0>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               nxp,tcea-delay = <333333333>;
+               nxp,busy-delay = <10000000>;
+               nxp,nand-ta = <18181818>;
+               nxp,rd-high = <31250000>;
+               nxp,rd-low = <45454545>;
+               nxp,wr-high = <40000000>;
+               nxp,wr-low = <83333333>;
+               gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */
+
+               mtd0@00000000 {
+                       label = "boot";
+                       reg = <0x00000000 0x00064000>;
+                       read-only;
+               };
+
+               ...
+
+       };
diff --git a/Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt b/Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt
new file mode 100644 (file)
index 0000000..d94edc0
--- /dev/null
@@ -0,0 +1,52 @@
+NXP LPC32xx SoC NAND SLC controller
+
+Required properties:
+- compatible: "nxp,lpc3220-slc"
+- reg: Address and size of the controller
+- nand-on-flash-bbt: Use bad block table on flash
+- gpios: GPIO specification for NAND write protect
+
+The following required properties are very controller specific. See the LPC32xx
+User Manual:
+- nxp,wdr-clks: Delay before Ready signal is tested on write (W_RDY)
+- nxp,rdr-clks: Delay before Ready signal is tested on read (R_RDY)
+(The following values are specified in Hz, to make them independent of actual
+clock speed:)
+- nxp,wwidth: Write pulse width (W_WIDTH)
+- nxp,whold: Write hold time (W_HOLD)
+- nxp,wsetup: Write setup time (W_SETUP)
+- nxp,rwidth: Read pulse width (R_WIDTH)
+- nxp,rhold: Read hold time (R_HOLD)
+- nxp,rsetup: Read setup time (R_SETUP)
+
+Optional subnodes:
+- Partitions, see Documentation/devicetree/bindings/mtd/partition.txt
+
+Example:
+
+       slc: flash@20020000 {
+               compatible = "nxp,lpc3220-slc";
+               reg = <0x20020000 0x1000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               nxp,wdr-clks = <14>;
+               nxp,wwidth = <40000000>;
+               nxp,whold = <100000000>;
+               nxp,wsetup = <100000000>;
+               nxp,rdr-clks = <14>;
+               nxp,rwidth = <40000000>;
+               nxp,rhold = <66666666>;
+               nxp,rsetup = <100000000>;
+               nand-on-flash-bbt;
+               gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */
+
+               mtd0@00000000 {
+                       label = "phy3250-boot";
+                       reg = <0x00000000 0x00064000>;
+                       read-only;
+               };
+
+               ...
+
+       };
index a63c2bd7de2b66f4d847618d31628d22cc2c870b..94de19b8f16bcd548e2e1163704b9fc3ae2ce31f 100644 (file)
@@ -16,6 +16,13 @@ file systems on embedded devices.
  - #address-cells, #size-cells : Must be present if the device has
    sub-nodes representing partitions (see below).  In this case
    both #address-cells and #size-cells must be equal to 1.
+ - no-unaligned-direct-access: boolean to disable the default direct
+   mapping of the flash.
+   On some platforms (e.g. MPC5200) a direct 1:1 mapping may cause
+   problems with JFFS2 usage, as the local bus (LPB) doesn't support
+   unaligned accesses as implemented in the JFFS2 code via memcpy().
+   By defining "no-unaligned-direct-access", the flash will not be
+   exposed directly to the MTD users (e.g. JFFS2) any more.
 
 For JEDEC compatible devices, the following additional properties
 are defined:
diff --git a/Documentation/devicetree/bindings/pwm/imx-pwm.txt b/Documentation/devicetree/bindings/pwm/imx-pwm.txt
new file mode 100644 (file)
index 0000000..8522bfb
--- /dev/null
@@ -0,0 +1,17 @@
+Freescale i.MX PWM controller
+
+Required properties:
+- compatible: should be "fsl,<soc>-pwm"
+- reg: physical base address and length of the controller's registers
+- #pwm-cells: should be 2.  The first cell specifies the per-chip index
+  of the PWM to use and the second cell is the period in nanoseconds.
+- interrupts: The interrupt for the pwm controller
+
+Example:
+
+pwm1: pwm@53fb4000 {
+       #pwm-cells = <2>;
+       compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
+       reg = <0x53fb4000 0x4000>;
+       interrupts = <61>;
+};
index 11963e4d6bc478a6e70e20aa1f06a32a759dee90..9e3f8f1d46a26642577177806d5f94f2db2b91a1 100644 (file)
@@ -4,7 +4,7 @@ Required properties:
 - compatible: should be "fsl,imx23-pwm"
 - reg: physical base address and length of the controller's registers
 - #pwm-cells: should be 2.  The first cell specifies the per-chip index
-  of the PWM to use and the second cell is the duty cycle in nanoseconds.
+  of the PWM to use and the second cell is the period in nanoseconds.
 - fsl,pwm-number: the number of PWM devices
 
 Example:
index bbbeedb4ec055c9c7f69b77ec1348a1525bc9dd5..01438ecd6628b80920dba8c783483dc94320373b 100644 (file)
@@ -7,7 +7,7 @@ Required properties:
 - reg: physical base address and length of the controller's registers
 - #pwm-cells: On Tegra the number of cells used to specify a PWM is 2. The
   first cell specifies the per-chip index of the PWM to use and the second
-  cell is the duty cycle in nanoseconds.
+  cell is the period in nanoseconds.
 
 Example:
 
index 2de21c2acf55d022681059e3ec690b1ed623e1cd..844bd5fbd04c13c0d5a511c7a333f19c37699e48 100644 (file)
@@ -7,7 +7,7 @@ free running counter values, and generates an interrupt.
 
 Required properties:
 
-- compatible : should be "brcm,bcm2835-system-timer.txt"
+- compatible : should be "brcm,bcm2835-system-timer"
 - reg : Specifies base physical address and size of the registers.
 - interrupts : A list of 4 interrupt sinks; one per timer channel.
 - clock-frequency : The frequency of the clock that drives the counter, in Hz.
index 950856bd2e39dd105ea39008df8e0b875604689d..43cff70465abb4b796b9f302d5bf4d2b9cfa987e 100644 (file)
@@ -284,3 +284,7 @@ CLOCK
 PINCTRL
   devm_pinctrl_get()
   devm_pinctrl_put()
+
+PWM
+  devm_pwm_get()
+  devm_pwm_put()
index f50f26ce6cd09af07d0b88ac7fa42a928a01bf79..f2571c8bef74e5ba5b156affea41568dee4f845e 100644 (file)
@@ -12,9 +12,47 @@ and work is in progress on adding support for minor version 1 of the NFSv4
 protocol.
 
 The purpose of this document is to provide information on some of the
-upcall interfaces that are used in order to provide the NFS client with
-some of the information that it requires in order to fully comply with
-the NFS spec.
+special features of the NFS client that can be configured by system
+administrators.
+
+
+The nfs4_unique_id parameter
+============================
+
+NFSv4 requires clients to identify themselves to servers with a unique
+string.  File open and lock state shared between one client and one server
+is associated with this identity.  To support robust NFSv4 state recovery
+and transparent state migration, this identity string must not change
+across client reboots.
+
+Without any other intervention, the Linux client uses a string that contains
+the local system's node name.  System administrators, however, often do not
+take care to ensure that node names are fully qualified and do not change
+over the lifetime of a client system.  Node names can have other
+administrative requirements that require particular behavior that does not
+work well as part of an nfs_client_id4 string.
+
+The nfs.nfs4_unique_id boot parameter specifies a unique string that can be
+used instead of a system's node name when an NFS client identifies itself to
+a server.  Thus, if the system's node name is not unique, or it changes, its
+nfs.nfs4_unique_id stays the same, preventing collision with other clients
+or loss of state during NFS reboot recovery or transparent state migration.
+
+The nfs.nfs4_unique_id string is typically a UUID, though it can contain
+anything that is believed to be unique across all NFS clients.  An
+nfs4_unique_id string should be chosen when a client system is installed,
+just as a system's root file system gets a fresh UUID in its label at
+install time.
+
+The string should remain fixed for the lifetime of the client.  It can be
+changed safely if care is taken that the client shuts down cleanly and all
+outstanding NFSv4 state has expired, to prevent loss of NFSv4 state.
+
+This string can be stored in an NFS client's grub.conf, or it can be provided
+via a net boot facility such as PXE.  It may also be specified as an nfs.ko
+module parameter.  Specifying a uniquifier string is not support for NFS
+clients running in containers.
+
 
 The DNS resolver
 ================
diff --git a/Documentation/filesystems/nfs/nfsd-admin-interfaces.txt b/Documentation/filesystems/nfs/nfsd-admin-interfaces.txt
new file mode 100644 (file)
index 0000000..56a96fb
--- /dev/null
@@ -0,0 +1,41 @@
+Administrative interfaces for nfsd
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Note that normally these interfaces are used only by the utilities in
+nfs-utils.
+
+nfsd is controlled mainly by pseudofiles under the "nfsd" filesystem,
+which is normally mounted at /proc/fs/nfsd/.
+
+The server is always started by the first write of a nonzero value to
+nfsd/threads.
+
+Before doing that, NFSD can be told which sockets to listen on by
+writing to nfsd/portlist; that write may be:
+
+       - an ascii-encoded file descriptor, which should refer to a
+         bound (and listening, for tcp) socket, or
+       - "transportname port", where transportname is currently either
+         "udp", "tcp", or "rdma".
+
+If nfsd is started without doing any of these, then it will create one
+udp and one tcp listener at port 2049 (see nfsd_init_socks).
+
+On startup, nfsd and lockd grace periods start.
+
+nfsd is shut down by a write of 0 to nfsd/threads.  All locks and state
+are thrown away at that point.
+
+Between startup and shutdown, the number of threads may be adjusted up
+or down by additional writes to nfsd/threads or by writes to
+nfsd/pool_threads.
+
+For more detail about files under nfsd/ and what they control, see
+fs/nfsd/nfsctl.c; most of them have detailed comments.
+
+Implementation notes
+^^^^^^^^^^^^^^^^^^^^
+
+Note that the rpc server requires the caller to serialize addition and
+removal of listening sockets, and startup and shutdown of the server.
+For nfsd this is done using nfsd_mutex.
index ef898553638ef960840202892a0060343c57981a..5bc51346b6897aead6100151d4faaab80722c694 100644 (file)
@@ -56,6 +56,6 @@ The junction temperature is calculated:
 The junction temperature attribute is supported by the driver.
 
 The battery temperature is calculated:
-       Degree Celcius = 1 / (t1 + 1/298)- 273
+       Degree Celsius = 1 / (t1 + 1/298)- 273
 where t1 = (1/B)* ln(( ADCval * 2.5)/(R25*ITBAT*255))
 Default values of R25, B, ITBAT are 10e3, 3380 and 50e-6 respectively.
index d6f8d9cd7d7f54dd7b78fb3d2207bee09e5b4f4e..e6d87398cc8f01e8c450713f5933347627d05752 100644 (file)
@@ -9,7 +9,7 @@ Supported chips:
                http://pdfserv.maxim-ic.com/en/ds/MAX1619.pdf
 
 Authors:
-        Alexey Fisher <fishor@mail.ru>,
+        Oleksij Rempel <bug-track@fisher-privat.net>,
         Jean Delvare <khali@linux-fr.org>
 
 Description
index ef7984317cecb29eca6ef23a30c21d920e66ef31..c3a3a5be10adc8785afa17db28c9bbc4b47aec33 100644 (file)
@@ -41,5 +41,5 @@ Channel Signal
 
 The Sysfs nodes will represent the voltage in the units of mV,
 the temperature channel shows the converted temperature in
-degree celcius. The Battery charging current channel represents
+degree Celsius. The Battery charging current channel represents
 battery charging current in mA.
index f777fa96243db4130771cb2dbd85e1a952ef683f..e2ed3360b708c68ef70807ea56429e9f6e1e0aea 100644 (file)
@@ -1730,6 +1730,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        will be autodetected by the client, and it will fall
                        back to using the idmapper.
                        To turn off this behaviour, set the value to '0'.
+       nfs.nfs4_unique_id=
+                       [NFS4] Specify an additional fixed unique ident-
+                       ification string that NFSv4 clients can insert into
+                       their nfs_client_id4 string.  This is typically a
+                       UUID that is generated at system install time.
 
        nfs.send_implementation_id =
                        [NFSv4.1] Send client implementation identification
index fad2feb8b7ce2d394b57c8532c6858576023993a..c2743f59f9acb1ce9479ecf7e39926a9caa404a4 100644 (file)
@@ -10,8 +10,22 @@ Contact: Samu Onkalo (samu.p.onkalo-at-nokia.com)
 Description
 -----------
 LP5523 can drive up to 9 channels. Leds can be controlled directly via
-the led class control interface. Channels have generic names:
-lp5523:channelx where x is 0...8
+the led class control interface.
+The name of each channel is configurable in the platform data - name and label.
+There are three options to make the channel name.
+
+a) Define the 'name' in the platform data
+To make specific channel name, then use 'name' platform data.
+/sys/class/leds/R1               (name: 'R1')
+/sys/class/leds/B1               (name: 'B1')
+
+b) Use the 'label' with no 'name' field
+For one device name with channel number, then use 'label'.
+/sys/class/leds/RGB:channelN     (label: 'RGB', N: 0 ~ 8)
+
+c) Default
+If both fields are NULL, 'lp5523' is used by default.
+/sys/class/leds/lp5523:channelN  (N: 0 ~ 8)
 
 The chip provides 3 engines. Each engine can control channels without
 interaction from the main CPU. Details of the micro engine code can be found
@@ -46,12 +60,13 @@ Note - chan_nr can have values between 0 and 8.
 
 static struct lp5523_led_config lp5523_led_config[] = {
         {
+               .name           = "D1",
                 .chan_nr        = 0,
                 .led_current    = 50,
                .max_current    = 130,
         },
 ...
-        }, {
+        {
                 .chan_nr        = 8,
                 .led_current    = 50,
                .max_current    = 130,
diff --git a/Documentation/percpu-rw-semaphore.txt b/Documentation/percpu-rw-semaphore.txt
new file mode 100644 (file)
index 0000000..7d3c824
--- /dev/null
@@ -0,0 +1,27 @@
+Percpu rw semaphores
+--------------------
+
+Percpu rw semaphores is a new read-write semaphore design that is
+optimized for locking for reading.
+
+The problem with traditional read-write semaphores is that when multiple
+cores take the lock for reading, the cache line containing the semaphore
+is bouncing between L1 caches of the cores, causing performance
+degradation.
+
+Locking for reading is very fast, it uses RCU and it avoids any atomic
+instruction in the lock and unlock path. On the other hand, locking for
+writing is very expensive, it calls synchronize_rcu() that can take
+hundreds of milliseconds.
+
+The lock is declared with "struct percpu_rw_semaphore" type.
+The lock is initialized percpu_init_rwsem, it returns 0 on success and
+-ENOMEM on allocation failure.
+The lock must be freed with percpu_free_rwsem to avoid memory leak.
+
+The lock is locked for read with percpu_down_read, percpu_up_read and
+for write with percpu_down_write, percpu_up_write.
+
+The idea of using RCU for optimized rw-lock was introduced by
+Eric Dumazet <eric.dumazet@gmail.com>.
+The code was written by Mikulas Patocka <mpatocka@redhat.com>
index 554290ebab94509f6fa9ae603cadfc3b8afcde4a..7d2b4c9b544b3c28596bec44c05a62dfadfdc260 100644 (file)
@@ -36,7 +36,8 @@ Legacy users can request a PWM device using pwm_request() and free it
 after usage with pwm_free().
 
 New users should use the pwm_get() function and pass to it the consumer
-device or a consumer name. pwm_put() is used to free the PWM device.
+device or a consumer name. pwm_put() is used to free the PWM device. Managed
+variants of these functions, devm_pwm_get() and devm_pwm_put(), also exist.
 
 After being requested a PWM has to be configured using:
 
index 3a3079411a3dc953c59cb75b8391906b2fb74df3..da03146c182ae39dbbe757955faae1c01ae1a0a1 100644 (file)
@@ -1,3 +1,16 @@
+Release Date    : Mon. Oct 1, 2012 17:00:00 PST 2012 -
+                       (emaild-id:megaraidlinux@lsi.com)
+                       Adam Radford
+Current Version : 06.504.01.00-rc1
+Old Version     : 00.00.06.18-rc1
+    1. Removed un-needed completion_lock spinlock calls.
+    2. Add module param for configurable MSI-X vector count.
+    3. Load io_request DataLength in bytes.
+    4. Add array boundary check for SystemPD.
+    5. Add SystemPD FastPath support.
+    6. Remove duplicate code.
+    7. Version, Changelog, Copyright update.
+-------------------------------------------------------------------------------
 Release Date    : Tue. Jun 17, 2012 17:00:00 PST 2012 -
                        (emaild-id:megaraidlinux@lsi.com)
                        Adam Radford/Kashyap Desai
index a78879b01f09ecb93aedff8ead9e619449851d54..3fe0d812dcecf28262e38e2cfed9d2ff11b41e82 100755 (executable)
@@ -402,8 +402,6 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "        .queue_data_in                  = " + fabric_mod_name + "_queue_data_in,\n"
        buf += "        .queue_status                   = " + fabric_mod_name + "_queue_status,\n"
        buf += "        .queue_tm_rsp                   = " + fabric_mod_name + "_queue_tm_rsp,\n"
-       buf += "        .get_fabric_sense_len           = " + fabric_mod_name + "_get_fabric_sense_len,\n"
-       buf += "        .set_fabric_sense_len           = " + fabric_mod_name + "_set_fabric_sense_len,\n"
        buf += "        .is_state_remove                = " + fabric_mod_name + "_is_state_remove,\n"
        buf += "        /*\n"
        buf += "         * Setup function pointers for generic logic in target_core_fabric_configfs.c\n"
@@ -906,20 +904,6 @@ def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
                        buf += "}\n\n"
                        bufi += "int " + fabric_mod_name + "_queue_tm_rsp(struct se_cmd *);\n"
 
-               if re.search('get_fabric_sense_len\)\(', fo):
-                       buf += "u16 " + fabric_mod_name + "_get_fabric_sense_len(void)\n"
-                       buf += "{\n"
-                       buf += "        return 0;\n"
-                       buf += "}\n\n"
-                       bufi += "u16 " + fabric_mod_name + "_get_fabric_sense_len(void);\n"
-
-               if re.search('set_fabric_sense_len\)\(', fo):
-                       buf += "u16 " + fabric_mod_name + "_set_fabric_sense_len(struct se_cmd *se_cmd, u32 sense_length)\n"
-                       buf += "{\n"
-                       buf += "        return 0;\n"
-                       buf += "}\n\n"
-                       bufi += "u16 " + fabric_mod_name + "_set_fabric_sense_len(struct se_cmd *, u32);\n"
-
                if re.search('is_state_remove\)\(', fo):
                        buf += "int " + fabric_mod_name + "_is_state_remove(struct se_cmd *se_cmd)\n"
                        buf += "{\n"
index 54270df99d5c2f1794c4fcd537eec05fd525d031..cfe52c798d743b0979a31c414948a5c72c491e46 100644 (file)
@@ -136,11 +136,25 @@ Or alternatively for integer menu controls, by calling v4l2_ctrl_new_int_menu:
                        const struct v4l2_ctrl_ops *ops,
                        u32 id, s32 max, s32 def, const s64 *qmenu_int);
 
+Standard menu controls with a driver specific menu are added by calling
+v4l2_ctrl_new_std_menu_items:
+
+       struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(
+               struct v4l2_ctrl_handler *hdl,
+               const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
+               s32 skip_mask, s32 def, const char * const *qmenu);
+
 These functions are typically called right after the v4l2_ctrl_handler_init:
 
        static const s64 exp_bias_qmenu[] = {
               -2, -1, 0, 1, 2
        };
+       static const char * const test_pattern[] = {
+               "Disabled",
+               "Vertical Bars",
+               "Solid Black",
+               "Solid White",
+       };
 
        v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls);
        v4l2_ctrl_new_std(&foo->ctrl_handler, &foo_ctrl_ops,
@@ -156,6 +170,9 @@ These functions are typically called right after the v4l2_ctrl_handler_init:
                        ARRAY_SIZE(exp_bias_qmenu) - 1,
                        ARRAY_SIZE(exp_bias_qmenu) / 2 - 1,
                        exp_bias_qmenu);
+       v4l2_ctrl_new_std_menu_items(&foo->ctrl_handler, &foo_ctrl_ops,
+                       V4L2_CID_TEST_PATTERN, ARRAY_SIZE(test_pattern) - 1, 0,
+                       0, test_pattern);
        ...
        if (foo->ctrl_handler.error) {
                int err = foo->ctrl_handler.error;
@@ -185,6 +202,13 @@ v4l2_ctrl_new_std_menu in that it doesn't have the mask argument and takes
 as the last argument an array of signed 64-bit integers that form an exact
 menu item list.
 
+The v4l2_ctrl_new_std_menu_items function is very similar to
+v4l2_ctrl_new_std_menu but takes an extra parameter qmenu, which is the driver
+specific menu for an otherwise standard menu control. A good example for this
+control is the test pattern control for capture/display/sensors devices that
+have the capability to generate test patterns. These test patterns are hardware
+specific, so the contents of the menu will vary from device to device.
+
 Note that if something fails, the function will return NULL or an error and
 set ctrl_handler->error to the error code. If ctrl_handler->error was already
 set, then it will just return and do nothing. This is also true for
index 77dfecf4e2d6e7ec310b145496f494f9aac25b08..a5f8436753e7d4698bf98d1e3989a14d4a98a923 100644 (file)
 
 
   Looking at the source shows that the fault happened during a call to
-  copy_to_user to copy the data into the kernel:
+  copy_from_user to copy the data into the kernel:
 
 
        107             count -= chars;
index eae3cd86831e2bda0f1416096a9957e94bfa7677..e73060fe07888916a358331744397a1257cd1696 100644 (file)
@@ -1544,7 +1544,7 @@ S:        Supported
 F:     drivers/rtc/rtc-bfin.c
 
 BLACKFIN SDH DRIVER
-M:     Cliff Cai <cliff.cai@analog.com>
+M:     Sonic Zhang <sonic.zhang@analog.com>
 L:     uclinux-dist-devel@blackfin.uclinux.org
 W:     http://blackfin.uclinux.org
 S:     Supported
@@ -1958,10 +1958,10 @@ S:      Supported
 F:     drivers/platform/x86/classmate-laptop.c
 
 COCCINELLE/Semantic Patches (SmPL)
-M:     Julia Lawall <julia@diku.dk>
+M:     Julia Lawall <Julia.Lawall@lip6.fr>
 M:     Gilles Muller <Gilles.Muller@lip6.fr>
-M:     Nicolas Palix <npalix.work@gmail.com>
-L:     cocci@diku.dk (moderated for non-subscribers)
+M:     Nicolas Palix <nicolas.palix@imag.fr>
+L:     cocci@systeme.lip6.fr (moderated for non-subscribers)
 W:     http://coccinelle.lip6.fr/
 S:     Supported
 F:     scripts/coccinelle/
@@ -2423,11 +2423,6 @@ S:       Maintained
 F:     Documentation/hwmon/dme1737
 F:     drivers/hwmon/dme1737.c
 
-DOCBOOK FOR DOCUMENTATION
-M:     Randy Dunlap <rdunlap@xenotime.net>
-S:     Maintained
-F:     scripts/kernel-doc
-
 DOCKING STATION DRIVER
 M:     Shaohua Li <shaohua.li@intel.com>
 L:     linux-acpi@vger.kernel.org
@@ -5207,8 +5202,10 @@ S:       Maintained
 F:     drivers/mmc/host/omap.c
 
 OMAP HS MMC SUPPORT
+M:     Venkatraman S <svenkatr@ti.com>
+L:     linux-mmc@vger.kernel.org
 L:     linux-omap@vger.kernel.org
-S:     Orphan
+S:     Maintained
 F:     drivers/mmc/host/omap_hsmmc.c
 
 OMAP RANDOM NUMBER GENERATOR SUPPORT
index 86eb6acb3978c81121746356290ca1d7e82d0c4e..5d8e7f2583881bcbc8b549dc9e2d3d246498865a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -664,22 +664,9 @@ ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y)
 endif
 
 # Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
-# But warn user when we do so
-warn-assign = \
-$(warning "WARNING: Appending $$K$(1) ($(K$(1))) from $(origin K$(1)) to kernel $$$(1)")
-
-ifneq ($(KCPPFLAGS),)
-        $(call warn-assign,CPPFLAGS)
-        KBUILD_CPPFLAGS += $(KCPPFLAGS)
-endif
-ifneq ($(KAFLAGS),)
-        $(call warn-assign,AFLAGS)
-        KBUILD_AFLAGS += $(KAFLAGS)
-endif
-ifneq ($(KCFLAGS),)
-        $(call warn-assign,CFLAGS)
-        KBUILD_CFLAGS += $(KCFLAGS)
-endif
+KBUILD_CPPFLAGS += $(KCPPFLAGS)
+KBUILD_AFLAGS += $(KAFLAGS)
+KBUILD_CFLAGS += $(KCFLAGS)
 
 # Use --build-id when available.
 LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
index 550cce4dd64840a2f0be048ffb046b6d4a2dafae..a79a1ad8bb960a1d2aead851018fd2496c231d12 100644 (file)
@@ -271,6 +271,12 @@ config ARCH_WANT_OLD_COMPAT_IPC
        select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
        bool
 
+config GENERIC_KERNEL_THREAD
+       bool
+
+config GENERIC_KERNEL_EXECVE
+       bool
+
 config HAVE_ARCH_SECCOMP_FILTER
        bool
        help
index 9944dedee5b1b1b31abf08599a44421333bd9290..7a08cfb80ee8319887ea4005e5eaa7da2f174c78 100644 (file)
@@ -20,6 +20,8 @@ config ALPHA
        select GENERIC_CMOS_UPDATE
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        help
          The Alpha is a 64-bit general-purpose processor designed and
          marketed by the Digital Equipment Corporation of blessed memory,
index d97d66334e6f87fa4d3024e9a98e0517ccadc8a1..64ffc9e9e5485a41b29e0836773389582dfac2fe 100644 (file)
@@ -10,3 +10,4 @@ header-y += pal.h
 header-y += reg.h
 header-y += regdef.h
 header-y += sysinfo.h
+generic-y += exec.h
diff --git a/arch/alpha/include/asm/exec.h b/arch/alpha/include/asm/exec.h
deleted file mode 100644 (file)
index 4a5a41f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ALPHA_EXEC_H
-#define __ALPHA_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* __ALPHA_EXEC_H */
index e37b887b3d9f636fdcb0b4615a8c648dfc3d364f..6cb7fe85c4b567adad3516a74c5b862a32a50a5e 100644 (file)
@@ -49,9 +49,6 @@ extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
-/* Create a kernel thread without removing it from tasklists.  */
-extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
index 28335bd40e406d54557fc17d7dbc15eae88d1a8d..4554ecbff7c6527be35fea7d20e255cc0770b653 100644 (file)
@@ -84,7 +84,6 @@ register struct thread_info *__current_thread_info __asm__("$8");
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
-#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 
 /* Work to do on interrupt/exception return.  */
@@ -117,5 +116,7 @@ register struct thread_info *__current_thread_info __asm__("$8");
                 (int __user *)(value));                                \
        })
 
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+
 #endif /* __KERNEL__ */
 #endif /* _ALPHA_THREAD_INFO_H */
index a31a78eac9b99962cf6b55df76b1066cdcaf7b2b..7826e227e4d09003ffb230c1596143f74539d607 100644 (file)
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
 
 /* "Conditional" syscalls.  What we want is
 
index 15fa821d09cd38ff58ea5390439617ee2ff4a2eb..89566b346c0f802bd5bfe0c817bd2fee9bd39d3e 100644 (file)
@@ -50,9 +50,6 @@ EXPORT_SYMBOL(alpha_read_fp_reg_s);
 EXPORT_SYMBOL(alpha_write_fp_reg);
 EXPORT_SYMBOL(alpha_write_fp_reg_s);
 
-/* entry.S */
-EXPORT_SYMBOL(kernel_thread);
-
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_tcpudp_magic);
 EXPORT_SYMBOL(ip_compute_csum);
index ec0da0567ab515e6203d2310a9d960be7d4fc0e7..a7607832dd4ff66236b06a8010fb50f9ecd02bdd 100644 (file)
@@ -311,7 +311,7 @@ entSys:
 
        .align  4
 ret_from_sys_call:
-       cmovne  $26, 0, $19             /* $19 = 0 => non-restartable */
+       cmovne  $26, 0, $18             /* $18 = 0 => non-restartable */
        ldq     $0, SP_OFF($sp)
        and     $0, 8, $0
        beq     $0, ret_to_kernel
@@ -320,8 +320,8 @@ ret_to_user:
                sampling and the rti.  */
        lda     $16, 7
        call_pal PAL_swpipl
-       ldl     $5, TI_FLAGS($8)
-       and     $5, _TIF_WORK_MASK, $2
+       ldl     $17, TI_FLAGS($8)
+       and     $17, _TIF_WORK_MASK, $2
        bne     $2, work_pending
 restore_all:
        RESTORE_ALL
@@ -341,10 +341,10 @@ $syscall_error:
         * frame to indicate that a negative return value wasn't an
         * error number..
         */
-       ldq     $19, 0($sp)     /* old syscall nr (zero if success) */
-       beq     $19, $ret_success
+       ldq     $18, 0($sp)     /* old syscall nr (zero if success) */
+       beq     $18, $ret_success
 
-       ldq     $20, 72($sp)    /* .. and this a3 */
+       ldq     $19, 72($sp)    /* .. and this a3 */
        subq    $31, $0, $0     /* with error in v0 */
        addq    $31, 1, $1      /* set a3 for errno return */
        stq     $0, 0($sp)
@@ -362,51 +362,35 @@ $ret_success:
  * Do all cleanup when returning from all interrupts and system calls.
  *
  * Arguments:
- *       $5: TI_FLAGS.
  *       $8: current.
- *      $19: The old syscall number, or zero if this is not a return
+ *      $17: TI_FLAGS.
+ *      $18: The old syscall number, or zero if this is not a return
  *           from a syscall that errored and is possibly restartable.
- *      $20: The old a3 value
+ *      $19: The old a3 value
  */
 
        .align  4
        .ent    work_pending
 work_pending:
-       and     $5, _TIF_NEED_RESCHED, $2
-       beq     $2, $work_notifysig
+       and     $17, _TIF_NOTIFY_RESUME | _TIF_SIGPENDING, $2
+       bne     $2, $work_notifysig
 
 $work_resched:
-       subq    $sp, 16, $sp
-       stq     $19, 0($sp)              /* save syscall nr */
-       stq     $20, 8($sp)              /* and error indication (a3) */
+       /*
+        * We can get here only if we returned from syscall without SIGPENDING
+        * or got through work_notifysig already.  Either case means no syscall
+        * restarts for us, so let $18 and $19 burn.
+        */
        jsr     $26, schedule
-       ldq     $19, 0($sp)
-       ldq     $20, 8($sp)
-       addq    $sp, 16, $sp
-       /* Make sure need_resched and sigpending don't change between
-               sampling and the rti.  */
-       lda     $16, 7
-       call_pal PAL_swpipl
-       ldl     $5, TI_FLAGS($8)
-       and     $5, _TIF_WORK_MASK, $2
-       beq     $2, restore_all
-       and     $5, _TIF_NEED_RESCHED, $2
-       bne     $2, $work_resched
+       mov     0, $18
+       br      ret_to_user
 
 $work_notifysig:
        mov     $sp, $16
        bsr     $1, do_switch_stack
-       mov     $sp, $17
-       mov     $5, $18
-       mov     $19, $9         /* save old syscall number */
-       mov     $20, $10        /* save old a3 */
-       and     $5, _TIF_SIGPENDING, $2
-       cmovne  $2, 0, $9       /* we don't want double syscall restarts */
-       jsr     $26, do_notify_resume
-       mov     $9, $19
-       mov     $10, $20
+       jsr     $26, do_work_pending
        bsr     $1, undo_switch_stack
-       br      ret_to_user
+       br      restore_all
 .end work_pending
 
 /*
@@ -418,11 +402,10 @@ $work_notifysig:
 strace:
        /* set up signal stack, call syscall_trace */
        bsr     $1, do_switch_stack
-       jsr     $26, syscall_trace
+       jsr     $26, syscall_trace_enter /* returns the syscall number */
        bsr     $1, undo_switch_stack
 
-       /* get the system call number and the arguments back.. */
-       ldq     $0, 0($sp)
+       /* get the arguments back.. */
        ldq     $16, SP_OFF+24($sp)
        ldq     $17, SP_OFF+32($sp)
        ldq     $18, SP_OFF+40($sp)
@@ -449,15 +432,15 @@ $strace_success:
        stq     $0, 0($sp)              /* save return value */
 
        bsr     $1, do_switch_stack
-       jsr     $26, syscall_trace
+       jsr     $26, syscall_trace_leave
        bsr     $1, undo_switch_stack
        br      $31, ret_from_sys_call
 
        .align  3
 $strace_error:
-       ldq     $19, 0($sp)     /* old syscall nr (zero if success) */
-       beq     $19, $strace_success
-       ldq     $20, 72($sp)    /* .. and this a3 */
+       ldq     $18, 0($sp)     /* old syscall nr (zero if success) */
+       beq     $18, $strace_success
+       ldq     $19, 72($sp)    /* .. and this a3 */
 
        subq    $31, $0, $0     /* with error in v0 */
        addq    $31, 1, $1      /* set a3 for errno return */
@@ -465,11 +448,11 @@ $strace_error:
        stq     $1, 72($sp)     /* a3 for return */
 
        bsr     $1, do_switch_stack
-       mov     $19, $9         /* save old syscall number */
-       mov     $20, $10        /* save old a3 */
-       jsr     $26, syscall_trace
-       mov     $9, $19
-       mov     $10, $20
+       mov     $18, $9         /* save old syscall number */
+       mov     $19, $10        /* save old a3 */
+       jsr     $26, syscall_trace_leave
+       mov     $9, $18
+       mov     $10, $19
        bsr     $1, undo_switch_stack
 
        mov     $31, $26        /* tell "ret_from_sys_call" we can restart */
@@ -609,59 +592,20 @@ ret_from_fork:
 .end ret_from_fork
 
 /*
- * kernel_thread(fn, arg, clone_flags)
+ * ... and new kernel threads - here
  */
        .align 4
-       .globl  kernel_thread
-       .ent    kernel_thread
-kernel_thread:
-       /* We can be called from a module.  */
-       ldgp    $gp, 0($27)
-       .prologue 1
-       subq    $sp, SP_OFF+6*8, $sp
-       br      $1, 2f          /* load start address */
-
-       /* We've now "returned" from a fake system call.  */
-       unop
-       blt     $0, 1f          /* error?  */
-       ldi     $1, 0x3fff
-       beq     $20, 1f         /* parent or child?  */
-
-       bic     $sp, $1, $8     /* in child.  */
-       jsr     $26, ($27)
-       ldgp    $gp, 0($26)
-       mov     $0, $16
-       mov     $31, $26
-       jmp     $31, sys_exit
-
-1:     ret                     /* in parent.  */
-
-       .align 4
-2:     /* Fake a system call stack frame, as we can't do system calls
-          from kernel space.  Note that we store FN and ARG as they
-          need to be set up in the child for the call.  Also store $8
-          and $26 for use in the parent.  */
-       stq     $31, SP_OFF($sp)        /* ps */
-       stq     $1, SP_OFF+8($sp)       /* pc */
-       stq     $gp, SP_OFF+16($sp)     /* gp */
-       stq     $16, 136($sp)           /* $27; FN for child */
-       stq     $17, SP_OFF+24($sp)     /* $16; ARG for child */
-       stq     $8, 64($sp)             /* $8 */
-       stq     $26, 128($sp)           /* $26 */
-       /* Avoid the HAE being gratuitously wrong, to avoid restoring it.  */
-       ldq     $2, alpha_mv+HAE_CACHE
-       stq     $2, 152($sp)            /* HAE */
-
-       /* Shuffle FLAGS to the front; add CLONE_VM.  */
-       ldi     $1, CLONE_VM|CLONE_UNTRACED
-       or      $18, $1, $16
-       bsr     $26, sys_clone
-
-       /* We don't actually care for a3 success widgetry in the kernel.
-          Not for positive errno values.  */
-       stq     $0, 0($sp)              /* $0 */
-       br      ret_to_kernel
-.end kernel_thread
+       .globl  ret_from_kernel_thread
+       .ent    ret_from_kernel_thread
+ret_from_kernel_thread:
+       mov     $17, $16
+       jsr     $26, schedule_tail
+       mov     $9, $27
+       mov     $10, $16
+       jsr     $26, ($9)
+       mov     $31, $19                /* to disable syscall restarts */
+       br      $31, ret_to_user
+.end ret_from_kernel_thread
 
 \f
 /*
@@ -722,7 +666,7 @@ sys_sigreturn:
        lda     $sp, -SWITCH_STACK_SIZE($sp)
        jsr     $26, do_sigreturn
        bne     $9, 1f
-       jsr     $26, syscall_trace
+       jsr     $26, syscall_trace_leave
 1:     br      $1, undo_switch_stack
        br      ret_from_sys_call
 .end sys_sigreturn
@@ -739,20 +683,11 @@ sys_rt_sigreturn:
        lda     $sp, -SWITCH_STACK_SIZE($sp)
        jsr     $26, do_rt_sigreturn
        bne     $9, 1f
-       jsr     $26, syscall_trace
+       jsr     $26, syscall_trace_leave
 1:     br      $1, undo_switch_stack
        br      ret_from_sys_call
 .end sys_rt_sigreturn
 
-       .align  4
-       .globl  sys_execve
-       .ent    sys_execve
-sys_execve:
-       .prologue 0
-       mov     $sp, $19
-       jmp     $31, do_sys_execve
-.end sys_execve
-
        .align  4
        .globl  alpha_ni_syscall
        .ent    alpha_ni_syscall
index 63e77e3944ced280724c964b7690502341383695..9eb090582cf1eb2c557e03025bafc73846fde02f 100644 (file)
@@ -449,7 +449,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
 {
        int retval;
        struct cdfs_args tmp;
-       char *devname;
+       struct filename *devname;
 
        retval = -EFAULT;
        if (copy_from_user(&tmp, args, sizeof(tmp)))
@@ -458,7 +458,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
        retval = PTR_ERR(devname);
        if (IS_ERR(devname))
                goto out;
-       retval = do_mount(devname, dirname, "ext2", flags, NULL);
+       retval = do_mount(devname->name, dirname, "ext2", flags, NULL);
        putname(devname);
  out:
        return retval;
@@ -469,7 +469,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
 {
        int retval;
        struct cdfs_args tmp;
-       char *devname;
+       struct filename *devname;
 
        retval = -EFAULT;
        if (copy_from_user(&tmp, args, sizeof(tmp)))
@@ -478,7 +478,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
        retval = PTR_ERR(devname);
        if (IS_ERR(devname))
                goto out;
-       retval = do_mount(devname, dirname, "iso9660", flags, NULL);
+       retval = do_mount(devname->name, dirname, "iso9660", flags, NULL);
        putname(devname);
  out:
        return retval;
@@ -499,7 +499,7 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path,
                int, flag, void __user *, data)
 {
        int retval;
-       char *name;
+       struct filename *name;
 
        name = getname(path);
        retval = PTR_ERR(name);
@@ -507,13 +507,13 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path,
                goto out;
        switch (typenr) {
        case 1:
-               retval = osf_ufs_mount(name, data, flag);
+               retval = osf_ufs_mount(name->name, data, flag);
                break;
        case 6:
-               retval = osf_cdfs_mount(name, data, flag);
+               retval = osf_cdfs_mount(name->name, data, flag);
                break;
        case 9:
-               retval = osf_procfs_mount(name, data, flag);
+               retval = osf_procfs_mount(name->name, data, flag);
                break;
        default:
                retval = -EINVAL;
index 83638aa096d562d803a8ffb3632dbb971db6da3d..4054e0ffe2b25a1055deb3946167755dc73fb201 100644 (file)
@@ -263,33 +263,35 @@ alpha_vfork(struct pt_regs *regs)
 
 /*
  * Copy an alpha thread..
- *
- * Note the "stack_offset" stuff: when returning to kernel mode, we need
- * to have some extra stack-space for the kernel stack that still exists
- * after the "ret_from_fork".  When returning to user mode, we only want
- * the space needed by the syscall stack frame (ie "struct pt_regs").
- * Use the passed "regs" pointer to determine how much space we need
- * for a kernel fork().
  */
 
 int
 copy_thread(unsigned long clone_flags, unsigned long usp,
-           unsigned long unused,
+           unsigned long arg,
            struct task_struct * p, struct pt_regs * regs)
 {
        extern void ret_from_fork(void);
+       extern void ret_from_kernel_thread(void);
 
        struct thread_info *childti = task_thread_info(p);
-       struct pt_regs * childregs;
-       struct switch_stack * childstack, *stack;
-       unsigned long stack_offset, settls;
-
-       stack_offset = PAGE_SIZE - sizeof(struct pt_regs);
-       if (!(regs->ps & 8))
-               stack_offset = (PAGE_SIZE-1) & (unsigned long) regs;
-       childregs = (struct pt_regs *)
-         (stack_offset + PAGE_SIZE + task_stack_page(p));
-               
+       struct pt_regs *childregs = task_pt_regs(p);
+       struct switch_stack *childstack, *stack;
+       unsigned long settls;
+
+       childstack = ((struct switch_stack *) childregs) - 1;
+       if (unlikely(!regs)) {
+               /* kernel thread */
+               memset(childstack, 0,
+                       sizeof(struct switch_stack) + sizeof(struct pt_regs));
+               childstack->r26 = (unsigned long) ret_from_kernel_thread;
+               childstack->r9 = usp;   /* function */
+               childstack->r10 = arg;
+               childregs->hae = alpha_mv.hae_cache,
+               childti->pcb.usp = 0;
+               childti->pcb.ksp = (unsigned long) childstack;
+               childti->pcb.flags = 1; /* set FEN, clear everything else */
+               return 0;
+       }
        *childregs = *regs;
        settls = regs->r20;
        childregs->r0 = 0;
@@ -297,7 +299,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
        childregs->r20 = 1;     /* OSF/1 has some strange fork() semantics.  */
        regs->r20 = 0;
        stack = ((struct switch_stack *) regs) - 1;
-       childstack = ((struct switch_stack *) childregs) - 1;
        *childstack = *stack;
        childstack->r26 = (unsigned long) ret_from_fork;
        childti->pcb.usp = usp;
@@ -385,27 +386,6 @@ dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task)
 }
 EXPORT_SYMBOL(dump_elf_task_fp);
 
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int
-do_sys_execve(const char __user *ufilename,
-             const char __user *const __user *argv,
-             const char __user *const __user *envp, struct pt_regs *regs)
-{
-       int error;
-       char *filename;
-
-       filename = getname(ufilename);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = do_execve(filename, argv, envp, regs);
-       putname(filename);
-out:
-       return error;
-}
-
 /*
  * Return saved PC of a blocked thread.  This assumes the frame
  * pointer is the 6th saved long on the kernel stack and that the
@@ -459,22 +439,3 @@ get_wchan(struct task_struct *p)
        }
        return pc;
 }
-
-int kernel_execve(const char *path, const char *const argv[], const char *const envp[])
-{
-       /* Avoid the HAE being gratuitously wrong, which would cause us
-          to do the whole turn off interrupts thing and restore it.  */
-       struct pt_regs regs = {.hae = alpha_mv.hae_cache};
-       int err = do_execve(path, argv, envp, &regs);
-       if (!err) {
-               struct pt_regs *p = current_pt_regs();
-               /* copy regs to normal position and off to userland we go... */
-               *p = regs;
-               __asm__ __volatile__ (
-                       "mov    %0, $sp;"
-                       "br     $31, ret_from_sys_call"
-                       : : "r"(p));
-       }
-       return err;
-}
-EXPORT_SYMBOL(kernel_execve);
index 54616f496aedb27629d298329a43ff8447113300..2a4a80ff4a2064262ea04298dee0a3d6e12f66be 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/signal.h>
+#include <linux/tracehook.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -312,25 +313,18 @@ long arch_ptrace(struct task_struct *child, long request,
        return ret;
 }
 
+asmlinkage unsigned long syscall_trace_enter(void)
+{
+       unsigned long ret = 0;
+       if (test_thread_flag(TIF_SYSCALL_TRACE) &&
+           tracehook_report_syscall_entry(current_pt_regs()))
+               ret = -1UL;
+       return ret ?: current_pt_regs()->r0;
+}
+
 asmlinkage void
-syscall_trace(void)
+syscall_trace_leave(void)
 {
-       if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               return;
-       if (!(current->ptrace & PT_PTRACED))
-               return;
-       /* The 0x80 provides a way for the tracing parent to distinguish
-          between a syscall stop and SIGTRAP delivery */
-       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-                                ? 0x80 : 0));
-
-       /*
-        * This isn't the same as continuing with a signal, but it will do
-        * for normal use.  strace only continues with a signal if the
-        * stopping signal is not SIGTRAP.  -brl
-        */
-       if (current->exit_code) {
-               send_sig(current->exit_code, current, 1);
-               current->exit_code = 0;
-       }
+       if (test_thread_flag(TIF_SYSCALL_TRACE))
+               tracehook_report_syscall_exit(current_pt_regs(), 0);
 }
index a8c97d42ec8eaef9215c32a40f743bd94505bc55..32575f85507d1a74d84198799dab405e07c94369 100644 (file)
@@ -298,8 +298,9 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 
 static long
 setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, 
-                struct switch_stack *sw, unsigned long mask, unsigned long sp)
+                unsigned long mask, unsigned long sp)
 {
+       struct switch_stack *sw = (struct switch_stack *)regs - 1;
        long i, err = 0;
 
        err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack);
@@ -354,7 +355,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 
 static int
 setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
-           struct pt_regs *regs, struct switch_stack * sw)
+           struct pt_regs *regs)
 {
        unsigned long oldsp, r26, err = 0;
        struct sigframe __user *frame;
@@ -364,7 +365,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
                return -EFAULT;
 
-       err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
+       err |= setup_sigcontext(&frame->sc, regs, set->sig[0], oldsp);
        if (err)
                return -EFAULT;
 
@@ -401,7 +402,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 
 static int
 setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-              sigset_t *set, struct pt_regs *regs, struct switch_stack * sw)
+              sigset_t *set, struct pt_regs *regs)
 {
        unsigned long oldsp, r26, err = 0;
        struct rt_sigframe __user *frame;
@@ -420,7 +421,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
        err |= __put_user(sas_ss_flags(oldsp), &frame->uc.uc_stack.ss_flags);
        err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
-       err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, sw,
+       err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, 
                                set->sig[0], oldsp);
        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
        if (err)
@@ -464,15 +465,15 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
  */
 static inline void
 handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
-             struct pt_regs * regs, struct switch_stack *sw)
+             struct pt_regs * regs)
 {
        sigset_t *oldset = sigmask_to_save();
        int ret;
 
        if (ka->sa.sa_flags & SA_SIGINFO)
-               ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
+               ret = setup_rt_frame(sig, ka, info, oldset, regs);
        else
-               ret = setup_frame(sig, ka, oldset, regs, sw);
+               ret = setup_frame(sig, ka, oldset, regs);
 
        if (ret) {
                force_sigsegv(sig, current);
@@ -519,8 +520,7 @@ syscall_restart(unsigned long r0, unsigned long r19,
  * all (if we get here from anything but a syscall return, it will be 0)
  */
 static void
-do_signal(struct pt_regs * regs, struct switch_stack * sw,
-         unsigned long r0, unsigned long r19)
+do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19)
 {
        siginfo_t info;
        int signr;
@@ -537,7 +537,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
                /* Whee!  Actually deliver the signal.  */
                if (r0)
                        syscall_restart(r0, r19, regs, &ka);
-               handle_signal(signr, &ka, &info, regs, sw);
+               handle_signal(signr, &ka, &info, regs);
                if (single_stepping) 
                        ptrace_set_bpt(current); /* re-set bpt */
                return;
@@ -568,15 +568,23 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
 }
 
 void
-do_notify_resume(struct pt_regs *regs, struct switch_stack *sw,
-                unsigned long thread_info_flags,
+do_work_pending(struct pt_regs *regs, unsigned long thread_flags,
                 unsigned long r0, unsigned long r19)
 {
-       if (thread_info_flags & _TIF_SIGPENDING)
-               do_signal(regs, sw, r0, r19);
-
-       if (thread_info_flags & _TIF_NOTIFY_RESUME) {
-               clear_thread_flag(TIF_NOTIFY_RESUME);
-               tracehook_notify_resume(regs);
-       }
+       do {
+               if (thread_flags & _TIF_NEED_RESCHED) {
+                       schedule();
+               } else {
+                       local_irq_enable();
+                       if (thread_flags & _TIF_SIGPENDING) {
+                               do_signal(regs, r0, r19);
+                               r0 = 0;
+                       } else {
+                               clear_thread_flag(TIF_NOTIFY_RESUME);
+                               tracehook_notify_resume(regs);
+                       }
+               }
+               local_irq_disable();
+               thread_flags = current_thread_info()->flags;
+       } while (thread_flags & _TIF_WORK_MASK);
 }
index 2867a7742306c3b9d3de7edbfd3d4f546e9c8cca..431c3753145a49c99bc144f63331f625fab22863 100644 (file)
@@ -52,6 +52,8 @@ config ARM
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
        select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        help
          The ARM series is a line of low-power-consumption RISC chip designs
          licensed by ARM Ltd and targeted at embedded applications and
@@ -493,7 +495,6 @@ config ARCH_IOP32X
        depends on MMU
        select CPU_XSCALE
        select NEED_MACH_GPIO_H
-       select NEED_MACH_IO_H
        select NEED_RET_TO_USER
        select PLAT_IOP
        select PCI
@@ -507,7 +508,6 @@ config ARCH_IOP33X
        depends on MMU
        select CPU_XSCALE
        select NEED_MACH_GPIO_H
-       select NEED_MACH_IO_H
        select NEED_RET_TO_USER
        select PLAT_IOP
        select PCI
@@ -1771,6 +1771,7 @@ source "mm/Kconfig"
 config FORCE_MAX_ZONEORDER
        int "Maximum zone order" if ARCH_SHMOBILE
        range 11 64 if ARCH_SHMOBILE
+       default "12" if SOC_AM33XX
        default "9" if SA1111
        default "11"
        help
index d0d441c429ae3e4e6c438fad1c51c7079c6eda5b..f79a08efe000aa490c1c010715cd0147baa869c0 100644 (file)
@@ -1,6 +1,7 @@
 ashldi3.S
 font.c
 lib1funcs.S
+hyp-stub.S
 piggy.gzip
 piggy.lzo
 piggy.lzma
index bb267562e7ed9a763218c83eaeb2c5c8645debb9..a517153a13eabdad582b6b6f75080cf93f699595 100644 (file)
@@ -30,6 +30,10 @@ FONTC        = $(srctree)/drivers/video/console/font_acorn_8x8.c
 OBJS           += string.o
 CFLAGS_string.o        := -Os
 
+ifeq ($(CONFIG_ARM_VIRT_EXT),y)
+OBJS           += hyp-stub.o
+endif
+
 #
 # Architecture dependencies
 #
@@ -126,7 +130,7 @@ KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
 endif
 
 ccflags-y := -fpic -fno-builtin -I$(obj)
-asflags-y := -Wa,-march=all
+asflags-y := -Wa,-march=all -DZIMAGE
 
 # Supply kernel BSS size to the decompressor via a linker symbol.
 KBSS_SZ = $(shell $(CROSS_COMPILE)size $(obj)/../../../../vmlinux | \
@@ -198,3 +202,6 @@ $(obj)/font.c: $(FONTC)
 
 $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile $(KCONFIG_CONFIG)
        @sed "$(SEDFLAGS)" < $< > $@
+
+$(obj)/hyp-stub.S: $(srctree)/arch/$(SRCARCH)/kernel/hyp-stub.S
+       $(call cmd,shipped)
index bc67cbff39448ff84a3f0c14cd22876975ee1965..90275f036cd14517affdb724ea4c6adf5194b72c 100644 (file)
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 /*
  * Debugging stuff
@@ -132,7 +133,12 @@ start:
                .word   start                   @ absolute load/run zImage address
                .word   _edata                  @ zImage end address
  THUMB(                .thumb                  )
-1:             mov     r7, r1                  @ save architecture ID
+1:
+               mrs     r9, cpsr
+#ifdef CONFIG_ARM_VIRT_EXT
+               bl      __hyp_stub_install      @ get into SVC mode, reversibly
+#endif
+               mov     r7, r1                  @ save architecture ID
                mov     r8, r2                  @ save atags pointer
 
 #ifndef __ARM_ARCH_2__
@@ -148,9 +154,9 @@ start:
  ARM(          swi     0x123456        )       @ angel_SWI_ARM
  THUMB(                svc     0xab            )       @ angel_SWI_THUMB
 not_angel:
-               mrs     r2, cpsr                @ turn off interrupts to
-               orr     r2, r2, #0xc0           @ prevent angel from running
-               msr     cpsr_c, r2
+               safe_svcmode_maskall r0
+               msr     spsr_cxsf, r9           @ Save the CPU boot mode in
+                                               @ SPSR
 #else
                teqp    pc, #0x0c000003         @ turn off interrupts
 #endif
@@ -350,6 +356,20 @@ dtb_check_done:
                adr     r5, restart
                bic     r5, r5, #31
 
+/* Relocate the hyp vector base if necessary */
+#ifdef CONFIG_ARM_VIRT_EXT
+               mrs     r0, spsr
+               and     r0, r0, #MODE_MASK
+               cmp     r0, #HYP_MODE
+               bne     1f
+
+               bl      __hyp_get_vectors
+               sub     r0, r0, r5
+               add     r0, r0, r10
+               bl      __hyp_set_vectors
+1:
+#endif
+
                sub     r9, r6, r5              @ size to copy
                add     r9, r9, #31             @ rounded up to a multiple
                bic     r9, r9, #31             @ ... of 32 bytes
@@ -458,11 +478,29 @@ not_relocated:    mov     r0, #0
                bl      decompress_kernel
                bl      cache_clean_flush
                bl      cache_off
-               mov     r0, #0                  @ must be zero
                mov     r1, r7                  @ restore architecture number
                mov     r2, r8                  @ restore atags pointer
- ARM(          mov     pc, r4  )               @ call kernel
- THUMB(                bx      r4      )               @ entry point is always ARM
+
+#ifdef CONFIG_ARM_VIRT_EXT
+               mrs     r0, spsr                @ Get saved CPU boot mode
+               and     r0, r0, #MODE_MASK
+               cmp     r0, #HYP_MODE           @ if not booted in HYP mode...
+               bne     __enter_kernel          @ boot kernel directly
+
+               adr     r12, .L__hyp_reentry_vectors_offset
+               ldr     r0, [r12]
+               add     r0, r0, r12
+
+               bl      __hyp_set_vectors
+               __HVC(0)                        @ otherwise bounce to hyp mode
+
+               b       .                       @ should never be reached
+
+               .align  2
+.L__hyp_reentry_vectors_offset:        .long   __hyp_reentry_vectors - .
+#else
+               b       __enter_kernel
+#endif
 
                .align  2
                .type   LC0, #object
@@ -1196,6 +1234,25 @@ memdump: mov     r12, r0
 #endif
 
                .ltorg
+
+#ifdef CONFIG_ARM_VIRT_EXT
+.align 5
+__hyp_reentry_vectors:
+               W(b)    .                       @ reset
+               W(b)    .                       @ undef
+               W(b)    .                       @ svc
+               W(b)    .                       @ pabort
+               W(b)    .                       @ dabort
+               W(b)    __enter_kernel          @ hyp
+               W(b)    .                       @ irq
+               W(b)    .                       @ fiq
+#endif /* CONFIG_ARM_VIRT_EXT */
+
+__enter_kernel:
+               mov     r0, #0                  @ must be 0
+ ARM(          mov     pc, r4  )               @ call kernel
+ THUMB(                bx      r4      )               @ entry point is always ARM
+
 reloc_code_end:
 
                .align
index 29f541f0e6530dde50cea5006cd2bbffc99ccfbf..c1ce813fcc4a1ea9094eb450ce4e50efd3d6048b 100644 (file)
@@ -25,14 +25,6 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
        exynos4210-trats.dtb \
        exynos5250-smdk5250.dtb
 dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb
-dtb-$(CONFIG_ARCH_IMX5) += imx51-babbage.dtb \
-       imx53-ard.dtb \
-       imx53-evk.dtb \
-       imx53-qsb.dtb \
-       imx53-smd.dtb
-dtb-$(CONFIG_SOC_IMX6Q) += imx6q-arm2.dtb \
-       imx6q-sabrelite.dtb \
-       imx6q-sabresd.dtb
 dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
 dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-dns320.dtb \
        kirkwood-dns325.dtb \
@@ -76,7 +68,9 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
        omap4-pandaES.dtb \
        omap4-var_som.dtb \
        omap4-sdp.dtb \
-       omap5-evm.dtb
+       omap5-evm.dtb \
+       am335x-evm.dtb \
+       am335x-bone.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
 dtb-$(CONFIG_ARCH_U8500) += snowball.dtb
 dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
@@ -104,5 +98,8 @@ dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \
        vexpress-v2p-ca15-tc1.dtb \
        vexpress-v2p-ca15_a7.dtb \
        xenvm-4.2.dtb
+dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \
+       wm8505-ref.dtb \
+       wm8650-mid.dtb
 
 endif
index 7c95f76398de401ac166af8f32d4a34a6b918e79..d410581a5a859901b32a49a1f037356c9f22e294 100644 (file)
@@ -28,6 +28,7 @@
                gpio2 = &pioC;
                tcb0 = &tcb0;
                tcb1 = &tcb1;
+               i2c0 = &i2c0;
        };
        cpus {
                cpu@0 {
                                status = "disabled";
                        };
 
+                       i2c0: i2c@fffac000 {
+                               compatible = "atmel,at91sam9260-i2c";
+                               reg = <0xfffac000 0x100>;
+                               interrupts = <11 4 6>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
                        adc0: adc@fffe0000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xfffe0000 0x100>;
index 195019b7ca0e046073361a587862c885c8fbfb7e..3e6e5c1abbf37184a44237e464080a52f4312e9f 100644 (file)
@@ -24,6 +24,7 @@
                gpio3 = &pioD;
                gpio4 = &pioE;
                tcb0 = &tcb0;
+               i2c0 = &i2c0;
        };
        cpus {
                cpu@0 {
                                interrupts = <24 4 2>;
                                status = "disabled";
                        };
+
+                       i2c0: i2c@fff88000 {
+                               compatible = "atmel,at91sam9263-i2c";
+                               reg = <0xfff88000 0x100>;
+                               interrupts = <13 4 6>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
                };
 
                nand0: nand@40000000 {
index 2a1d1ca8bd86636426bddfb77cf2ef8610bb8b16..75ce6e760016455cd1695ab1de148eabd807ca4b 100644 (file)
 
        ahb {
                apb {
+                       i2c0: i2c@fffac000 {
+                               compatible = "atmel,at91sam9g20-i2c";
+                       };
+
                        adc0: adc@fffe0000 {
                                atmel,adc-startup-time = <40>;
                        };
index 96514c134e54bafd1540c5f55524411b09f1e7a8..877c08f06763c643362eb41b8ebd058ac85abf7d 100644 (file)
                                phy-mode = "rmii";
                                status = "okay";
                        };
+
+                       i2c0: i2c@f8010000 {
+                               status = "okay";
+                       };
+
+                       i2c1: i2c@f8014000 {
+                               status = "okay";
+                       };
+
+                       i2c2: i2c@f8018000 {
+                               status = "okay";
+                       };
                };
 
                usb0: ohci@00600000 {
index 63751b1e744b42611f8e74d17738ccd69dd1efe1..3add030d61f8651fcf5a0476b11423897de71560 100644 (file)
@@ -29,6 +29,8 @@
                gpio4 = &pioE;
                tcb0 = &tcb0;
                tcb1 = &tcb1;
+               i2c0 = &i2c0;
+               i2c1 = &i2c1;
        };
        cpus {
                cpu@0 {
                                status = "disabled";
                        };
 
+                       i2c0: i2c@fff84000 {
+                               compatible = "atmel,at91sam9g10-i2c";
+                               reg = <0xfff84000 0x100>;
+                               interrupts = <12 4 6>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c1: i2c@fff88000 {
+                               compatible = "atmel,at91sam9g10-i2c";
+                               reg = <0xfff88000 0x100>;
+                               interrupts = <13 4 6>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
                        adc0: adc@fffb0000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xfffb0000 0x100>;
index a3633bd1311145168f36278afbed6dfe9e6bce76..15e1dd43f625aee627438c302e9a4a13f7002031 100644 (file)
                                phy-mode = "rmii";
                                status = "okay";
                        };
+
+                       i2c0: i2c@fff84000 {
+                               status = "okay";
+                       };
+
+                       i2c1: i2c@fff88000 {
+                               status = "okay";
+                       };
                };
 
                nand0: nand@40000000 {
index ef9336ae9614f85ffb0ce2348b69fc06b0f756e5..82508d68aa7edb0cdc98c5245d7872d47720dfd9 100644 (file)
@@ -26,6 +26,8 @@
                gpio3 = &pioD;
                tcb0 = &tcb0;
                tcb1 = &tcb1;
+               i2c0 = &i2c0;
+               i2c1 = &i2c1;
        };
        cpus {
                cpu@0 {
                                atmel,use-dma-tx;
                                status = "disabled";
                        };
+
+                       i2c0: i2c@f8010000 {
+                               compatible = "atmel,at91sam9x5-i2c";
+                               reg = <0xf8010000 0x100>;
+                               interrupts = <9 4 6>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c1: i2c@f8014000 {
+                               compatible = "atmel,at91sam9x5-i2c";
+                               reg = <0xf8014000 0x100>;
+                               interrupts = <10 4 6>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
                };
 
                nand0: nand@40000000 {
index f4e43e38f3a19e202fe07d88efb227b4e1d622ef..912b2c283d6f8d34ac7ac8273b8130360547ef81 100644 (file)
                        dbgu: serial@fffff200 {
                                status = "okay";
                        };
+
+                       i2c0: i2c@f8010000 {
+                               status = "okay";
+                       };
+
+                       i2c1: i2c@f8014000 {
+                               status = "okay";
+                       };
                };
 
                nand0: nand@40000000 {
index 8a387a8d61b745fc763c9e13f015896bc3e2bff7..03fc136421c5e31b01649c9caacdaf134bef4560 100644 (file)
@@ -27,6 +27,9 @@
                gpio3 = &pioD;
                tcb0 = &tcb0;
                tcb1 = &tcb1;
+               i2c0 = &i2c0;
+               i2c1 = &i2c1;
+               i2c2 = &i2c2;
        };
        cpus {
                cpu@0 {
                                status = "disabled";
                        };
 
+                       i2c0: i2c@f8010000 {
+                               compatible = "atmel,at91sam9x5-i2c";
+                               reg = <0xf8010000 0x100>;
+                               interrupts = <9 4 6>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c1: i2c@f8014000 {
+                               compatible = "atmel,at91sam9x5-i2c";
+                               reg = <0xf8014000 0x100>;
+                               interrupts = <10 4 6>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c2: i2c@f8018000 {
+                               compatible = "atmel,at91sam9x5-i2c";
+                               reg = <0xf8018000 0x100>;
+                               interrupts = <11 4 6>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
                        adc0: adc@f804c000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xf804c000 0x100>;
index 59fbfba23df8b237c6e775ef109106227a802903..e16d631554802f73227de6bcab58368d9e049227 100644 (file)
                                reg = <0x80058000 0x2000>;
                                interrupts = <111 68>;
                                clock-frequency = <100000>;
+                               fsl,i2c-dma-channel = <6>;
                                status = "disabled";
                        };
 
                                reg = <0x8005a000 0x2000>;
                                interrupts = <110 69>;
                                clock-frequency = <100000>;
+                               fsl,i2c-dma-channel = <7>;
                                status = "disabled";
                        };
 
index 2f71a91ca98e856263677bfd8c11ead4aafb1703..75d069fcf8979d9684d2c979badaacdb3d3a7876 100644 (file)
                                status = "disabled";
                        };
 
+                       nand@83fdb000 {
+                               compatible = "fsl,imx51-nand";
+                               reg = <0x83fdb000 0x1000 0xcfff0000 0x10000>;
+                               interrupts = <8>;
+                               status = "disabled";
+                       };
+
                        ssi3: ssi@83fe8000 {
                                compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
                                reg = <0x83fe8000 0x4000>;
index 221cf3321b0ade6ba6ee50df67d20a3a0510b74c..76ebb1ad2675334d38674fda586c9dee87d0cef8 100644 (file)
                                status = "disabled";
                        };
 
+                       nand@63fdb000 {
+                               compatible = "fsl,imx53-nand";
+                               reg = <0x63fdb000 0x1000 0xf7ff0000 0x10000>;
+                               interrupts = <8>;
+                               status = "disabled";
+                       };
+
                        ssi3: ssi@63fe8000 {
                                compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
                                reg = <0x63fe8000 0x4000>;
index 20b966ee1bb3cfd7addfbb4d07fb0391bc41dc42..e8f927cbb376b37ed3d30465cad847a57d9f8ce6 100644 (file)
        };
 };
 
+&omap4_pmx_core {
+       pinctrl-names = "default";
+       pinctrl-0 = <
+                       &twl6040_pins
+                       &mcpdm_pins
+                       &mcbsp1_pins
+       >;
+
+       twl6040_pins: pinmux_twl6040_pins {
+               pinctrl-single,pins = <
+                       0xe0 0x3        /* hdq_sio.gpio_127 OUTPUT | MODE3 */
+                       0x160 0x100     /* sys_nirq2.sys_nirq2 INPUT | MODE0 */
+               >;
+       };
+
+       mcpdm_pins: pinmux_mcpdm_pins {
+               pinctrl-single,pins = <
+                       0xc6 0x108      /* abe_pdm_ul_data.abe_pdm_ul_data INPUT PULLDOWN | MODE0 */
+                       0xc8 0x108      /* abe_pdm_dl_data.abe_pdm_dl_data INPUT PULLDOWN | MODE0 */
+                       0xca 0x118      /* abe_pdm_frame.abe_pdm_frame INPUT PULLUP | MODE0 */
+                       0xcc 0x108      /* abe_pdm_lb_clk.abe_pdm_lb_clk INPUT PULLDOWN | MODE0 */
+                       0xce 0x108      /* abe_clks.abe_clks INPUT PULLDOWN | MODE0 */
+               >;
+       };
+
+       mcbsp1_pins: pinmux_mcbsp1_pins {
+               pinctrl-single,pins = <
+                       0xbe 0x100      /* abe_mcbsp1_clkx.abe_mcbsp1_clkx INPUT | MODE0 */
+                       0xc0 0x108      /* abe_mcbsp1_dr.abe_mcbsp1_dr INPUT PULLDOWN | MODE0 */
+                       0xc2 0x8                /* abe_mcbsp1_dx.abe_mcbsp1_dx OUTPUT PULLDOWN | MODE0 */
+                       0xc4 0x100      /* abe_mcbsp1_fsx.abe_mcbsp1_fsx INPUT | MODE0 */
+               >;
+       };
+};
+
 &i2c1 {
        clock-frequency = <400000>;
 
        cs1-used;
        device-handle = <&elpida_ECB240ABACN>;
 };
+
+&mcbsp2 {
+       status = "disabled";
+};
+
+&mcbsp3 {
+       status = "disabled";
+};
+
+&dmic {
+       status = "disabled";
+};
index 94a23b39033ddcd9458b631ae894926ca420b422..5b7e04fbff500cf28b3338552b396745b30cac68 100644 (file)
 };
 
 &omap4_pmx_core {
+       pinctrl-names = "default";
+       pinctrl-0 = <
+                       &twl6040_pins
+                       &mcpdm_pins
+                       &dmic_pins
+                       &mcbsp1_pins
+                       &mcbsp2_pins
+       >;
+
        uart2_pins: pinmux_uart2_pins {
                pinctrl-single,pins = <
                        0xd8 0x118      /* uart2_cts.uart2_cts INPUT_PULLUP | MODE0 */
                        0x11e 0         /* uart4_tx.uart4_tx OUTPUT | MODE0 */
                >;
        };
+
+       twl6040_pins: pinmux_twl6040_pins {
+               pinctrl-single,pins = <
+                       0xe0 0x3        /* hdq_sio.gpio_127 OUTPUT | MODE3 */
+                       0x160 0x100     /* sys_nirq2.sys_nirq2 INPUT | MODE0 */
+               >;
+       };
+
+       mcpdm_pins: pinmux_mcpdm_pins {
+               pinctrl-single,pins = <
+                       0xc6 0x108      /* abe_pdm_ul_data.abe_pdm_ul_data INPUT PULLDOWN | MODE0 */
+                       0xc8 0x108      /* abe_pdm_dl_data.abe_pdm_dl_data INPUT PULLDOWN | MODE0 */
+                       0xca 0x118      /* abe_pdm_frame.abe_pdm_frame INPUT PULLUP | MODE0 */
+                       0xcc 0x108      /* abe_pdm_lb_clk.abe_pdm_lb_clk INPUT PULLDOWN | MODE0 */
+                       0xce 0x108      /* abe_clks.abe_clks INPUT PULLDOWN | MODE0 */
+               >;
+       };
+
+       dmic_pins: pinmux_dmic_pins {
+               pinctrl-single,pins = <
+                       0xd0 0          /* abe_dmic_clk1.abe_dmic_clk1 OUTPUT | MODE0 */
+                       0xd2 0x100      /* abe_dmic_din1.abe_dmic_din1 INPUT | MODE0 */
+                       0xd4 0x100      /* abe_dmic_din2.abe_dmic_din2 INPUT | MODE0 */
+                       0xd6 0x100      /* abe_dmic_din3.abe_dmic_din3 INPUT | MODE0 */
+               >;
+       };
+
+       mcbsp1_pins: pinmux_mcbsp1_pins {
+               pinctrl-single,pins = <
+                       0xbe 0x100      /* abe_mcbsp1_clkx.abe_mcbsp1_clkx INPUT | MODE0 */
+                       0xc0 0x108      /* abe_mcbsp1_dr.abe_mcbsp1_dr INPUT PULLDOWN | MODE0 */
+                       0xc2 0x8        /* abe_mcbsp1_dx.abe_mcbsp1_dx OUTPUT PULLDOWN | MODE0 */
+                       0xc4 0x100      /* abe_mcbsp1_fsx.abe_mcbsp1_fsx INPUT | MODE0 */
+               >;
+       };
+
+       mcbsp2_pins: pinmux_mcbsp2_pins {
+               pinctrl-single,pins = <
+                       0xb6 0x100      /* abe_mcbsp2_clkx.abe_mcbsp2_clkx INPUT | MODE0 */
+                       0xb8 0x108      /* abe_mcbsp2_dr.abe_mcbsp2_dr INPUT PULLDOWN | MODE0 */
+                       0xba 0x8        /* abe_mcbsp2_dx.abe_mcbsp2_dx OUTPUT PULLDOWN | MODE0 */
+                       0xbc 0x100      /* abe_mcbsp2_fsx.abe_mcbsp2_fsx INPUT | MODE0 */
+               >;
+       };
 };
 
 &i2c1 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart4_pins>;
 };
+
+&mcbsp3 {
+       status = "disabled";
+};
index 9c41a3f311aab25bd5e098d15c8f4cb5d5ee3695..c663eba73168adb8eb27edd7e15147440fae1af6 100644 (file)
 
 };
 
+&omap5_pmx_core {
+       pinctrl-names = "default";
+       pinctrl-0 = <
+                       &twl6040_pins
+                       &mcpdm_pins
+                       &dmic_pins
+                       &mcbsp1_pins
+                       &mcbsp2_pins
+       >;
+
+       twl6040_pins: pinmux_twl6040_pins {
+               pinctrl-single,pins = <
+                       0x18a 0x6       /* perslimbus2_clock.gpio5_145 OUTPUT | MODE6 */
+               >;
+       };
+
+       mcpdm_pins: pinmux_mcpdm_pins {
+               pinctrl-single,pins = <
+                       0x142 0x108     /* abe_clks.abe_clks INPUT PULLDOWN | MODE0 */
+                       0x15c 0x108     /* abemcpdm_ul_data.abemcpdm_ul_data INPUT PULLDOWN | MODE0 */
+                       0x15e 0x108     /* abemcpdm_dl_data.abemcpdm_dl_data INPUT PULLDOWN | MODE0 */
+                       0x160 0x118     /* abemcpdm_frame.abemcpdm_frame INPUT PULLUP | MODE0 */
+                       0x162 0x108     /* abemcpdm_lb_clk.abemcpdm_lb_clk INPUT PULLDOWN | MODE0 */
+               >;
+       };
+
+       dmic_pins: pinmux_dmic_pins {
+               pinctrl-single,pins = <
+                       0x144 0x100     /* abedmic_din1.abedmic_din1 INPUT | MODE0 */
+                       0x146 0x100     /* abedmic_din2.abedmic_din2 INPUT | MODE0 */
+                       0x148 0x100     /* abedmic_din3.abedmic_din3 INPUT | MODE0 */
+                       0x14a 0         /* abedmic_clk1.abedmic_clk1 OUTPUT | MODE0 */
+               >;
+       };
+
+       mcbsp1_pins: pinmux_mcbsp1_pins {
+               pinctrl-single,pins = <
+                       0x14c 0x101     /* abedmic_clk2.abemcbsp1_fsx INPUT | MODE1 */
+                       0x14e 0x9       /* abedmic_clk3.abemcbsp1_dx OUTPUT PULLDOWN | MODE1 */
+                       0x150 0x101     /* abeslimbus1_clock.abemcbsp1_clkx INPUT | MODE0 */
+                       0x152 0x109     /* abeslimbus1_data.abemcbsp1_dr INPUT PULLDOWN | MODE1 */
+               >;
+       };
+
+       mcbsp2_pins: pinmux_mcbsp2_pins {
+               pinctrl-single,pins = <
+                       0x154 0x108     /* abemcbsp2_dr.abemcbsp2_dr INPUT PULLDOWN | MODE0 */
+                       0x156 0x8       /* abemcbsp2_dx.abemcbsp2_dx OUTPUT PULLDOWN | MODE0 */
+                       0x158 0x100     /* abemcbsp2_fsx.abemcbsp2_fsx INPUT | MODE0 */
+                       0x15a 0x100     /* abemcbsp2_clkx.abemcbsp2_clkx INPUT | MODE0 */
+               >;
+       };
+};
+
 &mmc1 {
        vmmc-supply = <&vmmcsd_fixed>;
        bus-width = <4>;
                        0x020700d9>;    /* SEARCH */
        linux,input-no-autorepeat;
 };
+
+&mcbsp3 {
+       status = "disabled";
+};
index 5db33f481a331c29fb344ab304d0d6e0030c2686..42c78beb4fdc84c03c785bf50ac938d5d15063d1 100644 (file)
                ranges;
                ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
 
+               omap5_pmx_core: pinmux@4a002840 {
+                       compatible = "ti,omap4-padconf", "pinctrl-single";
+                       reg = <0x4a002840 0x01b6>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       pinctrl-single,register-width = <16>;
+                       pinctrl-single,function-mask = <0x7fff>;
+               };
+               omap5_pmx_wkup: pinmux@4ae0c840 {
+                       compatible = "ti,omap4-padconf", "pinctrl-single";
+                       reg = <0x4ae0c840 0x0038>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       pinctrl-single,register-width = <16>;
+                       pinctrl-single,function-mask = <0x7fff>;
+               };
+
                gic: interrupt-controller@48211000 {
                        compatible = "arm,cortex-a15-gic";
                        interrupt-controller;
index d71b8d581e3d39f77ea8d783303b9eb8a2388030..1e7c7a8e2123f63b3f671d4f5fcb8bd2fe1f8dd1 100644 (file)
@@ -80,8 +80,7 @@
                };
 
                sdhci@70000000 {
-                       int-gpio = <&gpio1 0 0>;
-                       power-gpio = <&gpio1 2 1>;
+                       cd-gpios = <&gpio1 0 0>;
                        status = "okay";
                };
 
index e4e912f9502466da3ab44a26eda9f8c83e383d8e..082328bd64abd1e09591b1555b7b130c35dd06a6 100644 (file)
                };
 
                sdhci@70000000 {
-                       power-gpio = <&gpio0 2 1>;
-                       power_always_enb;
                        status = "okay";
                };
 
index e60dc7124e9271b41c7fa27734cee825a3805365..f0ba901676ac640ddf5488ba51eb59d5ce38fd58 100644 (file)
                nvidia,invert-interrupt;
        };
 
-       memory-controller@0x7000f400 {
+       memory-controller@7000f400 {
                emc-table@190000 {
                        reg = <190000>;
                        compatible = "nvidia,tegra20-emc-table";
index 67a6cd910b9612d0a3aa7d206f1570a709a1226e..f3a09d0d45bc801a012fe7ea97f73548384ae9ad 100644 (file)
                reg = <0x7000e400 0x400>;
        };
 
-       memory-controller@0x7000f000 {
+       memory-controller@7000f000 {
                compatible = "nvidia,tegra20-mc";
                reg = <0x7000f000 0x024
                       0x7000f03c 0x3c4>;
                       0x58000000 0x02000000>;  /* GART aperture */
        };
 
-       memory-controller@0x7000f400 {
+       memory-controller@7000f400 {
                compatible = "nvidia,tegra20-emc";
                reg = <0x7000f400 0x200>;
                #address-cells = <1>;
index c4110d1b1f2db2e26ce32585a6a5c1e599550689..001f4913799c5a6c0d59159d4cc619456061f235 100644 (file)
@@ -284,11 +284,17 @@ int dma_set_coherent_mask(struct device *dev, u64 mask)
 
 int __init it8152_pci_setup(int nr, struct pci_sys_data *sys)
 {
-       it8152_io.start = IT8152_IO_BASE + 0x12000;
-       it8152_io.end   = IT8152_IO_BASE + 0x12000 + 0x100000;
+       /*
+        * FIXME: use pci_ioremap_io to remap the IO space here and
+        * move over to the generic io.h implementation.
+        * This requires solving the same problem for PXA PCMCIA
+        * support.
+        */
+       it8152_io.start = (unsigned long)IT8152_IO_BASE + 0x12000;
+       it8152_io.end   = (unsigned long)IT8152_IO_BASE + 0x12000 + 0x100000;
 
        sys->mem_offset = 0x10000000;
-       sys->io_offset  = IT8152_IO_BASE;
+       sys->io_offset  = (unsigned long)IT8152_IO_BASE;
 
        if (request_resource(&ioport_resource, &it8152_io)) {
                printk(KERN_ERR "PCI: unable to allocate IO region\n");
index cedc92ef88ab48e31b9901d964fd4071b8468501..14579711d8fc4482bfe058bfbe967cd8bb96f45a 100644 (file)
@@ -49,7 +49,6 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
 CONFIG_MTD_PLATRAM=m
 CONFIG_MTD_DATAFLASH=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_ATMEL=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
index e53c47563845e641c49d3081ec3dfa164c617c54..4b8a25d9e6867b9baf1fb15037de71f2a760d4e2 100644 (file)
@@ -97,7 +97,6 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_ROM=y
 CONFIG_MTD_COMPLEX_MAPPINGS=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_SHARPSL=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_IDE=y
index 8e97b2f7ceec571dbcf494b42cf22d526ecbcef8..806005a4c4c15cdeac19cbc6802494df0ff4e982 100644 (file)
@@ -61,7 +61,6 @@ CONFIG_MTD_CFI_STAA=y
 CONFIG_MTD_ROM=y
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_SCSI=y
index 082175c54e7cc7343a15c7d0f15f3ddbf5631c8a..00630e6af45c2199f68998dfa7d9b5450a205bd5 100644 (file)
@@ -102,7 +102,6 @@ CONFIG_MTD_CFI_STAA=y
 CONFIG_MTD_RAM=y
 CONFIG_MTD_ROM=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_S3C2410=y
 CONFIG_MTD_NAND_PLATFORM=y
 CONFIG_MTD_LPDDR=y
index 7305ebddb5105454edc11e353db1e6a864a87ed1..1f08219c1b3c68005f643ad8e5c23774c7f1bfd1 100644 (file)
@@ -49,7 +49,6 @@ CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_ORION=y
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_SCSI_PROC_FS is not set
index bf123c5384d4b345c3e0ddad9d8803c880410d59..240b25eea56559bb0588af7a048d720c15bb54ed 100644 (file)
@@ -57,7 +57,6 @@ CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ECC_SMC=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_NOMADIK=y
 CONFIG_MTD_ONENAND=y
 CONFIG_MTD_ONENAND_VERIFY_WRITE=y
index a288d7033950692f3ca05fee0501b3b091eb676b..cd5e6ba9a54da70d1896b0bcf1da731564dcd342 100644 (file)
@@ -72,7 +72,6 @@ CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_PLATFORM=y
 CONFIG_MTD_NAND_ORION=y
 CONFIG_BLK_DEV_LOOP=y
index 1677a0607ca9bd254b3794ef2c8770c87297e360..60e313834b3f97a4ddd5310b40d962f194cce2de 100644 (file)
@@ -36,7 +36,6 @@ CONFIG_MTD_CONCAT=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_PXA3xx=y
 CONFIG_MTD_NAND_PXA3xx_BUILTIN=y
 CONFIG_MTD_ONENAND=y
index 70158273c6dd617cdf60f0ef3ca9b23f8d2cd253..df77931a43262c4a6c2f0740a891bbe0d38dc5bb 100644 (file)
@@ -94,7 +94,6 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_ROM=y
 CONFIG_MTD_COMPLEX_MAPPINGS=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_SHARPSL=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_IDE=y
index 5c8b3bf4d8252f1013af6fea25848ce9c41dcfeb..2ef95813fce00b887dbd05020b35675870a7c929 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/domain.h>
+#include <asm/opcodes-virt.h>
 
 #define IOMEM(x)       (x)
 
        .endm
 #endif
 
+/*
+ * Helper macro to enter SVC mode cleanly and mask interrupts. reg is
+ * a scratch register for the macro to overwrite.
+ *
+ * This macro is intended for forcing the CPU into SVC mode at boot time.
+ * you cannot return to the original mode.
+ *
+ * Beware, it also clobers LR.
+ */
+.macro safe_svcmode_maskall reg:req
+       mrs     \reg , cpsr
+       mov     lr , \reg
+       and     lr , lr , #MODE_MASK
+       cmp     lr , #HYP_MODE
+       orr     \reg , \reg , #PSR_I_BIT | PSR_F_BIT
+       bic     \reg , \reg , #MODE_MASK
+       orr     \reg , \reg , #SVC_MODE
+THUMB( orr     \reg , \reg , #PSR_T_BIT        )
+       bne     1f
+       orr     \reg, \reg, #PSR_A_BIT
+       adr     lr, BSYM(2f)
+       msr     spsr_cxsf, \reg
+       __MSR_ELR_HYP(14)
+       __ERET
+1:     msr     cpsr_c, \reg
+2:
+.endm
+
 /*
  * STRT/LDRT access macros with ARM and Thumb-2 variants
  */
index e4448e16046dd32ab69ca17ef65a6b21745a3e0b..e1489c54cd12b4dcb8b997e8e327e2875b183b0c 100644 (file)
  *
  *             Unconditionally clean and invalidate the entire cache.
  *
+ *     flush_kern_louis()
+ *
+ *             Flush data cache levels up to the level of unification
+ *             inner shareable and invalidate the I-cache.
+ *             Only needed from v7 onwards, falls back to flush_cache_all()
+ *             for all other processor versions.
+ *
  *     flush_user_all()
  *
  *             Clean and invalidate all user space cache entries
 struct cpu_cache_fns {
        void (*flush_icache_all)(void);
        void (*flush_kern_all)(void);
+       void (*flush_kern_louis)(void);
        void (*flush_user_all)(void);
        void (*flush_user_range)(unsigned long, unsigned long, unsigned int);
 
@@ -119,6 +127,7 @@ extern struct cpu_cache_fns cpu_cache;
 
 #define __cpuc_flush_icache_all                cpu_cache.flush_icache_all
 #define __cpuc_flush_kern_all          cpu_cache.flush_kern_all
+#define __cpuc_flush_kern_louis                cpu_cache.flush_kern_louis
 #define __cpuc_flush_user_all          cpu_cache.flush_user_all
 #define __cpuc_flush_user_range                cpu_cache.flush_user_range
 #define __cpuc_coherent_kern_range     cpu_cache.coherent_kern_range
@@ -139,6 +148,7 @@ extern struct cpu_cache_fns cpu_cache;
 
 extern void __cpuc_flush_icache_all(void);
 extern void __cpuc_flush_kern_all(void);
+extern void __cpuc_flush_kern_louis(void);
 extern void __cpuc_flush_user_all(void);
 extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
 extern void __cpuc_coherent_kern_range(unsigned long, unsigned long);
@@ -204,6 +214,11 @@ static inline void __flush_icache_all(void)
        __flush_icache_preferred();
 }
 
+/*
+ * Flush caches up to Level of Unification Inner Shareable
+ */
+#define flush_cache_louis()            __cpuc_flush_kern_louis()
+
 #define flush_cache_all()              __cpuc_flush_kern_all()
 
 static inline void vivt_flush_cache_mm(struct mm_struct *mm)
index 4f8d2c0dc4419f702449132e46ae7f89bcf2865a..cca9f15704ed82bb2726ce8898611be42d28b5ff 100644 (file)
 #ifndef MULTI_CACHE
 #define __cpuc_flush_icache_all                __glue(_CACHE,_flush_icache_all)
 #define __cpuc_flush_kern_all          __glue(_CACHE,_flush_kern_cache_all)
+#define __cpuc_flush_kern_louis                __glue(_CACHE,_flush_kern_cache_louis)
 #define __cpuc_flush_user_all          __glue(_CACHE,_flush_user_cache_all)
 #define __cpuc_flush_user_range                __glue(_CACHE,_flush_user_cache_range)
 #define __cpuc_coherent_kern_range     __glue(_CACHE,_coherent_kern_range)
index b85665a96f8e329e2dc2494da1afb831f80f07e4..efcfdf92d9d5991ac618bf2ae608be27c44dc493 100644 (file)
        0xF7E08000 | (((imm16) & 0xF000) << 4) | ((imm16) & 0x0FFF)     \
 )
 
+#define __ERET __inst_arm_thumb32(                                     \
+       0xE160006E,                                                     \
+       0xF3DE8F00                                                      \
+)
+
+#define __MSR_ELR_HYP(regnum)  __inst_arm_thumb32(                     \
+       0xE12EF300 | regnum,                                            \
+       0xF3808E30 | (regnum << 16)                                     \
+)
+
 #endif /* ! __ASM_ARM_OPCODES_VIRT_H */
index 99afa7498260cdad985eaf9c74fd713095dd09f6..06e7d509eaac218864cc9d089ce9e6f4177c22f9 100644 (file)
@@ -85,11 +85,6 @@ unsigned long get_wchan(struct task_struct *p);
 #define cpu_relax()                    barrier()
 #endif
 
-/*
- * Create a new kernel thread
- */
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 #define task_pt_regs(p) \
        ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
 
index 355ece523f41f98d623f2c9af8d4d290a02af737..142d6ae4123150453d99aa9566767555afaa76f4 100644 (file)
@@ -44,6 +44,7 @@
 #define IRQ_MODE       0x00000012
 #define SVC_MODE       0x00000013
 #define ABT_MODE       0x00000017
+#define HYP_MODE       0x0000001a
 #define UND_MODE       0x0000001b
 #define SYSTEM_MODE    0x0000001f
 #define MODE32_BIT     0x00000010
@@ -254,6 +255,11 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
        return regs->ARM_sp;
 }
 
+#define current_pt_regs(void) ({                               \
+       register unsigned long sp asm ("sp");                   \
+       (struct pt_regs *)((sp | (THREAD_SIZE - 1)) - 7) - 1;   \
+})
+
 #endif /* __KERNEL__ */
 
 #endif /* __ASSEMBLY__ */
index 74542c52f9befa1d5f614b3d223291f0d4a0d2c4..368165e33c1ce5f012c3a7ee29b253a66f7c07e1 100644 (file)
@@ -2,7 +2,6 @@
 #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>
index f71cdab18b87589beb5d4df33bcae80483e71536..8477b4c1d39fb3fe43c21691d1ad46846a947e89 100644 (file)
@@ -151,7 +151,6 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 #define TIF_SYSCALL_TRACE      8
 #define TIF_SYSCALL_AUDIT      9
 #define TIF_SYSCALL_TRACEPOINT 10
-#define TIF_POLLING_NRFLAG     16
 #define TIF_USING_IWMMXT       17
 #define TIF_MEMDIE             18      /* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK    20
@@ -164,7 +163,6 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SYSCALL_TRACEPOINT        (1 << TIF_SYSCALL_TRACEPOINT)
-#define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
 #define _TIF_USING_IWMMXT      (1 << TIF_USING_IWMMXT)
 #define _TIF_SECCOMP           (1 << TIF_SECCOMP)
 
index d9ff5cc3a5060177be581772cf22ead601ad4f65..91819ad544242dc61706053cdff4dcb296e0a4f1 100644 (file)
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_SOCKETCALL
 #endif
+#define __ARCH_WANT_SYS_EXECVE
 
 /*
  * "Conditional" syscalls
index a7aadbd9a6dd2a1cbe18de85d6998c0ce0d8f53f..6a6f1e485f41a2b9402534c435b79c183cb5cdb2 100644 (file)
@@ -28,7 +28,7 @@
        ldr     \tmp, =elf_hwcap                    @ may not have MVFR regs
        ldr     \tmp, [\tmp, #0]
        tst     \tmp, #HWCAP_VFPv3D16
-       ldceq   p11, cr0, [\base],#32*4             @ FLDMIAD \base!, {d16-d31}
+       ldceql  p11, cr0, [\base],#32*4             @ FLDMIAD \base!, {d16-d31}
        addne   \base, \base, #32*4                 @ step over unused register space
 #else
        VFPFMRX \tmp, MVFR0                         @ Media and VFP Feature Register 0
@@ -52,7 +52,7 @@
        ldr     \tmp, =elf_hwcap                    @ may not have MVFR regs
        ldr     \tmp, [\tmp, #0]
        tst     \tmp, #HWCAP_VFPv3D16
-       stceq   p11, cr0, [\base],#32*4             @ FSTMIAD \base!, {d16-d31}
+       stceql  p11, cr0, [\base],#32*4             @ FSTMIAD \base!, {d16-d31}
        addne   \base, \base, #32*4                 @ step over unused register space
 #else
        VFPFMRX \tmp, MVFR0                         @ Media and VFP Feature Register 0
diff --git a/arch/arm/include/asm/virt.h b/arch/arm/include/asm/virt.h
new file mode 100644 (file)
index 0000000..86164df
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012 Linaro 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef VIRT_H
+#define VIRT_H
+
+#include <asm/ptrace.h>
+
+/*
+ * Flag indicating that the kernel was not entered in the same mode on every
+ * CPU.  The zImage loader stashes this value in an SPSR, so we need an
+ * architecturally defined flag bit here (the N flag, as it happens)
+ */
+#define BOOT_CPU_MODE_MISMATCH (1<<31)
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_ARM_VIRT_EXT
+/*
+ * __boot_cpu_mode records what mode the primary CPU was booted in.
+ * A correctly-implemented bootloader must start all CPUs in the same mode:
+ * if it fails to do this, the flag BOOT_CPU_MODE_MISMATCH is set to indicate
+ * that some CPU(s) were booted in a different mode.
+ *
+ * This allows the kernel to flag an error when the secondaries have come up.
+ */
+extern int __boot_cpu_mode;
+
+void __hyp_set_vectors(unsigned long phys_vector_base);
+unsigned long __hyp_get_vectors(void);
+#else
+#define __boot_cpu_mode        (SVC_MODE)
+#endif
+
+#ifndef ZIMAGE
+void hyp_mode_check(void);
+
+/* Reports the availability of HYP mode */
+static inline bool is_hyp_mode_available(void)
+{
+       return ((__boot_cpu_mode & MODE_MASK) == HYP_MODE &&
+               !(__boot_cpu_mode & BOOT_CPU_MODE_MISMATCH));
+}
+
+/* Check if the bootloader has booted CPUs in different modes */
+static inline bool is_hyp_mode_mismatched(void)
+{
+       return !!(__boot_cpu_mode & BOOT_CPU_MODE_MISMATCH);
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* ! VIRT_H */
index 5dfef9d97ed92b960d8d359997a20108759d60c8..5bbec7b8183e46e0d5ba4f078ba146789f409be1 100644 (file)
@@ -81,4 +81,6 @@ head-y                        := head$(MMUEXT).o
 obj-$(CONFIG_DEBUG_LL) += debug.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 
+obj-$(CONFIG_ARM_VIRT_EXT)     += hyp-stub.o
+
 extra-y := $(head-y) vmlinux.lds
index e337879595e565e5666cbd8ac0c40a4a72908c0e..831cd38c8d997b32f895fa077f3745c08879d99d 100644 (file)
@@ -20,7 +20,7 @@
                CALL(sys_creat)
                CALL(sys_link)
 /* 10 */       CALL(sys_unlink)
-               CALL(sys_execve_wrapper)
+               CALL(sys_execve)
                CALL(sys_chdir)
                CALL(OBSOLETE(sys_time))        /* used by libc4 */
                CALL(sys_mknod)
index f45987037bf1c4467396799a117245cfede3d0d1..417bac1846bdeb71dc475bfe7bee3e729623caa4 100644 (file)
@@ -86,8 +86,11 @@ ENDPROC(ret_to_user)
  */
 ENTRY(ret_from_fork)
        bl      schedule_tail
+       cmp     r5, #0
+       movne   r0, r4
+       movne   lr, pc
+       movne   pc, r5
        get_thread_info tsk
-       mov     why, #1
        b       ret_slow_syscall
 ENDPROC(ret_from_fork)
 
@@ -517,11 +520,6 @@ sys_vfork_wrapper:
                b       sys_vfork
 ENDPROC(sys_vfork_wrapper)
 
-sys_execve_wrapper:
-               add     r3, sp, #S_OFF
-               b       sys_execve
-ENDPROC(sys_execve_wrapper)
-
 sys_clone_wrapper:
                add     ip, sp, #S_OFF
                str     ip, [sp, #4]
index 9874d074119118f1d42abeee662beaa3433ca052..4eee351f4668e2bbee54c3771a5389ce8900c10c 100644 (file)
@@ -83,8 +83,12 @@ ENTRY(stext)
  THUMB(        .thumb                  )       @ switch to Thumb now.
  THUMB(1:                      )
 
-       setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
-                                               @ and irqs disabled
+#ifdef CONFIG_ARM_VIRT_EXT
+       bl      __hyp_stub_install
+#endif
+       @ ensure svc mode and all interrupts masked
+       safe_svcmode_maskall r9
+
        mrc     p15, 0, r9, c0, c0              @ get processor id
        bl      __lookup_processor_type         @ r5=procinfo r9=cpuid
        movs    r10, r5                         @ invalid processor (r5=0)?
@@ -326,7 +330,11 @@ ENTRY(secondary_startup)
         * the processor type - there is no need to check the machine type
         * as it has already been validated by the primary processor.
         */
-       setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9
+#ifdef CONFIG_ARM_VIRT_EXT
+       bl      __hyp_stub_install
+#endif
+       safe_svcmode_maskall r9
+
        mrc     p15, 0, r9, c0, c0              @ get processor id
        bl      __lookup_processor_type
        movs    r10, r5                         @ invalid processor?
diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S
new file mode 100644 (file)
index 0000000..65b2417
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2012 Linaro 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/virt.h>
+
+#ifndef ZIMAGE
+/*
+ * For the kernel proper, we need to find out the CPU boot mode long after
+ * boot, so we need to store it in a writable variable.
+ *
+ * This is not in .bss, because we set it sufficiently early that the boot-time
+ * zeroing of .bss would clobber it.
+ */
+.data
+ENTRY(__boot_cpu_mode)
+       .long   0
+.text
+
+       /*
+        * Save the primary CPU boot mode. Requires 3 scratch registers.
+        */
+       .macro  store_primary_cpu_mode  reg1, reg2, reg3
+       mrs     \reg1, cpsr
+       and     \reg1, \reg1, #MODE_MASK
+       adr     \reg2, .L__boot_cpu_mode_offset
+       ldr     \reg3, [\reg2]
+       str     \reg1, [\reg2, \reg3]
+       .endm
+
+       /*
+        * Compare the current mode with the one saved on the primary CPU.
+        * If they don't match, record that fact. The Z bit indicates
+        * if there's a match or not.
+        * Requires 3 additionnal scratch registers.
+        */
+       .macro  compare_cpu_mode_with_primary mode, reg1, reg2, reg3
+       adr     \reg2, .L__boot_cpu_mode_offset
+       ldr     \reg3, [\reg2]
+       ldr     \reg1, [\reg2, \reg3]
+       cmp     \mode, \reg1            @ matches primary CPU boot mode?
+       orrne   r7, r7, #BOOT_CPU_MODE_MISMATCH
+       strne   r7, [r5, r6]            @ record what happened and give up
+       .endm
+
+#else  /* ZIMAGE */
+
+       .macro  store_primary_cpu_mode  reg1:req, reg2:req, reg3:req
+       .endm
+
+/*
+ * The zImage loader only runs on one CPU, so we don't bother with mult-CPU
+ * consistency checking:
+ */
+       .macro  compare_cpu_mode_with_primary mode, reg1, reg2, reg3
+       cmp     \mode, \mode
+       .endm
+
+#endif /* ZIMAGE */
+
+/*
+ * Hypervisor stub installation functions.
+ *
+ * These must be called with the MMU and D-cache off.
+ * They are not ABI compliant and are only intended to be called from the kernel
+ * entry points in head.S.
+ */
+@ Call this from the primary CPU
+ENTRY(__hyp_stub_install)
+       store_primary_cpu_mode  r4, r5, r6
+ENDPROC(__hyp_stub_install)
+
+       @ fall through...
+
+@ Secondary CPUs should call here
+ENTRY(__hyp_stub_install_secondary)
+       mrs     r4, cpsr
+       and     r4, r4, #MODE_MASK
+
+       /*
+        * If the secondary has booted with a different mode, give up
+        * immediately.
+        */
+       compare_cpu_mode_with_primary   r4, r5, r6, r7
+       bxne    lr
+
+       /*
+        * Once we have given up on one CPU, we do not try to install the
+        * stub hypervisor on the remaining ones: because the saved boot mode
+        * is modified, it can't compare equal to the CPSR mode field any
+        * more.
+        *
+        * Otherwise...
+        */
+
+       cmp     r4, #HYP_MODE
+       bxne    lr                      @ give up if the CPU is not in HYP mode
+
+/*
+ * Configure HSCTLR to set correct exception endianness/instruction set
+ * state etc.
+ * Turn off all traps
+ * Eventually, CPU-specific code might be needed -- assume not for now
+ *
+ * This code relies on the "eret" instruction to synchronize the
+ * various coprocessor accesses.
+ */
+       @ Now install the hypervisor stub:
+       adr     r7, __hyp_stub_vectors
+       mcr     p15, 4, r7, c12, c0, 0  @ set hypervisor vector base (HVBAR)
+
+       @ Disable all traps, so we don't get any nasty surprise
+       mov     r7, #0
+       mcr     p15, 4, r7, c1, c1, 0   @ HCR
+       mcr     p15, 4, r7, c1, c1, 2   @ HCPTR
+       mcr     p15, 4, r7, c1, c1, 3   @ HSTR
+
+THUMB( orr     r7, #(1 << 30)  )       @ HSCTLR.TE
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       orr     r7, #(1 << 9)           @ HSCTLR.EE
+#endif
+       mcr     p15, 4, r7, c1, c0, 0   @ HSCTLR
+
+       mrc     p15, 4, r7, c1, c1, 1   @ HDCR
+       and     r7, #0x1f               @ Preserve HPMN
+       mcr     p15, 4, r7, c1, c1, 1   @ HDCR
+
+#if !defined(ZIMAGE) && defined(CONFIG_ARM_ARCH_TIMER)
+       @ make CNTP_* and CNTPCT accessible from PL1
+       mrc     p15, 0, r7, c0, c1, 1   @ ID_PFR1
+       lsr     r7, #16
+       and     r7, #0xf
+       cmp     r7, #1
+       bne     1f
+       mrc     p15, 4, r7, c14, c1, 0  @ CNTHCTL
+       orr     r7, r7, #3              @ PL1PCEN | PL1PCTEN
+       mcr     p15, 4, r7, c14, c1, 0  @ CNTHCTL
+1:
+#endif
+
+       bic     r7, r4, #MODE_MASK
+       orr     r7, r7, #SVC_MODE
+THUMB( orr     r7, r7, #PSR_T_BIT      )
+       msr     spsr_cxsf, r7           @ This is SPSR_hyp.
+
+       __MSR_ELR_HYP(14)               @ msr elr_hyp, lr
+       __ERET                          @ return, switching to SVC mode
+                                       @ The boot CPU mode is left in r4.
+ENDPROC(__hyp_stub_install_secondary)
+
+__hyp_stub_do_trap:
+       cmp     r0, #-1
+       mrceq   p15, 4, r0, c12, c0, 0  @ get HVBAR
+       mcrne   p15, 4, r0, c12, c0, 0  @ set HVBAR
+       __ERET
+ENDPROC(__hyp_stub_do_trap)
+
+/*
+ * __hyp_set_vectors: Call this after boot to set the initial hypervisor
+ * vectors as part of hypervisor installation.  On an SMP system, this should
+ * be called on each CPU.
+ *
+ * r0 must be the physical address of the new vector table (which must lie in
+ * the bottom 4GB of physical address space.
+ *
+ * r0 must be 32-byte aligned.
+ *
+ * Before calling this, you must check that the stub hypervisor is installed
+ * everywhere, by waiting for any secondary CPUs to be brought up and then
+ * checking that BOOT_CPU_MODE_HAVE_HYP(__boot_cpu_mode) is true.
+ *
+ * If not, there is a pre-existing hypervisor, some CPUs failed to boot, or
+ * something else went wrong... in such cases, trying to install a new
+ * hypervisor is unlikely to work as desired.
+ *
+ * When you call into your shiny new hypervisor, sp_hyp will contain junk,
+ * so you will need to set that to something sensible at the new hypervisor's
+ * initialisation entry point.
+ */
+ENTRY(__hyp_get_vectors)
+       mov     r0, #-1
+ENDPROC(__hyp_get_vectors)
+       @ fall through
+ENTRY(__hyp_set_vectors)
+       __HVC(0)
+       bx      lr
+ENDPROC(__hyp_set_vectors)
+
+#ifndef ZIMAGE
+.align 2
+.L__boot_cpu_mode_offset:
+       .long   __boot_cpu_mode - .
+#endif
+
+.align 5
+__hyp_stub_vectors:
+__hyp_stub_reset:      W(b)    .
+__hyp_stub_und:                W(b)    .
+__hyp_stub_svc:                W(b)    .
+__hyp_stub_pabort:     W(b)    .
+__hyp_stub_dabort:     W(b)    .
+__hyp_stub_trap:       W(b)    __hyp_stub_do_trap
+__hyp_stub_irq:                W(b)    .
+__hyp_stub_fiq:                W(b)    .
+ENDPROC(__hyp_stub_vectors)
+
index 04eea22d7958637f17456c7e2f37ac7b71e8e182..90084a6de35a75ede68e451a4f521e3a4174fc92 100644 (file)
@@ -381,13 +381,20 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
        struct thread_info *thread = task_thread_info(p);
        struct pt_regs *childregs = task_pt_regs(p);
 
-       *childregs = *regs;
-       childregs->ARM_r0 = 0;
-       childregs->ARM_sp = stack_start;
-
        memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
-       thread->cpu_context.sp = (unsigned long)childregs;
+
+       if (likely(regs)) {
+               *childregs = *regs;
+               childregs->ARM_r0 = 0;
+               childregs->ARM_sp = stack_start;
+       } else {
+               memset(childregs, 0, sizeof(struct pt_regs));
+               thread->cpu_context.r4 = stk_sz;
+               thread->cpu_context.r5 = stack_start;
+               childregs->ARM_cpsr = SVC_MODE;
+       }
        thread->cpu_context.pc = (unsigned long)ret_from_fork;
+       thread->cpu_context.sp = (unsigned long)childregs;
 
        clear_ptrace_hw_breakpoint(p);
 
@@ -423,63 +430,6 @@ int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
 }
 EXPORT_SYMBOL(dump_fpu);
 
-/*
- * Shuffle the argument into the correct register before calling the
- * thread function.  r4 is the thread argument, r5 is the pointer to
- * the thread function, and r6 points to the exit function.
- */
-extern void kernel_thread_helper(void);
-asm(   ".pushsection .text\n"
-"      .align\n"
-"      .type   kernel_thread_helper, #function\n"
-"kernel_thread_helper:\n"
-#ifdef CONFIG_TRACE_IRQFLAGS
-"      bl      trace_hardirqs_on\n"
-#endif
-"      msr     cpsr_c, r7\n"
-"      mov     r0, r4\n"
-"      mov     lr, r6\n"
-"      mov     pc, r5\n"
-"      .size   kernel_thread_helper, . - kernel_thread_helper\n"
-"      .popsection");
-
-#ifdef CONFIG_ARM_UNWIND
-extern void kernel_thread_exit(long code);
-asm(   ".pushsection .text\n"
-"      .align\n"
-"      .type   kernel_thread_exit, #function\n"
-"kernel_thread_exit:\n"
-"      .fnstart\n"
-"      .cantunwind\n"
-"      bl      do_exit\n"
-"      nop\n"
-"      .fnend\n"
-"      .size   kernel_thread_exit, . - kernel_thread_exit\n"
-"      .popsection");
-#else
-#define kernel_thread_exit     do_exit
-#endif
-
-/*
- * Create a kernel thread.
- */
-pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-
-       regs.ARM_r4 = (unsigned long)arg;
-       regs.ARM_r5 = (unsigned long)fn;
-       regs.ARM_r6 = (unsigned long)kernel_thread_exit;
-       regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE;
-       regs.ARM_pc = (unsigned long)kernel_thread_helper;
-       regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT;
-
-       return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 unsigned long get_wchan(struct task_struct *p)
 {
        struct stackframe frame;
index febafa0f552d6a75e2bc51755054a8b6e68cf5a8..da1d1aa20ad957ccd7021815014d12530de4f3a1 100644 (file)
@@ -53,6 +53,7 @@
 #include <asm/traps.h>
 #include <asm/unwind.h>
 #include <asm/memblock.h>
+#include <asm/virt.h>
 
 #include "atags.h"
 #include "tcm.h"
@@ -703,6 +704,21 @@ static int __init meminfo_cmp(const void *_a, const void *_b)
        return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
 }
 
+void __init hyp_mode_check(void)
+{
+#ifdef CONFIG_ARM_VIRT_EXT
+       if (is_hyp_mode_available()) {
+               pr_info("CPU: All CPU(s) started in HYP mode.\n");
+               pr_info("CPU: Virtualization extensions available.\n");
+       } else if (is_hyp_mode_mismatched()) {
+               pr_warn("CPU: WARNING: CPU(s) started in wrong/inconsistent modes (primary CPU mode 0x%x)\n",
+                       __boot_cpu_mode & MODE_MASK);
+               pr_warn("CPU: This may indicate a broken bootloader or firmware.\n");
+       } else
+               pr_info("CPU: All CPU(s) started in SVC mode.\n");
+#endif
+}
+
 void __init setup_arch(char **cmdline_p)
 {
        struct machine_desc *mdesc;
@@ -748,6 +764,10 @@ void __init setup_arch(char **cmdline_p)
                smp_init_cpus();
        }
 #endif
+
+       if (!is_smp())
+               hyp_mode_check();
+
        reserve_crashkernel();
 
        tcm_init();
index f27789e4e38aaad749e05426d042cffe7912b5c7..56f72d257ebdfcdfd8607fcc770eeecc61c24806 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/personality.h>
-#include <linux/freezer.h>
 #include <linux/uaccess.h>
 #include <linux/tracehook.h>
 
index d100eacdb7983f8e490a8dc88d4f830b7fab3b8c..8e20754dd31d5946f5297aae2023ae2c8d5cd572 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/ptrace.h>
 #include <asm/localtimer.h>
 #include <asm/smp_plat.h>
+#include <asm/virt.h>
 #include <asm/mach/arch.h>
 
 /*
@@ -202,8 +203,11 @@ int __cpuinit __cpu_disable(void)
        /*
         * Flush user cache and TLB mappings, and then remove this CPU
         * from the vm mask set of all processes.
+        *
+        * Caches are flushed to the Level of Unification Inner Shareable
+        * to write-back dirty lines to unified caches shared by all CPUs.
         */
-       flush_cache_all();
+       flush_cache_louis();
        local_flush_tlb_all();
 
        clear_tasks_mm_cpumask(cpu);
@@ -355,6 +359,8 @@ void __init smp_cpus_done(unsigned int max_cpus)
               num_online_cpus(),
               bogosum / (500000/HZ),
               (bogosum / (5000/HZ)) % 100);
+
+       hyp_mode_check();
 }
 
 void __init smp_prepare_boot_cpu(void)
index 1794cc3b0f1836583fec297ee484c554fdefffcd..358bca3a995ed37ec66da93ec40841abd99fa804 100644 (file)
@@ -17,6 +17,8 @@ extern void cpu_resume_mmu(void);
  */
 void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)
 {
+       u32 *ctx = ptr;
+
        *save_ptr = virt_to_phys(ptr);
 
        /* This must correspond to the LDM in cpu_resume() assembly */
@@ -26,7 +28,20 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)
 
        cpu_do_suspend(ptr);
 
-       flush_cache_all();
+       flush_cache_louis();
+
+       /*
+        * flush_cache_louis does not guarantee that
+        * save_ptr and ptr are cleaned to main memory,
+        * just up to the Level of Unification Inner Shareable.
+        * Since the context pointer and context itself
+        * are to be retrieved with the MMU off that
+        * data must be cleaned from all cache levels
+        * to main memory using "area" cache primitives.
+       */
+       __cpuc_flush_dcache_area(ctx, ptrsz);
+       __cpuc_flush_dcache_area(save_ptr, sizeof(*save_ptr));
+
        outer_clean_range(*save_ptr, *save_ptr + ptrsz);
        outer_clean_range(virt_to_phys(save_ptr),
                          virt_to_phys(save_ptr) + sizeof(*save_ptr));
index 76cbb055dd05ee2e8620bc1a3f1dc322f1333aeb..c2a898aa57aada4b16cff08ea6da84d797f88ab9 100644 (file)
@@ -59,69 +59,6 @@ asmlinkage int sys_vfork(struct pt_regs *regs)
        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
 }
 
-/* sys_execve() executes a new program.
- * This is called indirectly via a small wrapper
- */
-asmlinkage int sys_execve(const char __user *filenamei,
-                         const char __user *const __user *argv,
-                         const char __user *const __user *envp, struct pt_regs *regs)
-{
-       int error;
-       char * filename;
-
-       filename = getname(filenamei);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = do_execve(filename, argv, envp, regs);
-       putname(filename);
-out:
-       return error;
-}
-
-int kernel_execve(const char *filename,
-                 const char *const argv[],
-                 const char *const envp[])
-{
-       struct pt_regs regs;
-       int ret;
-
-       memset(&regs, 0, sizeof(struct pt_regs));
-       ret = do_execve(filename,
-                       (const char __user *const __user *)argv,
-                       (const char __user *const __user *)envp, &regs);
-       if (ret < 0)
-               goto out;
-
-       /*
-        * Save argc to the register structure for userspace.
-        */
-       regs.ARM_r0 = ret;
-
-       /*
-        * We were successful.  We won't be returning to our caller, but
-        * instead to user space by manipulating the kernel stack.
-        */
-       asm(    "add    r0, %0, %1\n\t"
-               "mov    r1, %2\n\t"
-               "mov    r2, %3\n\t"
-               "bl     memmove\n\t"    /* copy regs to top of stack */
-               "mov    r8, #0\n\t"     /* not a syscall */
-               "mov    r9, %0\n\t"     /* thread structure */
-               "mov    sp, r0\n\t"     /* reposition stack pointer */
-               "b      ret_to_user"
-               :
-               : "r" (current_thread_info()),
-                 "Ir" (THREAD_START_SP - sizeof(regs)),
-                 "r" (&regs),
-                 "Ir" (sizeof(regs))
-               : "r0", "r1", "r2", "r3", "r8", "r9", "ip", "lr", "memory");
-
- out:
-       return ret;
-}
-EXPORT_SYMBOL(kernel_execve);
-
 /*
  * Since loff_t is a 64 bit type we avoid a lot of ABI hassle
  * with a different argument ordering.
index 6f50c6722276dcc73f8607b51132bfe40dd077b9..b4f0565aff638af135c7797b430bbfeb2a29b439 100644 (file)
@@ -187,6 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200", &twi_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
index 9ac427a702da3d5cc25f380ededa12dcbcd73ed9..a563189cdfc3e1bfd4bdc2e71049073de01cd712 100644 (file)
@@ -511,7 +511,7 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91rm9200_twi_device = {
-       .name           = "at91_i2c",
+       .name           = "i2c-at91rm9200",
        .id             = -1,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
index 30c7f26a4668c34e3739955a782ef3ec2befb978..ad29f93f20cab175555cd2a8c2974deff0fe31fd 100644 (file)
@@ -211,6 +211,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
        CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20", &twi_clk),
        /* more usart lookup table for DT entries */
        CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
        CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
@@ -219,6 +221,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("usart", "fffd0000.serial", &usart3_clk),
        CLKDEV_CON_DEV_ID("usart", "fffd4000.serial", &usart4_clk),
        CLKDEV_CON_DEV_ID("usart", "fffd8000.serial", &usart5_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffac000.i2c", &twi_clk),
        /* more tc lookup table for DT entries */
        CLKDEV_CON_DEV_ID("t0_clk", "fffa0000.timer", &tc0_clk),
        CLKDEV_CON_DEV_ID("t1_clk", "fffa0000.timer", &tc1_clk),
index af50ff3281c7153b46ec054d3aa2c14488ea2fbb..a76b8684f52d07328fcfe2f4a08726124b643f5a 100644 (file)
@@ -421,7 +421,6 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9260_twi_device = {
-       .name           = "at91_i2c",
        .id             = -1,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
@@ -429,6 +428,13 @@ static struct platform_device at91sam9260_twi_device = {
 
 void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
 {
+       /* IP version is not the same on 9260 and g20 */
+       if (cpu_is_at91sam9g20()) {
+               at91sam9260_twi_device.name = "i2c-at91sam9g20";
+       } else {
+               at91sam9260_twi_device.name = "i2c-at91sam9260";
+       }
+
        /* pins used for TWI interface */
        at91_set_A_periph(AT91_PIN_PA23, 0);            /* TWD */
        at91_set_multi_drive(AT91_PIN_PA23, 1);
index f40762c5fedee898fb836b24556f50499ee2858e..8d999eb1a137f1ed72529d296774c084d17da1a4 100644 (file)
@@ -178,6 +178,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10", &twi_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
        CLKDEV_CON_ID("pioB", &pioB_clk),
        CLKDEV_CON_ID("pioC", &pioC_clk),
index 11e9fa835cde2e296f5c585a43fc8f1aecf48cff..9752f17efba9926501a23b8e5209fbabcdfedc6d 100644 (file)
@@ -317,7 +317,6 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9261_twi_device = {
-       .name           = "at91_i2c",
        .id             = -1,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
@@ -325,12 +324,19 @@ static struct platform_device at91sam9261_twi_device = {
 
 void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
 {
+       /* IP version is not the same on 9261 and g10 */
+       if (cpu_is_at91sam9g10()) {
+               at91sam9261_twi_device.name = "i2c-at91sam9g10";
+               /* I2C PIO must not be configured as open-drain on this chip */
+       } else {
+               at91sam9261_twi_device.name = "i2c-at91sam9261";
+               at91_set_multi_drive(AT91_PIN_PA7, 1);
+               at91_set_multi_drive(AT91_PIN_PA8, 1);
+       }
+
        /* pins used for TWI interface */
        at91_set_A_periph(AT91_PIN_PA7, 0);             /* TWD */
-       at91_set_multi_drive(AT91_PIN_PA7, 1);
-
        at91_set_A_periph(AT91_PIN_PA8, 0);             /* TWCK */
-       at91_set_multi_drive(AT91_PIN_PA8, 1);
 
        i2c_register_board_info(0, devices, nr_devices);
        platform_device_register(&at91sam9261_twi_device);
index 144ef5de51b6beaf3b989801277aabe94aefe97b..6a01d0360dfb8940cbaaa2affc9bb58f88d702d9 100644 (file)
@@ -193,6 +193,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
@@ -210,6 +211,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("hclk", "a00000.ohci", &ohci_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "fffa4000.spi", &spi0_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "fffa8000.spi", &spi1_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
index 7c0898fe20fa5850d174f69b2d43f48c645a6a30..8dde220b42b69c785c70118a16e48a1aa20acb95 100644 (file)
@@ -599,7 +599,7 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9263_twi_device = {
-       .name           = "at91_i2c",
+       .name           = "i2c-at91sam9260",
        .id             = -1,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
index ef6cedd52e3c2e71fdfb6dd8e68158b8ef622420..84af1b506d92a0b1e9e88c885b1d57be95fbf40b 100644 (file)
@@ -237,6 +237,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb0_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi0_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.1", &twi1_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
        CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
@@ -254,6 +256,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "fffd4000.timer", &tcb0_clk),
        CLKDEV_CON_DEV_ID("hclk", "700000.ohci", &uhphs_clk),
        CLKDEV_CON_DEV_ID("ehci_clk", "800000.ehci", &uhphs_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fff84000.i2c", &twi0_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi1_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
index e4c3b3709204256297f6887ed89ab74847159841..b1596072dcc23cd1414a8449eb4c25a35ed11222 100644 (file)
@@ -653,7 +653,7 @@ static struct resource twi0_resources[] = {
 };
 
 static struct platform_device at91sam9g45_twi0_device = {
-       .name           = "at91_i2c",
+       .name           = "i2c-at91sam9g10",
        .id             = 0,
        .resource       = twi0_resources,
        .num_resources  = ARRAY_SIZE(twi0_resources),
@@ -673,7 +673,7 @@ static struct resource twi1_resources[] = {
 };
 
 static struct platform_device at91sam9g45_twi1_device = {
-       .name           = "at91_i2c",
+       .name           = "i2c-at91sam9g10",
        .id             = 1,
        .resource       = twi1_resources,
        .num_resources  = ARRAY_SIZE(twi1_resources),
@@ -686,18 +686,12 @@ void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, in
        /* pins used for TWI interface */
        if (i2c_id == 0) {
                at91_set_A_periph(AT91_PIN_PA20, 0);            /* TWD */
-               at91_set_multi_drive(AT91_PIN_PA20, 1);
-
                at91_set_A_periph(AT91_PIN_PA21, 0);            /* TWCK */
-               at91_set_multi_drive(AT91_PIN_PA21, 1);
 
                platform_device_register(&at91sam9g45_twi0_device);
        } else {
                at91_set_A_periph(AT91_PIN_PB10, 0);            /* TWD */
-               at91_set_multi_drive(AT91_PIN_PB10, 1);
-
                at91_set_A_periph(AT91_PIN_PB11, 0);            /* TWCK */
-               at91_set_multi_drive(AT91_PIN_PB11, 1);
 
                platform_device_register(&at91sam9g45_twi1_device);
        }
index 08494664ab78d362fcc3b62878cff83ce2cd3921..732d3d3f4ec5f7f93430839330d0e473a8063c20 100644 (file)
@@ -169,6 +169,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb_clk),
        CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma_clk),
+       CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
+       CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
        CLKDEV_CON_ID("pioA", &pioAB_clk),
        CLKDEV_CON_ID("pioB", &pioAB_clk),
        CLKDEV_CON_ID("pioC", &pioCD_clk),
index 72ce50a50de5a278e21535422c1572bb95837a36..72e908412222615134fc0530cc339348093f76be 100644 (file)
@@ -186,6 +186,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi0_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.1", &twi1_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
        CLKDEV_CON_ID("pioB", &pioB_clk),
        CLKDEV_CON_ID("pioC", &pioC_clk),
index deafea0e493dd41c9a20e52acab75baca1badbf0..d6ca0543ce8d7f1054d8f25614cd17369efe283d 100644 (file)
@@ -346,7 +346,7 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9rl_twi_device = {
-       .name           = "at91_i2c",
+       .name           = "i2c-at91sam9g20",
        .id             = -1,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
index 477cf9d06672c7259cca0dab641bcb099de8e6b5..e5035380dcbce16e806fb460625fd73d9a3c1153 100644 (file)
@@ -231,6 +231,9 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
        CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma0_clk),
        CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk),
+       CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
+       CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
+       CLKDEV_CON_DEV_ID(NULL, "f8018000.i2c", &twi2_clk),
        CLKDEV_CON_ID("pioA", &pioAB_clk),
        CLKDEV_CON_ID("pioB", &pioAB_clk),
        CLKDEV_CON_ID("pioC", &pioCD_clk),
diff --git a/arch/arm/mach-at91/include/mach/at91_twi.h b/arch/arm/mach-at91/include/mach/at91_twi.h
deleted file mode 100644 (file)
index bb2880f..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_twi.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Two-wire Interface (TWI) registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * 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 AT91_TWI_H
-#define AT91_TWI_H
-
-#define        AT91_TWI_CR             0x00            /* Control Register */
-#define                AT91_TWI_START          (1 <<  0)       /* Send a Start Condition */
-#define                AT91_TWI_STOP           (1 <<  1)       /* Send a Stop Condition */
-#define                AT91_TWI_MSEN           (1 <<  2)       /* Master Transfer Enable */
-#define                AT91_TWI_MSDIS          (1 <<  3)       /* Master Transfer Disable */
-#define                AT91_TWI_SVEN           (1 <<  4)       /* Slave Transfer Enable [SAM9260 only] */
-#define                AT91_TWI_SVDIS          (1 <<  5)       /* Slave Transfer Disable [SAM9260 only] */
-#define                AT91_TWI_SWRST          (1 <<  7)       /* Software Reset */
-
-#define        AT91_TWI_MMR            0x04            /* Master Mode Register */
-#define                AT91_TWI_IADRSZ         (3    <<  8)    /* Internal Device Address Size */
-#define                        AT91_TWI_IADRSZ_NO              (0 << 8)
-#define                        AT91_TWI_IADRSZ_1               (1 << 8)
-#define                        AT91_TWI_IADRSZ_2               (2 << 8)
-#define                        AT91_TWI_IADRSZ_3               (3 << 8)
-#define                AT91_TWI_MREAD          (1    << 12)    /* Master Read Direction */
-#define                AT91_TWI_DADR           (0x7f << 16)    /* Device Address */
-
-#define        AT91_TWI_SMR            0x08            /* Slave Mode Register [SAM9260 only] */
-#define                AT91_TWI_SADR           (0x7f << 16)    /* Slave Address */
-
-#define        AT91_TWI_IADR           0x0c            /* Internal Address Register */
-
-#define        AT91_TWI_CWGR           0x10            /* Clock Waveform Generator Register */
-#define                AT91_TWI_CLDIV          (0xff <<  0)    /* Clock Low Divisor */
-#define                AT91_TWI_CHDIV          (0xff <<  8)    /* Clock High Divisor */
-#define                AT91_TWI_CKDIV          (7    << 16)    /* Clock Divider */
-
-#define        AT91_TWI_SR             0x20            /* Status Register */
-#define                AT91_TWI_TXCOMP         (1 <<  0)       /* Transmission Complete */
-#define                AT91_TWI_RXRDY          (1 <<  1)       /* Receive Holding Register Ready */
-#define                AT91_TWI_TXRDY          (1 <<  2)       /* Transmit Holding Register Ready */
-#define                AT91_TWI_SVREAD         (1 <<  3)       /* Slave Read [SAM9260 only] */
-#define                AT91_TWI_SVACC          (1 <<  4)       /* Slave Access [SAM9260 only] */
-#define                AT91_TWI_GACC           (1 <<  5)       /* General Call Access [SAM9260 only] */
-#define                AT91_TWI_OVRE           (1 <<  6)       /* Overrun Error [AT91RM9200 only] */
-#define                AT91_TWI_UNRE           (1 <<  7)       /* Underrun Error [AT91RM9200 only] */
-#define                AT91_TWI_NACK           (1 <<  8)       /* Not Acknowledged */
-#define                AT91_TWI_ARBLST         (1 <<  9)       /* Arbitration Lost [SAM9260 only] */
-#define                AT91_TWI_SCLWS          (1 << 10)       /* Clock Wait State [SAM9260 only] */
-#define                AT91_TWI_EOSACC         (1 << 11)       /* End of Slave Address [SAM9260 only] */
-
-#define        AT91_TWI_IER            0x24            /* Interrupt Enable Register */
-#define        AT91_TWI_IDR            0x28            /* Interrupt Disable Register */
-#define        AT91_TWI_IMR            0x2c            /* Interrupt Mask Register */
-#define        AT91_TWI_RHR            0x30            /* Receive Holding Register */
-#define        AT91_TWI_THR            0x34            /* Transmit Holding Register */
-
-#endif
-
index 2c2d86505a541fe1964f3f717d7e81c04f9e6a30..5315f05896e9e9b59d71aa0a2f95d8a4989c0e91 100644 (file)
@@ -153,7 +153,9 @@ static int at91_pm_verify_clocks(void)
                }
        }
 
-#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+       if (!IS_ENABLED(CONFIG_AT91_PROGRAMMABLE_CLOCKS))
+               return 1;
+
        /* PCK0..PCK3 must be disabled, or configured to use clk32k */
        for (i = 0; i < 4; i++) {
                u32 css;
@@ -167,7 +169,6 @@ static int at91_pm_verify_clocks(void)
                        return 0;
                }
        }
-#endif
 
        return 1;
 }
index e6f52de1062fd960fbd3fc015fb5c8e2211ba91f..da9881b161e1e15dc0693a74c2ce2716a0ebd5d3 100644 (file)
@@ -87,7 +87,7 @@ void __init at91_init_sram(int bank, unsigned long base, unsigned int length)
        iotable_init(desc, 1);
 }
 
-static struct map_desc at91_io_desc __initdata = {
+static struct map_desc at91_io_desc __initdata __maybe_unused = {
        .virtual        = (unsigned long)AT91_VA_BASE_SYS,
        .pfn            = __phys_to_pfn(AT91_BASE_SYS),
        .length         = SZ_16K,
index 3fb79a1d0bde3e94f9804d9d0a4f47e1e490a937..32871918bb6e7bbe1fb2e01de752d037e478c5a3 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
 
 #include <mach/hardware.h>
 #include <asm/sizes.h>
@@ -62,9 +64,26 @@ void __init autcpu12_map_io(void)
         iotable_init(autcpu12_io_desc, ARRAY_SIZE(autcpu12_io_desc));
 }
 
+static struct resource autcpu12_nvram_resource[] __initdata = {
+       DEFINE_RES_MEM_NAMED(AUTCPU12_PHYS_NVRAM, SZ_128K, "SRAM"),
+};
+
+static struct platform_device autcpu12_nvram_pdev __initdata = {
+       .name           = "autcpu12_nvram",
+       .id             = -1,
+       .resource       = autcpu12_nvram_resource,
+       .num_resources  = ARRAY_SIZE(autcpu12_nvram_resource),
+};
+
+static void __init autcpu12_init(void)
+{
+       platform_device_register(&autcpu12_nvram_pdev);
+}
+
 MACHINE_START(AUTCPU12, "autronix autcpu12")
        /* Maintainer: Thomas Gleixner */
        .atag_offset    = 0x20000,
+       .init_machine   = autcpu12_init,
        .map_io         = autcpu12_map_io,
        .init_irq       = clps711x_init_irq,
        .timer          = &clps711x_timer,
index ab99c3c3b752689e50db5720e2d36beb23ee2b21..026b4b277ae5d54e4d911f69c91c7bfee21ea68d 100644 (file)
@@ -186,6 +186,13 @@ config DA850_UI_RMII
          NOTE: Please take care while choosing this option, MII PHY will
          not be functional if RMII mode is selected.
 
+config DA850_UI_SD_VIDEO_PORT
+       bool "Video Port Interface"
+       help
+         Say Y if you want to use Video Port Interface (VPIF) on the
+         DA850/OMAP-L138 EVM. The Video decoders/encoders are found on the
+         UI daughter card that is supplied with the EVM.
+
 endchoice
 
 config DA850_WL12XX
index 1295e616ceee7e32a5b31d62b3cf52a4286578b3..32ee3f89596738d988a00105c0358d4ff1a61f1b 100644 (file)
@@ -45,6 +45,9 @@
 #include <linux/platform_data/mtd-davinci-aemif.h>
 #include <linux/platform_data/spi-davinci.h>
 
+#include <media/tvp514x.h>
+#include <media/adv7343.h>
+
 #define DA850_EVM_PHY_ID               "davinci_mdio-0:00"
 #define DA850_LCD_PWR_PIN              GPIO_TO_PIN(2, 8)
 #define DA850_LCD_BL_PIN               GPIO_TO_PIN(2, 15)
@@ -452,6 +455,15 @@ static void da850_evm_ui_keys_init(unsigned gpio)
        }
 }
 
+#ifdef CONFIG_DA850_UI_SD_VIDEO_PORT
+static inline void da850_evm_setup_video_port(int video_sel)
+{
+       gpio_set_value_cansleep(video_sel, 0);
+}
+#else
+static inline void da850_evm_setup_video_port(int video_sel) { }
+#endif
+
 static int da850_evm_ui_expander_setup(struct i2c_client *client, unsigned gpio,
                                                unsigned ngpio, void *c)
 {
@@ -497,6 +509,8 @@ static int da850_evm_ui_expander_setup(struct i2c_client *client, unsigned gpio,
 
        da850_evm_setup_emac_rmii(sel_a);
 
+       da850_evm_setup_video_port(sel_c);
+
        return 0;
 
 exp_setup_keys_fail:
@@ -1149,6 +1163,169 @@ static __init int da850_evm_init_cpufreq(void)
 static __init int da850_evm_init_cpufreq(void) { return 0; }
 #endif
 
+#if defined(CONFIG_DA850_UI_SD_VIDEO_PORT)
+
+#define TVP5147_CH0            "tvp514x-0"
+#define TVP5147_CH1            "tvp514x-1"
+
+/* VPIF capture configuration */
+static struct tvp514x_platform_data tvp5146_pdata = {
+               .clk_polarity = 0,
+               .hs_polarity  = 1,
+               .vs_polarity  = 1,
+};
+
+#define TVP514X_STD_ALL (V4L2_STD_NTSC | V4L2_STD_PAL)
+
+static const struct vpif_input da850_ch0_inputs[] = {
+       {
+               .input = {
+                       .index = 0,
+                       .name  = "Composite",
+                       .type  = V4L2_INPUT_TYPE_CAMERA,
+                       .capabilities = V4L2_IN_CAP_STD,
+                       .std   = TVP514X_STD_ALL,
+               },
+               .input_route = INPUT_CVBS_VI2B,
+               .output_route = OUTPUT_10BIT_422_EMBEDDED_SYNC,
+               .subdev_name = TVP5147_CH0,
+       },
+};
+
+static const struct vpif_input da850_ch1_inputs[] = {
+       {
+               .input = {
+                       .index = 0,
+                       .name  = "S-Video",
+                       .type  = V4L2_INPUT_TYPE_CAMERA,
+                       .capabilities = V4L2_IN_CAP_STD,
+                       .std   = TVP514X_STD_ALL,
+               },
+               .input_route = INPUT_SVIDEO_VI2C_VI1C,
+               .output_route = OUTPUT_10BIT_422_EMBEDDED_SYNC,
+               .subdev_name = TVP5147_CH1,
+       },
+};
+
+static struct vpif_subdev_info da850_vpif_capture_sdev_info[] = {
+       {
+               .name = TVP5147_CH0,
+               .board_info = {
+                       I2C_BOARD_INFO("tvp5146", 0x5d),
+                       .platform_data = &tvp5146_pdata,
+               },
+       },
+       {
+               .name = TVP5147_CH1,
+               .board_info = {
+                       I2C_BOARD_INFO("tvp5146", 0x5c),
+                       .platform_data = &tvp5146_pdata,
+               },
+       },
+};
+
+static struct vpif_capture_config da850_vpif_capture_config = {
+       .subdev_info = da850_vpif_capture_sdev_info,
+       .subdev_count = ARRAY_SIZE(da850_vpif_capture_sdev_info),
+       .chan_config[0] = {
+               .inputs = da850_ch0_inputs,
+               .input_count = ARRAY_SIZE(da850_ch0_inputs),
+               .vpif_if = {
+                       .if_type = VPIF_IF_BT656,
+                       .hd_pol  = 1,
+                       .vd_pol  = 1,
+                       .fid_pol = 0,
+               },
+       },
+       .chan_config[1] = {
+               .inputs = da850_ch1_inputs,
+               .input_count = ARRAY_SIZE(da850_ch1_inputs),
+               .vpif_if = {
+                       .if_type = VPIF_IF_BT656,
+                       .hd_pol  = 1,
+                       .vd_pol  = 1,
+                       .fid_pol = 0,
+               },
+       },
+       .card_name = "DA850/OMAP-L138 Video Capture",
+};
+
+/* VPIF display configuration */
+static struct vpif_subdev_info da850_vpif_subdev[] = {
+       {
+               .name = "adv7343",
+               .board_info = {
+                       I2C_BOARD_INFO("adv7343", 0x2a),
+               },
+       },
+};
+
+static const struct vpif_output da850_ch0_outputs[] = {
+       {
+               .output = {
+                       .index = 0,
+                       .name = "Composite",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_COMPOSITE_ID,
+       },
+       {
+               .output = {
+                       .index = 1,
+                       .name = "S-Video",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_SVIDEO_ID,
+       },
+};
+
+static struct vpif_display_config da850_vpif_display_config = {
+       .subdevinfo   = da850_vpif_subdev,
+       .subdev_count = ARRAY_SIZE(da850_vpif_subdev),
+       .chan_config[0] = {
+               .outputs = da850_ch0_outputs,
+               .output_count = ARRAY_SIZE(da850_ch0_outputs),
+       },
+       .card_name    = "DA850/OMAP-L138 Video Display",
+};
+
+static __init void da850_vpif_init(void)
+{
+       int ret;
+
+       ret = da850_register_vpif();
+       if (ret)
+               pr_warn("da850_evm_init: VPIF setup failed: %d\n", ret);
+
+       ret = davinci_cfg_reg_list(da850_vpif_capture_pins);
+       if (ret)
+               pr_warn("da850_evm_init: VPIF capture mux setup failed: %d\n",
+                       ret);
+
+       ret = da850_register_vpif_capture(&da850_vpif_capture_config);
+       if (ret)
+               pr_warn("da850_evm_init: VPIF capture setup failed: %d\n", ret);
+
+       ret = davinci_cfg_reg_list(da850_vpif_display_pins);
+       if (ret)
+               pr_warn("da850_evm_init: VPIF display mux setup failed: %d\n",
+                       ret);
+
+       ret = da850_register_vpif_display(&da850_vpif_display_config);
+       if (ret)
+               pr_warn("da850_evm_init: VPIF display setup failed: %d\n", ret);
+}
+
+#else
+static __init void da850_vpif_init(void) {}
+#endif
+
 #ifdef CONFIG_DA850_WL12XX
 
 static void wl12xx_set_power(int index, bool power_on)
@@ -1375,6 +1552,8 @@ static __init void da850_evm_init(void)
                pr_warning("da850_evm_init: suspend registration failed: %d\n",
                                ret);
 
+       da850_vpif_init();
+
        ret = da8xx_register_spi(1, da850evm_spi_info,
                                 ARRAY_SIZE(da850evm_spi_info));
        if (ret)
index ca72fc4b8ccaac489b3e5e4e800e84e73730149e..f22572cee49d89ade236851a04fdf2ba94fed2e6 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/phy.h>
 #include <linux/clk.h>
 #include <linux/videodev2.h>
+#include <linux/v4l2-dv-timings.h>
 #include <linux/export.h>
 
 #include <media/tvp514x.h>
@@ -620,7 +621,7 @@ static struct vpbe_enc_mode_info dm644xevm_enc_std_timing[] = {
        {
                .name           = "ntsc",
                .timings_type   = VPBE_ENC_STD,
-               .timings        = {V4L2_STD_525_60},
+               .std_id         = V4L2_STD_525_60,
                .interlaced     = 1,
                .xres           = 720,
                .yres           = 480,
@@ -632,7 +633,7 @@ static struct vpbe_enc_mode_info dm644xevm_enc_std_timing[] = {
        {
                .name           = "pal",
                .timings_type   = VPBE_ENC_STD,
-               .timings        = {V4L2_STD_625_50},
+               .std_id         = V4L2_STD_625_50,
                .interlaced     = 1,
                .xres           = 720,
                .yres           = 576,
@@ -647,8 +648,8 @@ static struct vpbe_enc_mode_info dm644xevm_enc_std_timing[] = {
 static struct vpbe_enc_mode_info dm644xevm_enc_preset_timing[] = {
        {
                .name           = "480p59_94",
-               .timings_type   = VPBE_ENC_DV_PRESET,
-               .timings        = {V4L2_DV_480P59_94},
+               .timings_type   = VPBE_ENC_CUSTOM_TIMINGS,
+               .dv_timings     = V4L2_DV_BT_CEA_720X480P59_94,
                .interlaced     = 0,
                .xres           = 720,
                .yres           = 480,
@@ -659,8 +660,8 @@ static struct vpbe_enc_mode_info dm644xevm_enc_preset_timing[] = {
        },
        {
                .name           = "576p50",
-               .timings_type   = VPBE_ENC_DV_PRESET,
-               .timings        = {V4L2_DV_576P50},
+               .timings_type   = VPBE_ENC_CUSTOM_TIMINGS,
+               .dv_timings     = V4L2_DV_BT_CEA_720X576P50,
                .interlaced     = 0,
                .xres           = 720,
                .yres           = 576,
@@ -698,7 +699,7 @@ static struct vpbe_output dm644xevm_vpbe_outputs[] = {
                        .index          = 1,
                        .name           = "Component",
                        .type           = V4L2_OUTPUT_TYPE_ANALOG,
-                       .capabilities   = V4L2_OUT_CAP_PRESETS,
+                       .capabilities   = V4L2_OUT_CAP_DV_TIMINGS,
                },
                .subdev_name    = VPBE_VENC_SUBDEV_NAME,
                .default_mode   = "480p59_94",
index 9944367b4931b9a630a5bd91db7d6e784aebf75f..1dbf85beed1baaf55718a7f00debd3416327e66d 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/i2c/pcf857x.h>
 
 #include <media/tvp514x.h>
+#include <media/adv7343.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -496,18 +497,49 @@ static struct vpif_subdev_info dm646x_vpif_subdev[] = {
        },
 };
 
-static const char *output[] = {
-       "Composite",
-       "Component",
-       "S-Video",
+static const struct vpif_output dm6467_ch0_outputs[] = {
+       {
+               .output = {
+                       .index = 0,
+                       .name = "Composite",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_COMPOSITE_ID,
+       },
+       {
+               .output = {
+                       .index = 1,
+                       .name = "Component",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_CUSTOM_TIMINGS,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_COMPONENT_ID,
+       },
+       {
+               .output = {
+                       .index = 2,
+                       .name = "S-Video",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_SVIDEO_ID,
+       },
 };
 
 static struct vpif_display_config dm646x_vpif_display_config = {
        .set_clock      = set_vpif_clock,
        .subdevinfo     = dm646x_vpif_subdev,
        .subdev_count   = ARRAY_SIZE(dm646x_vpif_subdev),
-       .output         = output,
-       .output_count   = ARRAY_SIZE(output),
+       .chan_config[0] = {
+               .outputs = dm6467_ch0_outputs,
+               .output_count = ARRAY_SIZE(dm6467_ch0_outputs),
+       },
        .card_name      = "DM646x EVM",
 };
 
@@ -601,15 +633,6 @@ static struct vpif_subdev_info vpif_capture_sdev_info[] = {
                        I2C_BOARD_INFO("tvp5146", 0x5d),
                        .platform_data = &tvp5146_pdata,
                },
-               .input = INPUT_CVBS_VI2B,
-               .output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
-               .can_route = 1,
-               .vpif_if = {
-                       .if_type = VPIF_IF_BT656,
-                       .hd_pol = 1,
-                       .vd_pol = 1,
-                       .fid_pol = 0,
-               },
        },
        {
                .name   = TVP5147_CH1,
@@ -617,15 +640,6 @@ static struct vpif_subdev_info vpif_capture_sdev_info[] = {
                        I2C_BOARD_INFO("tvp5146", 0x5c),
                        .platform_data = &tvp5146_pdata,
                },
-               .input = INPUT_SVIDEO_VI2C_VI1C,
-               .output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
-               .can_route = 1,
-               .vpif_if = {
-                       .if_type = VPIF_IF_BT656,
-                       .hd_pol = 1,
-                       .vd_pol = 1,
-                       .fid_pol = 0,
-               },
        },
 };
 
@@ -635,9 +649,12 @@ static const struct vpif_input dm6467_ch0_inputs[] = {
                        .index = 0,
                        .name = "Composite",
                        .type = V4L2_INPUT_TYPE_CAMERA,
+                       .capabilities = V4L2_IN_CAP_STD,
                        .std = TVP514X_STD_ALL,
                },
                .subdev_name = TVP5147_CH0,
+               .input_route = INPUT_CVBS_VI2B,
+               .output_route = OUTPUT_10BIT_422_EMBEDDED_SYNC,
        },
 };
 
@@ -647,9 +664,12 @@ static const struct vpif_input dm6467_ch1_inputs[] = {
                        .index = 0,
                        .name = "S-Video",
                        .type = V4L2_INPUT_TYPE_CAMERA,
+                       .capabilities = V4L2_IN_CAP_STD,
                        .std = TVP514X_STD_ALL,
                },
                .subdev_name = TVP5147_CH1,
+               .input_route = INPUT_SVIDEO_VI2C_VI1C,
+               .output_route = OUTPUT_10BIT_422_EMBEDDED_SYNC,
        },
 };
 
@@ -661,10 +681,22 @@ static struct vpif_capture_config dm646x_vpif_capture_cfg = {
        .chan_config[0] = {
                .inputs = dm6467_ch0_inputs,
                .input_count = ARRAY_SIZE(dm6467_ch0_inputs),
+               .vpif_if = {
+                       .if_type = VPIF_IF_BT656,
+                       .hd_pol = 1,
+                       .vd_pol = 1,
+                       .fid_pol = 0,
+               },
        },
        .chan_config[1] = {
                .inputs = dm6467_ch1_inputs,
                .input_count = ARRAY_SIZE(dm6467_ch1_inputs),
+               .vpif_if = {
+                       .if_type = VPIF_IF_BT656,
+                       .hd_pol = 1,
+                       .vd_pol = 1,
+                       .fid_pol = 0,
+               },
        },
 };
 
index 6676dee7104ec6abdbc1b31fa82ae801a119a492..b90c172d55413dc6e301ba15afff70f721d3c704 100644 (file)
@@ -347,6 +347,13 @@ static struct clk spi1_clk = {
        .flags          = DA850_CLK_ASYNC3,
 };
 
+static struct clk vpif_clk = {
+       .name           = "vpif",
+       .parent         = &pll0_sysclk2,
+       .lpsc           = DA850_LPSC1_VPIF,
+       .gpsc           = 1,
+};
+
 static struct clk sata_clk = {
        .name           = "sata",
        .parent         = &pll0_sysclk2,
@@ -397,6 +404,7 @@ static struct clk_lookup da850_clks[] = {
        CLK(NULL,               "usb20",        &usb20_clk),
        CLK("spi_davinci.0",    NULL,           &spi0_clk),
        CLK("spi_davinci.1",    NULL,           &spi1_clk),
+       CLK("vpif",             NULL,           &vpif_clk),
        CLK("ahci",             NULL,           &sata_clk),
        CLK(NULL,               NULL,           NULL),
 };
@@ -573,6 +581,46 @@ static const struct mux_config da850_pins[] = {
        MUX_CFG(DA850, GPIO6_10,        13,     20,     15,     8,      false)
        MUX_CFG(DA850, GPIO6_13,        13,     8,      15,     8,      false)
        MUX_CFG(DA850, RTC_ALARM,       0,      28,     15,     2,      false)
+       /* VPIF Capture */
+       MUX_CFG(DA850, VPIF_DIN0,       15,     4,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN1,       15,     0,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN2,       14,     28,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN3,       14,     24,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN4,       14,     20,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN5,       14,     16,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN6,       14,     12,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN7,       14,     8,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN8,       16,     4,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN9,       16,     0,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN10,      15,     28,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN11,      15,     24,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN12,      15,     20,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN13,      15,     16,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN14,      15,     12,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN15,      15,     8,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKIN0,     14,     0,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKIN1,     14,     4,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKIN2,     19,     8,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKIN3,     19,     16,     15,     1,      false)
+       /* VPIF Display */
+       MUX_CFG(DA850, VPIF_DOUT0,      17,     4,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT1,      17,     0,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT2,      16,     28,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT3,      16,     24,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT4,      16,     20,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT5,      16,     16,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT6,      16,     12,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT7,      16,     8,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT8,      18,     4,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT9,      18,     0,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT10,     17,     28,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT11,     17,     24,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT12,     17,     20,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT13,     17,     16,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT14,     17,     12,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT15,     17,     8,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKO2,      19,     12,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKO3,      19,     20,     15,     1,      false)
 #endif
 };
 
@@ -595,6 +643,26 @@ const short da850_lcdcntl_pins[] __initconst = {
        -1
 };
 
+const short da850_vpif_capture_pins[] __initdata = {
+       DA850_VPIF_DIN0, DA850_VPIF_DIN1, DA850_VPIF_DIN2, DA850_VPIF_DIN3,
+       DA850_VPIF_DIN4, DA850_VPIF_DIN5, DA850_VPIF_DIN6, DA850_VPIF_DIN7,
+       DA850_VPIF_DIN8, DA850_VPIF_DIN9, DA850_VPIF_DIN10, DA850_VPIF_DIN11,
+       DA850_VPIF_DIN12, DA850_VPIF_DIN13, DA850_VPIF_DIN14, DA850_VPIF_DIN15,
+       DA850_VPIF_CLKIN0, DA850_VPIF_CLKIN1, DA850_VPIF_CLKIN2,
+       DA850_VPIF_CLKIN3,
+       -1
+};
+
+const short da850_vpif_display_pins[] __initdata = {
+       DA850_VPIF_DOUT0, DA850_VPIF_DOUT1, DA850_VPIF_DOUT2, DA850_VPIF_DOUT3,
+       DA850_VPIF_DOUT4, DA850_VPIF_DOUT5, DA850_VPIF_DOUT6, DA850_VPIF_DOUT7,
+       DA850_VPIF_DOUT8, DA850_VPIF_DOUT9, DA850_VPIF_DOUT10,
+       DA850_VPIF_DOUT11, DA850_VPIF_DOUT12, DA850_VPIF_DOUT13,
+       DA850_VPIF_DOUT14, DA850_VPIF_DOUT15, DA850_VPIF_CLKO2,
+       DA850_VPIF_CLKO3,
+       -1
+};
+
 /* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
 static u8 da850_default_priorities[DA850_N_CP_INTC_IRQ] = {
        [IRQ_DA8XX_COMMTX]              = 7,
@@ -939,7 +1007,7 @@ static struct platform_device da850_cpufreq_device = {
 
 unsigned int da850_max_speed = 300000;
 
-int __init da850_register_cpufreq(char *async_clk)
+int da850_register_cpufreq(char *async_clk)
 {
        int i;
 
@@ -1064,6 +1132,90 @@ no_ddrpll_mem:
        return ret;
 }
 
+/* VPIF resource, platform data */
+static u64 da850_vpif_dma_mask = DMA_BIT_MASK(32);
+
+static struct resource da850_vpif_resource[] = {
+       {
+               .start = DA8XX_VPIF_BASE,
+               .end   = DA8XX_VPIF_BASE + 0xfff,
+               .flags = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device da850_vpif_dev = {
+       .name           = "vpif",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &da850_vpif_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+       .resource       = da850_vpif_resource,
+       .num_resources  = ARRAY_SIZE(da850_vpif_resource),
+};
+
+static struct resource da850_vpif_display_resource[] = {
+       {
+               .start = IRQ_DA850_VPIFINT,
+               .end   = IRQ_DA850_VPIFINT,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device da850_vpif_display_dev = {
+       .name           = "vpif_display",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &da850_vpif_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+       .resource       = da850_vpif_display_resource,
+       .num_resources  = ARRAY_SIZE(da850_vpif_display_resource),
+};
+
+static struct resource da850_vpif_capture_resource[] = {
+       {
+               .start = IRQ_DA850_VPIFINT,
+               .end   = IRQ_DA850_VPIFINT,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = IRQ_DA850_VPIFINT,
+               .end   = IRQ_DA850_VPIFINT,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device da850_vpif_capture_dev = {
+       .name           = "vpif_capture",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &da850_vpif_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+       .resource       = da850_vpif_capture_resource,
+       .num_resources  = ARRAY_SIZE(da850_vpif_capture_resource),
+};
+
+int __init da850_register_vpif(void)
+{
+       return platform_device_register(&da850_vpif_dev);
+}
+
+int __init da850_register_vpif_display(struct vpif_display_config
+                                               *display_config)
+{
+       da850_vpif_display_dev.dev.platform_data = display_config;
+       return platform_device_register(&da850_vpif_display_dev);
+}
+
+int __init da850_register_vpif_capture(struct vpif_capture_config
+                                                       *capture_config)
+{
+       da850_vpif_capture_dev.dev.platform_data = capture_config;
+       return platform_device_register(&da850_vpif_capture_dev);
+}
+
 static struct davinci_soc_info davinci_soc_info_da850 = {
        .io_desc                = da850_io_desc,
        .io_desc_num            = ARRAY_SIZE(da850_io_desc),
index 0755d466221a6aad1b3c93056f5e39e314cfc034..cd0c8b1e1ecfad4a868b9aae3f6180a1b1794ed1 100644 (file)
@@ -701,7 +701,7 @@ static struct resource dm644x_venc_resources[] = {
 #define DM644X_VPSS_DACCLKEN                  BIT(4)
 
 static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type,
-                                  unsigned int mode)
+                                  unsigned int pclock)
 {
        int ret = 0;
        u32 v = DM644X_VPSS_VENCLKEN;
@@ -711,27 +711,18 @@ static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type,
                v |= DM644X_VPSS_DACCLKEN;
                writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
                break;
-       case VPBE_ENC_DV_PRESET:
-               switch (mode) {
-               case V4L2_DV_480P59_94:
-               case V4L2_DV_576P50:
+       case VPBE_ENC_CUSTOM_TIMINGS:
+               if (pclock <= 27000000) {
                        v |= DM644X_VPSS_MUXSEL_PLL2_MODE |
                             DM644X_VPSS_DACCLKEN;
                        writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
-                       break;
-               case V4L2_DV_720P60:
-               case V4L2_DV_1080I60:
-               case V4L2_DV_1080P30:
+               } else {
                        /*
                         * For HD, use external clock source since
                         * HD requires higher clock rate
                         */
                        v |= DM644X_VPSS_MUXSEL_VPBECLK_MODE;
                        writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
-                       break;
-               default:
-                       ret = -EINVAL;
-                       break;
                }
                break;
        default:
index c9ee723c56f35a78628dc0a4a78c08bd63a4f6c3..aaccdc4528fcce2f3110d2d4385dc1c5239ceebb 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/davinci_emac.h>
 #include <linux/spi/spi.h>
 #include <linux/platform_data/davinci_asp.h>
+#include <linux/videodev2.h>
 
 #include <mach/serial.h>
 #include <mach/edma.h>
@@ -26,6 +27,8 @@
 #include <linux/platform_data/usb-davinci.h>
 #include <linux/platform_data/spi-davinci.h>
 
+#include <media/davinci/vpif_types.h>
+
 extern void __iomem *da8xx_syscfg0_base;
 extern void __iomem *da8xx_syscfg1_base;
 
@@ -63,6 +66,7 @@ extern unsigned int da850_max_speed;
 #define DA8XX_PLL0_BASE                0x01c11000
 #define DA8XX_TIMER64P0_BASE   0x01c20000
 #define DA8XX_TIMER64P1_BASE   0x01c21000
+#define DA8XX_VPIF_BASE                0x01e17000
 #define DA8XX_GPIO_BASE                0x01e26000
 #define DA8XX_PSC1_BASE                0x01e27000
 #define DA8XX_AEMIF_CS2_BASE   0x60000000
@@ -92,6 +96,11 @@ int da8xx_register_cpuidle(void);
 void __iomem * __init da8xx_get_mem_ctlr(void);
 int da850_register_pm(struct platform_device *pdev);
 int __init da850_register_sata(unsigned long refclkpn);
+int __init da850_register_vpif(void);
+int __init da850_register_vpif_display
+                       (struct vpif_display_config *display_config);
+int __init da850_register_vpif_capture
+                       (struct vpif_capture_config *capture_config);
 void da8xx_restart(char mode, const char *cmd);
 
 extern struct platform_device da8xx_serial_device;
@@ -126,6 +135,8 @@ extern const short da830_ecap1_pins[];
 extern const short da830_ecap2_pins[];
 extern const short da830_eqep0_pins[];
 extern const short da830_eqep1_pins[];
+extern const short da850_vpif_capture_pins[];
+extern const short da850_vpif_display_pins[];
 
 extern const short da850_i2c0_pins[];
 extern const short da850_i2c1_pins[];
index a7e92fca32e6719457167f1c2f9efbdd2921df73..9e95b8a1edb62964cc473c1947bc61ebc6ca0402 100644 (file)
@@ -928,6 +928,48 @@ enum davinci_da850_index {
        DA850_GPIO6_10,
        DA850_GPIO6_13,
        DA850_RTC_ALARM,
+
+       /* VPIF Capture */
+       DA850_VPIF_DIN0,
+       DA850_VPIF_DIN1,
+       DA850_VPIF_DIN2,
+       DA850_VPIF_DIN3,
+       DA850_VPIF_DIN4,
+       DA850_VPIF_DIN5,
+       DA850_VPIF_DIN6,
+       DA850_VPIF_DIN7,
+       DA850_VPIF_DIN8,
+       DA850_VPIF_DIN9,
+       DA850_VPIF_DIN10,
+       DA850_VPIF_DIN11,
+       DA850_VPIF_DIN12,
+       DA850_VPIF_DIN13,
+       DA850_VPIF_DIN14,
+       DA850_VPIF_DIN15,
+       DA850_VPIF_CLKIN0,
+       DA850_VPIF_CLKIN1,
+       DA850_VPIF_CLKIN2,
+       DA850_VPIF_CLKIN3,
+
+       /* VPIF Display */
+       DA850_VPIF_DOUT0,
+       DA850_VPIF_DOUT1,
+       DA850_VPIF_DOUT2,
+       DA850_VPIF_DOUT3,
+       DA850_VPIF_DOUT4,
+       DA850_VPIF_DOUT5,
+       DA850_VPIF_DOUT6,
+       DA850_VPIF_DOUT7,
+       DA850_VPIF_DOUT8,
+       DA850_VPIF_DOUT9,
+       DA850_VPIF_DOUT10,
+       DA850_VPIF_DOUT11,
+       DA850_VPIF_DOUT12,
+       DA850_VPIF_DOUT13,
+       DA850_VPIF_DOUT14,
+       DA850_VPIF_DOUT15,
+       DA850_VPIF_CLKO2,
+       DA850_VPIF_CLKO3,
 };
 
 enum davinci_tnetv107x_index {
index 405318e35bf63f8422dc5263088d2a9cbe64a212..40a0027838e81601427fbb2bc7ff04311e5300ad 100644 (file)
 #define DA830_LPSC1_McASP1             8
 #define DA850_LPSC1_SATA               8
 #define DA830_LPSC1_McASP2             9
+#define DA850_LPSC1_VPIF               9
 #define DA8XX_LPSC1_SPI1               10
 #define DA8XX_LPSC1_I2C                        11
 #define DA8XX_LPSC1_UART1              12
index f60b66dbcf84ebe5ebe750e3e89521724d7a8d73..21d568b3b1497c90bb79eb841f45595020351db9 100644 (file)
@@ -303,10 +303,12 @@ static int __init exynos_dma_init(void)
 
        dma_cap_set(DMA_SLAVE, exynos_pdma0_pdata.cap_mask);
        dma_cap_set(DMA_CYCLIC, exynos_pdma0_pdata.cap_mask);
+       dma_cap_set(DMA_PRIVATE, exynos_pdma0_pdata.cap_mask);
        amba_device_register(&exynos_pdma0_device, &iomem_resource);
 
        dma_cap_set(DMA_SLAVE, exynos_pdma1_pdata.cap_mask);
        dma_cap_set(DMA_CYCLIC, exynos_pdma1_pdata.cap_mask);
+       dma_cap_set(DMA_PRIVATE, exynos_pdma1_pdata.cap_mask);
        amba_device_register(&exynos_pdma1_device, &iomem_resource);
 
        dma_cap_set(DMA_MEMCPY, exynos_mdma1_pdata.cap_mask);
index 480cd78f1920da5a1fdd62a0593b2231923ea53d..c05d7aa84031b70a601598fd0a5542dfbf3056f3 100644 (file)
@@ -29,6 +29,7 @@
 #include <drm/exynos_drm.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 #include <media/m5mols.h>
 #include <media/s5k6aa.h>
 #include <media/s5p_fimc.h>
@@ -39,7 +40,6 @@
 #include <asm/mach-types.h>
 
 #include <plat/adc.h>
-#include <plat/regs-fb-v4.h>
 #include <plat/regs-serial.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
@@ -378,10 +378,10 @@ static struct regulator_consumer_supply __initdata max8997_ldo1_[] = {
 };
 static struct regulator_consumer_supply __initdata max8997_ldo3_[] = {
        REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"), /* USB */
-       REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+       REGULATOR_SUPPLY("vddcore", "s5p-mipi-csis.0"), /* MIPI */
 };
 static struct regulator_consumer_supply __initdata max8997_ldo4_[] = {
-       REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+       REGULATOR_SUPPLY("vddio", "s5p-mipi-csis.0"), /* MIPI */
 };
 static struct regulator_consumer_supply __initdata max8997_ldo5_[] = {
        REGULATOR_SUPPLY("vhsic", "modemctl"), /* MODEM */
@@ -1180,9 +1180,7 @@ static struct platform_device cam_8m_12v_fixed_rdev = {
 static struct s5p_platform_mipi_csis mipi_csis_platdata = {
        .clk_rate       = 166000000UL,
        .lanes          = 2,
-       .alignment      = 32,
        .hs_settle      = 12,
-       .phy_enable     = s5p_csis_phy_enable,
 };
 
 #define GPIO_CAM_MEGA_RST      EXYNOS4_GPY3(7) /* ISP_RESET */
@@ -1226,7 +1224,6 @@ static struct s5p_fimc_isp_info nuri_camera_sensors[] = {
                .bus_type       = FIMC_MIPI_CSI2,
                .board_info     = &m5mols_board_info,
                .clk_frequency  = 24000000UL,
-               .csi_data_align = 32,
        },
 };
 
index 67b50bb89c0f7d83deb9fd42fcba58e4c4b0b489..9adf491674ea18f350039da0dfbd20e6c825d690 100644 (file)
@@ -30,9 +30,9 @@
 #include <asm/mach-types.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <plat/regs-serial.h>
-#include <plat/regs-fb-v4.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/sdhci.h>
@@ -97,12 +97,12 @@ static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = {
 };
 
 static struct regulator_consumer_supply __initdata ldo3_consumer[] = {
-       REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+       REGULATOR_SUPPLY("vddcore", "s5p-mipi-csis.0"), /* MIPI */
        REGULATOR_SUPPLY("vdd", "exynos4-hdmi"), /* HDMI */
        REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"), /* HDMI */
 };
 static struct regulator_consumer_supply __initdata ldo6_consumer[] = {
-       REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+       REGULATOR_SUPPLY("vddio", "s5p-mipi-csis.0"), /* MIPI */
 };
 static struct regulator_consumer_supply __initdata ldo7_consumer[] = {
        REGULATOR_SUPPLY("avdd", "alc5625"), /* Realtek ALC5625 */
index 7a265d1a82d3e6e172799fe2dfc52d16b4217f7c..730f1ac65928ed832a52fdb2cf0e8b80f2ae4d60 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 
+#include <video/samsung_fimd.h>
 #include <plat/backlight.h>
 #include <plat/clock.h>
 #include <plat/cpu.h>
@@ -36,7 +37,6 @@
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/keypad.h>
 #include <plat/mfc.h>
-#include <plat/regs-fb.h>
 #include <plat/regs-serial.h>
 #include <plat/sdhci.h>
 
index c15d2238ceb017e40b44206951c26e4aaa7ff39c..ee4fb1a9cb7207b226fdffc24f4e4016fafc7618 100644 (file)
@@ -27,9 +27,9 @@
 #include <asm/mach-types.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 #include <plat/regs-serial.h>
 #include <plat/regs-srom.h>
-#include <plat/regs-fb-v4.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/fb.h>
index 98d3aced2289d246f42903dd2881d6f83054b5a6..ebc9dd339a3899ae6170a24a0ddf2c1e44b1281d 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 
+#include <video/samsung_fimd.h>
 #include <plat/regs-serial.h>
 #include <plat/clock.h>
 #include <plat/cpu.h>
@@ -39,7 +40,6 @@
 #include <plat/fb.h>
 #include <plat/mfc.h>
 #include <plat/sdhci.h>
-#include <plat/regs-fb-v4.h>
 #include <plat/fimc-core.h>
 #include <plat/s5p-time.h>
 #include <plat/camport.h>
@@ -209,7 +209,7 @@ static struct regulator_consumer_supply lp3974_ldo3_consumer[] = {
        REGULATOR_SUPPLY("vusb_a", "s3c-hsotg"),
        REGULATOR_SUPPLY("vdd", "exynos4-hdmi"),
        REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"),
-       REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"),
+       REGULATOR_SUPPLY("vddcore", "s5p-mipi-csis.0"),
 };
 
 static struct regulator_init_data lp3974_ldo3_data = {
@@ -273,7 +273,7 @@ static struct regulator_init_data lp3974_ldo6_data = {
 };
 
 static struct regulator_consumer_supply lp3974_ldo7_consumer[] = {
-       REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"),
+       REGULATOR_SUPPLY("vddio", "s5p-mipi-csis.0"),
 };
 
 static struct regulator_init_data lp3974_ldo7_data = {
@@ -942,9 +942,7 @@ static struct platform_device cam_s_if_fixed_reg_dev = {
 static struct s5p_platform_mipi_csis mipi_csis_platdata = {
        .clk_rate       = 166000000UL,
        .lanes          = 2,
-       .alignment      = 32,
        .hs_settle      = 12,
-       .phy_enable     = s5p_csis_phy_enable,
 };
 
 #define GPIO_CAM_LEVEL_EN(n)   EXYNOS4_GPE4(n + 3)
@@ -1008,7 +1006,6 @@ static struct s5p_fimc_isp_info universal_camera_sensors[] = {
                .board_info     = &m5mols_board_info,
                .i2c_bus_num    = 0,
                .clk_frequency  = 24000000UL,
-               .csi_data_align = 32,
        },
 };
 
index 07a6dbeecdd081998be213f2b5ecacf90b3d7a78..5665bb4e980b8f6da6dbf50a6353912118fbb334 100644 (file)
@@ -13,8 +13,8 @@
 #include <linux/fb.h>
 #include <linux/gpio.h>
 
+#include <video/samsung_fimd.h>
 #include <plat/gpio-cfg.h>
-#include <plat/regs-fb-v4.h>
 
 #include <mach/map.h>
 
index 400551e43e4efddd06c0c9751701a52769cb77b2..61c714c4920e1f7268d9a2fa6d7784b6efa50ccf 100644 (file)
@@ -89,8 +89,6 @@
 #define IRQ_NETWINDER_VGA      _ISA_IRQ(11)
 #define IRQ_NETWINDER_SOUND    _ISA_IRQ(12)
 
-#undef RTC_IRQ
-#define RTC_IRQ                IRQ_ISA_RTC_ALARM
 #define I8042_KBD_IRQ  IRQ_ISA_KEYBOARD
 #define I8042_AUX_IRQ  (machine_is_netwinder() ? IRQ_NETWINDER_PS2MOUSE : IRQ_ISA_PS2MOUSE)
 #define IRQ_FLOPPYDISK IRQ_ISA_FLOPPY
index e5165a84f93f7ff8467f5b7c981a083518fffff4..a0bf84803eacee45978fc1b1deef41076db17f19 100644 (file)
@@ -369,6 +369,7 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
        clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "83fcc000.ssi");
        clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "70014000.ssi");
        clk_register_clkdev(clk[ssi3_ipg_gate], NULL, "83fe8000.ssi");
+       clk_register_clkdev(clk[nfc_gate], NULL, "83fdb000.nand");
 
        /* set the usboh3 parent to pll2_sw */
        clk_set_parent(clk[usboh3_sel], clk[pll2_sw]);
@@ -461,6 +462,7 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
        clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "63fcc000.ssi");
        clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "50014000.ssi");
        clk_register_clkdev(clk[ssi3_ipg_gate], NULL, "63fd0000.ssi");
+       clk_register_clkdev(clk[nfc_gate], NULL, "63fdb000.nand");
        clk_register_clkdev(clk[can1_ipg_gate], "ipg", "53fc8000.can");
        clk_register_clkdev(clk[can1_serial_gate], "per", "53fc8000.can");
        clk_register_clkdev(clk[can2_ipg_gate], "ipg", "53fcc000.can");
index 1a78692e32a4bc5d42432180ff67f75a885ce084..202e6a57f1006a3b1ae820d4f229007131bbee84 100644 (file)
@@ -3,7 +3,7 @@
  */
 void cm_control(u32, u32);
 
-#define CM_CTRL        IO_ADDRESS(INTEGRATOR_HDR_CTRL)
+#define CM_CTRL        __io_address(INTEGRATOR_HDR_CTRL)
 
 #define CM_CTRL_LED                    (1 << 0)
 #define CM_CTRL_nMBDET                 (1 << 1)
index 4c034752685152a84ad80b6b64cea298317984fc..efeac5d0bc9ef2abfe3887e93edd653ff2973f55 100644 (file)
  */
 #define PHYS_PCI_V3_BASE                0x62000000
 
-#define PCI_MEMORY_VADDR               0xe8000000
-#define PCI_CONFIG_VADDR               0xec000000
-#define PCI_V3_VADDR                   0xed000000
+#define PCI_MEMORY_VADDR               IOMEM(0xe8000000)
+#define PCI_CONFIG_VADDR               IOMEM(0xec000000)
+#define PCI_V3_VADDR                   IOMEM(0xed000000)
 
 /* ------------------------------------------------------------------------
  *  Integrator Interrupt Controllers
index d5b5435a09aed30896817ce1930c1af6ab4aa88a..e6617c134fafe27542ef140be83e7783db0a9bf3 100644 (file)
@@ -157,7 +157,7 @@ static struct map_desc ap_io_desc[] __initdata = {
 static void __init ap_map_io(void)
 {
        iotable_init(ap_io_desc, ARRAY_SIZE(ap_io_desc));
-       vga_base = PCI_MEMORY_VADDR;
+       vga_base = (unsigned long)PCI_MEMORY_VADDR;
        pci_map_io_early(__phys_to_pfn(PHYS_PCI_IO_BASE));
 }
 
index 6870a1fbcd7870233d20746d1ab892d10c989161..5b08e8e4cc838a4221e28313c80a535d41c8e506 100644 (file)
@@ -261,6 +261,8 @@ static void __init intcp_init_early(void)
 #endif
 }
 
+#ifdef CONFIG_OF
+
 static void __init intcp_timer_init_of(void)
 {
        struct device_node *node;
@@ -297,8 +299,6 @@ static struct sys_timer cp_of_timer = {
        .init           = intcp_timer_init_of,
 };
 
-#ifdef CONFIG_OF
-
 static const struct of_device_id fpga_irq_of_match[] __initconst = {
        { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
        { /* Sentinel */ }
index 060cddde2fd4ad4f52830f065b275cc3cf704bb5..e947441116340fe6f80ddb44a4ed696b17a8cb9a 100644 (file)
@@ -30,7 +30,7 @@
 extern int init_atu;
 
 static int __init
-iq81340sc_atux_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
+iq81340sc_atux_map_irq(const struct pci_dev *dev, u8 idsel, u8 pin)
 {
        WARN_ON(idsel < 1 || idsel > 2);
 
index 9082b84aeebb54cd7831256937f85299dd07a039..2f28018c44478d97a5d108c861faaa1d1ae0483e 100644 (file)
@@ -504,7 +504,7 @@ iop13xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 
 /* Scan an IOP13XX PCI bus.  nr selects which ATU we use.
  */
-struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys)
+struct pci_bus * __devinit iop13xx_scan_bus(int nr, struct pci_sys_data *sys)
 {
        int which_atu;
        struct pci_bus *bus = NULL;
index f7e1b9bce345688419167f5ff6d6e0e3c00cc2f9..95e731a7ed6a5730ce29d5c8921547b433ae8652 100644 (file)
@@ -34,7 +34,8 @@ extern struct bus_type platform_bus_type;
 #define __arch_dma_to_virt(dev, x)     ({ (void *) (is_lbus_device(dev) ? \
                                        __phys_to_virt(x) : __bus_to_virt(x)); })
 #define __arch_virt_to_dma(dev, x)     ({ is_lbus_device(dev) ? \
-                                       (dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); })
+                                       (dma_addr_t)__virt_to_phys((unsigned long)x) \
+                                       : (dma_addr_t)__virt_to_bus(x); })
 #define __arch_pfn_to_dma(dev, pfn)    \
        ({ dma_addr_t __dma = __pfn_to_phys(pfn); \
           if (!is_lbus_device(dev)) \
index 343c435b4176ac6cd323ac556fd5f1ae9f62c0b2..26e9876b50e9cb52df675c3435a4933003eed016 100644 (file)
@@ -54,7 +54,7 @@ static void __init __iomem *win_cfg_base(const struct orion_addr_map_cfg *cfg, i
 /*
  * Description of the windows needed by the platform code
  */
-static struct __initdata orion_addr_map_cfg addr_map_cfg = {
+static struct orion_addr_map_cfg addr_map_cfg __initdata = {
        .num_wins = 14,
        .remappable_wins = 8,
        .win_cfg_base = win_cfg_base,
index 131cd4883f3db21019c15dc8efc296d61d65a7e6..d0cb4857b4b3fdac50b9fcfcee1422416ffe2ddf 100644 (file)
@@ -336,7 +336,7 @@ void __init mv78xx0_init_early(void)
        orion_time_set_base(TIMER_VIRT_BASE);
 }
 
-static void mv78xx0_timer_init(void)
+static void __init_refok mv78xx0_timer_init(void)
 {
        orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
                        IRQ_MV78XX0_TIMER_1, get_tclk());
index 726c02c9c0cdcfd87ac88a4ec0584712ab58bc69..d3fec92c54cb5d5d852974c9e9c3ec7ad58e72bc 100644 (file)
@@ -231,7 +231,7 @@ void __init omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
 
                omap_mmc_add("mmci-omap", i, base, size, irq,
                                rx_req, tx_req, mmc_data[i]);
-       };
+       }
 }
 
 #endif
index a88809a59ea9d731738017338372cd8d6e0b9015..3669c120c7e8a7b29628273ea4dbf2d3bfac39b7 100644 (file)
@@ -607,29 +607,6 @@ static void __init omap_sfh7741prox_init(void)
                        __func__, OMAP4_SFH7741_ENABLE_GPIO, error);
 }
 
-static struct gpio sdp4430_hdmi_gpios[] = {
-       { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },
-       { HDMI_GPIO_LS_OE,      GPIOF_OUT_INIT_HIGH,    "hdmi_gpio_ls_oe" },
-       { HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },
-};
-
-static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev)
-{
-       int status;
-
-       status = gpio_request_array(sdp4430_hdmi_gpios,
-                                   ARRAY_SIZE(sdp4430_hdmi_gpios));
-       if (status)
-               pr_err("%s: Cannot request HDMI GPIOs\n", __func__);
-
-       return status;
-}
-
-static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev)
-{
-       gpio_free_array(sdp4430_hdmi_gpios, ARRAY_SIZE(sdp4430_hdmi_gpios));
-}
-
 static struct nokia_dsi_panel_data dsi1_panel = {
                .name           = "taal",
                .reset_gpio     = 102,
@@ -650,29 +627,6 @@ static struct omap_dss_device sdp4430_lcd_device = {
        .phy.dsi                = {
                .module         = 0,
        },
-
-       .clocks = {
-               .dispc = {
-                       .channel = {
-                               /* Logic Clock = 172.8 MHz */
-                               .lck_div        = 1,
-                               /* Pixel Clock = 34.56 MHz */
-                               .pck_div        = 5,
-                               .lcd_clk_src    = OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC,
-                       },
-                       .dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK,
-               },
-
-               .dsi = {
-                       .regn           = 16,   /* Fint = 2.4 MHz */
-                       .regm           = 180,  /* DDR Clock = 216 MHz */
-                       .regm_dispc     = 5,    /* PLL1_CLK1 = 172.8 MHz */
-                       .regm_dsi       = 5,    /* PLL1_CLK2 = 172.8 MHz */
-
-                       .lp_clk_div     = 10,   /* LP Clock = 8.64 MHz */
-                       .dsi_fclk_src   = OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI,
-               },
-       },
        .channel                = OMAP_DSS_CHANNEL_LCD,
 };
 
@@ -697,33 +651,12 @@ static struct omap_dss_device sdp4430_lcd2_device = {
 
                .module         = 1,
        },
-
-       .clocks = {
-               .dispc = {
-                       .channel = {
-                               /* Logic Clock = 172.8 MHz */
-                               .lck_div        = 1,
-                               /* Pixel Clock = 34.56 MHz */
-                               .pck_div        = 5,
-                               .lcd_clk_src    = OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC,
-                       },
-                       .dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK,
-               },
-
-               .dsi = {
-                       .regn           = 16,   /* Fint = 2.4 MHz */
-                       .regm           = 180,  /* DDR Clock = 216 MHz */
-                       .regm_dispc     = 5,    /* PLL1_CLK1 = 172.8 MHz */
-                       .regm_dsi       = 5,    /* PLL1_CLK2 = 172.8 MHz */
-
-                       .lp_clk_div     = 10,   /* LP Clock = 8.64 MHz */
-                       .dsi_fclk_src   = OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI,
-               },
-       },
        .channel                = OMAP_DSS_CHANNEL_LCD2,
 };
 
 static struct omap_dss_hdmi_data sdp4430_hdmi_data = {
+       .ct_cp_hpd_gpio = HDMI_GPIO_CT_CP_HPD,
+       .ls_oe_gpio = HDMI_GPIO_LS_OE,
        .hpd_gpio = HDMI_GPIO_HPD,
 };
 
@@ -731,8 +664,6 @@ static struct omap_dss_device sdp4430_hdmi_device = {
        .name = "hdmi",
        .driver_name = "hdmi_panel",
        .type = OMAP_DISPLAY_TYPE_HDMI,
-       .platform_enable = sdp4430_panel_enable_hdmi,
-       .platform_disable = sdp4430_panel_disable_hdmi,
        .channel = OMAP_DSS_CHANNEL_DIGIT,
        .data = &sdp4430_hdmi_data,
 };
@@ -830,6 +761,32 @@ static struct omap_board_mux board_mux[] __initdata = {
        /* NIRQ2 for twl6040 */
        OMAP4_MUX(SYS_NIRQ2, OMAP_MUX_MODE0 |
                  OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE),
+       /* GPIO_127 for twl6040 */
+       OMAP4_MUX(HDQ_SIO, OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT),
+       /* McPDM */
+       OMAP4_MUX(ABE_PDM_UL_DATA, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+       OMAP4_MUX(ABE_PDM_DL_DATA, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+       OMAP4_MUX(ABE_PDM_FRAME, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+       OMAP4_MUX(ABE_PDM_LB_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+       OMAP4_MUX(ABE_CLKS, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+       /* DMIC */
+       OMAP4_MUX(ABE_DMIC_CLK1, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+       OMAP4_MUX(ABE_DMIC_DIN1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP4_MUX(ABE_DMIC_DIN2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP4_MUX(ABE_DMIC_DIN3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       /* McBSP1 */
+       OMAP4_MUX(ABE_MCBSP1_CLKX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP4_MUX(ABE_MCBSP1_DR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+       OMAP4_MUX(ABE_MCBSP1_DX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT |
+                 OMAP_PULL_ENA),
+       OMAP4_MUX(ABE_MCBSP1_FSX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       /* McBSP2 */
+       OMAP4_MUX(ABE_MCBSP2_CLKX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP4_MUX(ABE_MCBSP2_DR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+       OMAP4_MUX(ABE_MCBSP2_DX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT |
+                 OMAP_PULL_ENA),
+       OMAP4_MUX(ABE_MCBSP2_FSX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+
        { .reg_offset = OMAP_MUX_TERMINATOR },
 };
 
index 0cabe61cd5071c1c22d1d63dcf52da85029e819e..e642acf9cad0e1132bf3edcd6398d02c05d4cdaa 100644 (file)
@@ -218,7 +218,7 @@ void __init board_flash_init(struct flash_partitions partition_info[],
                        if (onenandcs > GPMC_CS_NUM)
                                onenandcs = cs;
                        break;
-               };
+               }
                cs++;
        }
 
index a08bebc94ec59d5269acd1d5c08f40f41a9cb616..388c431c745a0e4134c847f96f84b73912053bf7 100644 (file)
@@ -461,7 +461,7 @@ static void __init beagle_opp_init(void)
                mpu_dev = omap_device_get_by_hwmod_name("mpu");
                iva_dev = omap_device_get_by_hwmod_name("iva");
 
-               if (!mpu_dev || !iva_dev) {
+               if (IS_ERR(mpu_dev) || IS_ERR(iva_dev)) {
                        pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
                                __func__, mpu_dev, iva_dev);
                        return;
index a3959de85e0554706a20a8266edb050c16c8ef7e..b9b776b6c954c9a519f6ae2dee868b815a79d990 100644 (file)
@@ -88,11 +88,10 @@ enum {
 
 static u8 omap3_evm_version;
 
-u8 get_omap3_evm_rev(void)
+static u8 get_omap3_evm_rev(void)
 {
        return omap3_evm_version;
 }
-EXPORT_SYMBOL(get_omap3_evm_rev);
 
 static void __init omap3_evm_get_revision(void)
 {
index c7f3d026e6d48c3332b6e25c9eff65a19ad9a880..731235eb319e7456c10a20d2405d4d54bf5cff5d 100644 (file)
 #include <video/omap-panel-tfp410.h>
 
 #include <linux/platform_data/spi-omap2-mcspi.h>
-#include <linux/input/matrix_keypad.h>
-#include <linux/spi/spi.h>
-#include <linux/interrupt.h>
-#include <linux/smsc911x.h>
-#include <linux/i2c/at24.h>
 
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "mux.h"
index 2b012f9d69255454b4639b48d533c5f33df3bec2..bfcd397e233c8750ee2d92f85b025d70c02c0699 100644 (file)
@@ -247,8 +247,7 @@ static struct platform_device omap_vwlan_device = {
 };
 
 static struct wl12xx_platform_data omap_panda_wlan_data  __initdata = {
-       /* PANDA ref clock is 38.4 MHz */
-       .board_ref_clock = 2,
+       .board_ref_clock = WL12XX_REFCLOCK_38, /* 38.4 MHz */
 };
 
 static struct twl6040_codec_data twl6040_codec = {
@@ -388,6 +387,21 @@ static struct omap_board_mux board_mux[] __initdata = {
        /* NIRQ2 for twl6040 */
        OMAP4_MUX(SYS_NIRQ2, OMAP_MUX_MODE0 |
                  OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE),
+       /* GPIO_127 for twl6040 */
+       OMAP4_MUX(HDQ_SIO, OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT),
+       /* McPDM */
+       OMAP4_MUX(ABE_PDM_UL_DATA, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+       OMAP4_MUX(ABE_PDM_DL_DATA, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+       OMAP4_MUX(ABE_PDM_FRAME, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+       OMAP4_MUX(ABE_PDM_LB_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+       OMAP4_MUX(ABE_CLKS, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+       /* McBSP1 */
+       OMAP4_MUX(ABE_MCBSP1_CLKX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP4_MUX(ABE_MCBSP1_DR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+       OMAP4_MUX(ABE_MCBSP1_DX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT |
+                 OMAP_PULL_ENA),
+       OMAP4_MUX(ABE_MCBSP1_FSX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+
        { .reg_offset = OMAP_MUX_TERMINATOR },
 };
 
@@ -414,30 +428,9 @@ static struct omap_dss_device omap4_panda_dvi_device = {
        .channel                = OMAP_DSS_CHANNEL_LCD2,
 };
 
-static struct gpio panda_hdmi_gpios[] = {
-       { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },
-       { HDMI_GPIO_LS_OE,      GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
-       { HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },
-};
-
-static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev)
-{
-       int status;
-
-       status = gpio_request_array(panda_hdmi_gpios,
-                                   ARRAY_SIZE(panda_hdmi_gpios));
-       if (status)
-               pr_err("Cannot request HDMI GPIOs\n");
-
-       return status;
-}
-
-static void omap4_panda_panel_disable_hdmi(struct omap_dss_device *dssdev)
-{
-       gpio_free_array(panda_hdmi_gpios, ARRAY_SIZE(panda_hdmi_gpios));
-}
-
 static struct omap_dss_hdmi_data omap4_panda_hdmi_data = {
+       .ct_cp_hpd_gpio = HDMI_GPIO_CT_CP_HPD,
+       .ls_oe_gpio = HDMI_GPIO_LS_OE,
        .hpd_gpio = HDMI_GPIO_HPD,
 };
 
@@ -445,8 +438,6 @@ static struct omap_dss_device  omap4_panda_hdmi_device = {
        .name = "hdmi",
        .driver_name = "hdmi_panel",
        .type = OMAP_DISPLAY_TYPE_HDMI,
-       .platform_enable = omap4_panda_panel_enable_hdmi,
-       .platform_disable = omap4_panda_panel_disable_hdmi,
        .channel = OMAP_DSS_CHANNEL_DIGIT,
        .data = &omap4_panda_hdmi_data,
 };
index ed85fb898c7fd62b8526d0bf1e0bea1d23ff26fd..020e03c95bfe0843bdf9bac22f0077f6a4ce906f 100644 (file)
@@ -748,7 +748,7 @@ static struct radio_si4713_platform_data rx51_si4713_data __initdata_or_module =
        .subdev_board_info = &rx51_si4713_board_info,
 };
 
-static struct platform_device rx51_si4713_dev = {
+static struct platform_device rx51_si4713_dev __initdata_or_module = {
        .name   = "radio-si4713",
        .id     = -1,
        .dev    = {
index 67f8540c8e07a912a87460311afc0f3a0e5c094e..c166fe1fdff9bbf1d92a276a72df028c8f89993f 100644 (file)
@@ -195,8 +195,7 @@ static struct platform_device omap_vwlan_device = {
 };
 
 static struct wl12xx_platform_data omap_zoom_wlan_data __initdata = {
-       /* ZOOM ref clock is 26 MHz */
-       .board_ref_clock = 1,
+       .board_ref_clock = WL12XX_REFCLOCK_26, /* 26 MHz */
 };
 
 static struct omap2_hsmmc_info mmc[] = {
index eaed3900a83c7519d029e1a11e439c797e75769b..3ff22114d702468192c781fe12ae72144691e509 100644 (file)
@@ -382,7 +382,7 @@ void omap2_init_clksel_parent(struct clk *clk)
                                                  __clk_get_name(parent) :
                                                 "NULL"));
                                        clk_reparent(clk, clks->parent);
-                               };
+                               }
                                found = 1;
                        }
                }
index b87b88c2638b968ae834f5d4df2dade5c388c52a..114ab4b8e0e356883192bb847237172df9d46ab3 100644 (file)
@@ -1035,6 +1035,8 @@ static struct omap_clk am33xx_clks[] = {
        CLK(NULL,       "pruss_ocp_gclk",       &pruss_ocp_gclk,        CK_AM33XX),
        CLK("davinci-mcasp.0",  NULL,           &mcasp0_fck,    CK_AM33XX),
        CLK("davinci-mcasp.1",  NULL,           &mcasp1_fck,    CK_AM33XX),
+       CLK(NULL,       "mcasp0_fck",           &mcasp0_fck,    CK_AM33XX),
+       CLK(NULL,       "mcasp1_fck",           &mcasp1_fck,    CK_AM33XX),
        CLK("NULL",     "mmc2_fck",             &mmc2_fck,      CK_AM33XX),
        CLK(NULL,       "mmu_fck",              &mmu_fck,       CK_AM33XX),
        CLK(NULL,       "smartreflex0_fck",     &smartreflex0_fck,      CK_AM33XX),
index 9a7792aec6730f498a642810073888ad6b12df38..70294f54e35af2b656cacaf10543612511d2d584 100644 (file)
@@ -183,17 +183,6 @@ static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
        if (!clkdm->clktrctrl_mask)
                return 0;
 
-       /*
-        * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
-        * more details on the unpleasant problem this is working
-        * around
-        */
-       if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
-           !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
-               _enable_hwsup(clkdm);
-               return 0;
-       }
-
        hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
                                clkdm->clktrctrl_mask);
 
@@ -217,17 +206,6 @@ static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
        if (!clkdm->clktrctrl_mask)
                return 0;
 
-       /*
-        * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
-        * more details on the unpleasant problem this is working
-        * around
-        */
-       if ((clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) &&
-           (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
-               omap3_clkdm_wakeup(clkdm);
-               return 0;
-       }
-
        hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
                                clkdm->clktrctrl_mask);
 
@@ -269,6 +247,17 @@ static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)
        if (!clkdm->clktrctrl_mask)
                return 0;
 
+       /*
+        * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
+        * more details on the unpleasant problem this is working
+        * around
+        */
+       if ((clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) &&
+           (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
+               omap3_clkdm_wakeup(clkdm);
+               return 0;
+       }
+
        hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
                                clkdm->clktrctrl_mask);
 
@@ -292,6 +281,17 @@ static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm)
        if (!clkdm->clktrctrl_mask)
                return 0;
 
+       /*
+        * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
+        * more details on the unpleasant problem this is working
+        * around
+        */
+       if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
+           !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
+               _enable_hwsup(clkdm);
+               return 0;
+       }
+
        hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
                                clkdm->clktrctrl_mask);
 
index 7012068ccbf65542f3c184e41e72d427ee7840fa..1011995f150a60c8f4453832835f4b974dbdd000 100644 (file)
@@ -95,7 +95,6 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = {
        { "dss_core", "omapdss_dss", -1 },
        { "dss_dispc", "omapdss_dispc", -1 },
        { "dss_rfbi", "omapdss_rfbi", -1 },
-       { "dss_venc", "omapdss_venc", -1 },
        { "dss_dsi1", "omapdss_dsi", 0 },
        { "dss_dsi2", "omapdss_dsi", 1 },
        { "dss_hdmi", "omapdss_hdmi", -1 },
@@ -221,7 +220,7 @@ static struct platform_device *create_dss_pdev(const char *pdev_name,
 
        ohs[0] = oh;
        od = omap_device_alloc(pdev, ohs, 1, NULL, 0);
-       if (!od) {
+       if (IS_ERR(od)) {
                pr_err("Could not alloc omap_device for %s\n", pdev_name);
                r = -ENOMEM;
                goto err;
index 8ab1e1bde5e9e82b66968b48a73d16846af940fb..5ac5cf30406a81aef651ae361bab6351903d4c3e 100644 (file)
@@ -838,7 +838,7 @@ static int gpmc_setup_irq(void)
        return request_irq(gpmc_irq, gpmc_handle_irq, 0, "gpmc", NULL);
 }
 
-static __exit int gpmc_free_irq(void)
+static __devexit int gpmc_free_irq(void)
 {
        int i;
 
@@ -944,7 +944,7 @@ static __devinit int gpmc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static __exit int gpmc_remove(struct platform_device *pdev)
+static __devexit int gpmc_remove(struct platform_device *pdev)
 {
        gpmc_free_irq();
        gpmc_mem_exit();
index 03ebf47cfa9a493e1e7ac83cf0a2311110c8c04c..4d3a6324155f95de768fd1416f81ad068e80c3bd 100644 (file)
@@ -523,7 +523,7 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo,
        dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
 
        od = omap_device_alloc(pdev, ohs, 1, NULL, 0);
-       if (!od) {
+       if (IS_ERR(od)) {
                pr_err("Could not allocate od for %s\n", name);
                goto put_pdev;
        }
index 9fe6829f4c16f2dd0837862f5f4254ecba98230b..701e17cba46855bb4c57e441d10ac76fc55c7fb9 100644 (file)
@@ -486,7 +486,7 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
                default:
                        /* Nothing to be done */
                        break;
-               };
+               }
 
                if (val >= 0) {
                        omap_mux_write(pad->partition, val,
index a004cb9acf527d644223ef5facda224321a7263f..e089e4d1ae38f2d3a12890087ab514a69bf57ccd 100644 (file)
@@ -61,8 +61,8 @@ int __init omap_secure_ram_reserve_memblock(void)
 {
        u32 size = OMAP_SECURE_RAM_STORAGE;
 
-       size = ALIGN(size, SZ_1M);
-       omap_secure_memblock_base = arm_memblock_steal(size, SZ_1M);
+       size = ALIGN(size, SECTION_SIZE);
+       omap_secure_memblock_base = arm_memblock_steal(size, SECTION_SIZE);
 
        return 0;
 }
index 299ca2821ad1d6b0f6fed5a5a9712d5abeb2d5ce..b969ab1d258b91894415c3507bd8b50cd2aefa50 100644 (file)
@@ -1697,6 +1697,29 @@ static bool _are_all_hardreset_lines_asserted(struct omap_hwmod *oh)
        return false;
 }
 
+/**
+ * _are_any_hardreset_lines_asserted - return true if any part of @oh is
+ * hard-reset
+ * @oh: struct omap_hwmod *
+ *
+ * If any hardreset lines associated with @oh are asserted, then
+ * return true.  Otherwise, if no hardreset lines associated with @oh
+ * are asserted, or if @oh has no hardreset lines, then return false.
+ * This function is used to avoid executing some parts of the IP block
+ * enable/disable sequence if any hardreset line is set.
+ */
+static bool _are_any_hardreset_lines_asserted(struct omap_hwmod *oh)
+{
+       int rst_cnt = 0;
+       int i;
+
+       for (i = 0; i < oh->rst_lines_cnt && rst_cnt == 0; i++)
+               if (_read_hardreset(oh, oh->rst_lines[i].name) > 0)
+                       rst_cnt++;
+
+       return (rst_cnt) ? true : false;
+}
+
 /**
  * _omap4_disable_module - enable CLKCTRL modulemode on OMAP4
  * @oh: struct omap_hwmod *
@@ -1715,7 +1738,7 @@ static int _omap4_disable_module(struct omap_hwmod *oh)
         * Since integration code might still be doing something, only
         * disable if all lines are under hardreset.
         */
-       if (!_are_all_hardreset_lines_asserted(oh))
+       if (_are_any_hardreset_lines_asserted(oh))
                return 0;
 
        pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
@@ -1749,12 +1772,12 @@ static int _am33xx_disable_module(struct omap_hwmod *oh)
 
        pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
 
+       if (_are_any_hardreset_lines_asserted(oh))
+               return 0;
+
        am33xx_cm_module_disable(oh->clkdm->cm_inst, oh->clkdm->clkdm_offs,
                                 oh->prcm.omap4.clkctrl_offs);
 
-       if (_are_all_hardreset_lines_asserted(oh))
-               return 0;
-
        v = _am33xx_wait_target_disable(oh);
        if (v)
                pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
index 35dcdb66a4e01c6ef63b77c81506953d6fc45b50..bd9220ed5ab9d9fda89cca30b4bf1c339cad9f6d 100644 (file)
@@ -219,7 +219,7 @@ struct omap_hwmod omap2xxx_l4_wkup_hwmod = {
 
 /* MPU */
 static struct omap_hwmod_irq_info omap2xxx_mpu_irqs[] = {
-       { .name = "pmu", .irq = 3 },
+       { .name = "pmu", .irq = 3 + OMAP_INTC_START },
        { .irq = -1 }
 };
 
index 285777241d5a75d1202480781317556338fcd45b..f67b7ee07dd4f5575e206c2098bb67c88fa32873 100644 (file)
@@ -94,7 +94,7 @@ static struct omap_hwmod omap3xxx_l4_sec_hwmod = {
 
 /* MPU */
 static struct omap_hwmod_irq_info omap3xxx_mpu_irqs[] = {
-       { .name = "pmu", .irq = 3 },
+       { .name = "pmu", .irq = 3 + OMAP_INTC_START },
        { .irq = -1 }
 };
 
@@ -3683,6 +3683,7 @@ static struct omap_hwmod_ocp_if *am35xx_hwmod_ocp_ifs[] __initdata = {
        &omap3xxx_l4_core__usb_tll_hs,
        &omap3xxx_l4_core__es3plus_mmc1,
        &omap3xxx_l4_core__es3plus_mmc2,
+       &omap3xxx_l4_core__hdq1w,
        &am35xx_mdio__l3,
        &am35xx_l4_core__mdio,
        &am35xx_emac__l3,
@@ -3737,7 +3738,7 @@ int __init omap3xxx_hwmod_init(void)
        } else {
                WARN(1, "OMAP3 hwmod family init: unknown chip type\n");
                return -EINVAL;
-       };
+       }
 
        r = omap_hwmod_register_links(h);
        if (r < 0)
@@ -3754,7 +3755,7 @@ int __init omap3xxx_hwmod_init(void)
                   rev == OMAP3430_REV_ES3_0 || rev == OMAP3430_REV_ES3_1 ||
                   rev == OMAP3430_REV_ES3_1_2) {
                h = omap3430es2plus_hwmod_ocp_ifs;
-       };
+       }
 
        if (h) {
                r = omap_hwmod_register_links(h);
@@ -3769,7 +3770,7 @@ int __init omap3xxx_hwmod_init(void)
        } else if (rev == OMAP3430_REV_ES3_0 || rev == OMAP3430_REV_ES3_1 ||
                   rev == OMAP3430_REV_ES3_1_2) {
                h = omap3430_es3plus_hwmod_ocp_ifs;
-       };
+       }
 
        if (h)
                r = omap_hwmod_register_links(h);
index 45ad7f74f35624fd564d7cf1325dc3edb983d8a1..58e16aef40bbd92f73ea631ce2e777028ddfaf53 100644 (file)
@@ -18,6 +18,7 @@
  */
 #include <linux/module.h>
 #include <linux/opp.h>
+#include <linux/cpu.h>
 
 #include <plat/omap_device.h>
 
@@ -62,13 +63,23 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
                                __func__, i);
                        return -EINVAL;
                }
-               oh = omap_hwmod_lookup(opp_def->hwmod_name);
-               if (!oh || !oh->od) {
-                       pr_debug("%s: no hwmod or odev for %s, [%d] cannot add OPPs.\n",
-                                __func__, opp_def->hwmod_name, i);
-                       continue;
+
+               if (!strncmp(opp_def->hwmod_name, "mpu", 3)) {
+                       /* 
+                        * All current OMAPs share voltage rail and
+                        * clock source, so CPU0 is used to represent
+                        * the MPU-SS.
+                        */
+                       dev = get_cpu_device(0);
+               } else {
+                       oh = omap_hwmod_lookup(opp_def->hwmod_name);
+                       if (!oh || !oh->od) {
+                               pr_debug("%s: no hwmod or odev for %s, [%d] cannot add OPPs.\n",
+                                        __func__, opp_def->hwmod_name, i);
+                               continue;
+                       }
+                       dev = &oh->od->pdev->dev;
                }
-               dev = &oh->od->pdev->dev;
 
                r = opp_add(dev, opp_def->freq, opp_def->u_volt);
                if (r) {
index 3e1345fc07139777a967c61dc8112fc9a5e69331..46092cd806fae24d14b90829c163190579104a05 100644 (file)
@@ -168,7 +168,7 @@ static int pm_dbg_open(struct inode *inode, struct file *file)
        default:
                return single_open(file, pm_dbg_show_timers,
                        &inode->i_private);
-       };
+       }
 }
 
 static const struct file_operations debug_fops = {
index abefbc4d8e0b9bd452c54af22d3a09e7cd172af9..ea61c32957bdaeeb69f5f21467dcc291b05d397f 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/opp.h>
 #include <linux/export.h>
 #include <linux/suspend.h>
+#include <linux/cpu.h>
 
 #include <asm/system_misc.h>
 
@@ -169,7 +170,15 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
                goto exit;
        }
 
-       dev = omap_device_get_by_hwmod_name(oh_name);
+       if (!strncmp(oh_name, "mpu", 3))
+               /* 
+                * All current OMAPs share voltage rail and clock
+                * source, so CPU0 is used to represent the MPU-SS.
+                */
+               dev = get_cpu_device(0);
+       else
+               dev = omap_device_get_by_hwmod_name(oh_name);
+
        if (IS_ERR(dev)) {
                pr_err("%s: Unable to get dev pointer for hwmod %s\n",
                        __func__, oh_name);
@@ -177,7 +186,7 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
        }
 
        voltdm = voltdm_lookup(vdd_name);
-       if (IS_ERR(voltdm)) {
+       if (!voltdm) {
                pr_err("%s: unable to get vdd pointer for vdd_%s\n",
                        __func__, vdd_name);
                goto exit;
index cbeae56b56a9bf06f117c87a752a17a362fb47cf..f8217a5a4a26db510350dbeb9daf9f140fd2204d 100644 (file)
@@ -122,7 +122,7 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
        sr_data->senp_mod = 0x1;
 
        sr_data->voltdm = voltdm_lookup(sr_dev_attr->sensor_voltdm_name);
-       if (IS_ERR(sr_data->voltdm)) {
+       if (!sr_data->voltdm) {
                pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
                        __func__, sr_dev_attr->sensor_voltdm_name);
                goto exit;
index 8847d6eb23131b7df5e32c94fea1b8a4018f15fa..44f9aa7ec0c0a63e089137342accb6a52ab48ef7 100644 (file)
@@ -378,7 +378,7 @@ static void __init realtime_counter_init(void)
                return;
        }
        sys_clk = clk_get(NULL, "sys_clkin_ck");
-       if (!sys_clk) {
+       if (IS_ERR(sys_clk)) {
                pr_err("%s: failed to get system clock handle\n", __func__);
                iounmap(base);
                return;
index 18a8519594252df8b9a383373b9f5ccd0755044f..635e109f5ad352e97e04dfad00c11e8728c72c98 100644 (file)
@@ -158,7 +158,7 @@ static struct regulator_init_data omap3_vpll2_idata = {
 };
 
 static struct regulator_consumer_supply omap3_vdd1_supply[] = {
-       REGULATOR_SUPPLY("vcc", "mpu.0"),
+       REGULATOR_SUPPLY("vcc", "cpu0"),
 };
 
 static struct regulator_consumer_supply omap3_vdd2_supply[] = {
@@ -239,6 +239,10 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
 static struct twl4030_usb_data omap4_usb_pdata = {
 };
 
+static struct regulator_consumer_supply omap4_vdda_hdmi_dac_supplies[] = {
+       REGULATOR_SUPPLY("vdda_hdmi_dac", "omapdss_hdmi"),
+};
+
 static struct regulator_init_data omap4_vdac_idata = {
        .constraints = {
                .min_uV                 = 1800000,
@@ -248,6 +252,8 @@ static struct regulator_init_data omap4_vdac_idata = {
                .valid_ops_mask         = REGULATOR_CHANGE_MODE
                                        | REGULATOR_CHANGE_STATUS,
        },
+       .num_consumer_supplies  = ARRAY_SIZE(omap4_vdda_hdmi_dac_supplies),
+       .consumer_supplies      = omap4_vdda_hdmi_dac_supplies,
        .supply_regulator       = "V2V1",
 };
 
index fc3afc7cd36624437a57a81a9a0180cb19520cd2..a103c8ffea9f179eeb9083c2b91721ae255e8252 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/mach/map.h>
 
 #include <mach/pxa25x.h>
+#undef GPIO24_SSP1_SFRM
 #include <mach/pxa27x.h>
 #include <mach/audio.h>
 #include <linux/platform_data/video-pxafb.h>
index 997e6da9a9c4743a0f4529d1a4a5de53dc754cf5..32e0d79983551858947b9e5eb7c8897dd86c154f 100644 (file)
@@ -105,6 +105,7 @@ static struct pxamci_platform_data palmte2_mci_platform_data = {
        .gpio_power             = GPIO_NR_PALMTE2_SD_POWER,
 };
 
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 /******************************************************************************
  * GPIO keys
  ******************************************************************************/
@@ -132,6 +133,7 @@ static struct platform_device palmte2_pxa_keys = {
                .platform_data = &palmte2_pxa_keys_data,
        },
 };
+#endif
 
 /******************************************************************************
  * Backlight
index 5a406f7947989932736202d9c9d0f962d5124d4a..ec55c575ed192f7969d64b19dc0dbb8837ae89eb 100644 (file)
@@ -55,7 +55,6 @@
 #ifdef CONFIG_PM
 static int sharpsl_off_charge_battery(void);
 static int sharpsl_check_battery_voltage(void);
-static int sharpsl_fatal_check(void);
 #endif
 static int sharpsl_check_battery_temp(void);
 static int sharpsl_ac_check(void);
@@ -686,53 +685,6 @@ static int corgi_pxa_pm_enter(suspend_state_t state)
        return 0;
 }
 
-/*
- * Check for fatal battery errors
- * Fatal returns -1
- */
-static int sharpsl_fatal_check(void)
-{
-       int buff[5], temp, i, acin;
-
-       dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n");
-
-       /* Check AC-Adapter */
-       acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
-
-       if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
-               sharpsl_pm.machinfo->charge(0);
-               udelay(100);
-               sharpsl_pm.machinfo->discharge(1);      /* enable discharge */
-               mdelay(SHARPSL_WAIT_DISCHARGE_ON);
-       }
-
-       if (sharpsl_pm.machinfo->discharge1)
-               sharpsl_pm.machinfo->discharge1(1);
-
-       /* Check battery : check inserting battery ? */
-       for (i = 0; i < 5; i++) {
-               buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
-               mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
-       }
-
-       if (sharpsl_pm.machinfo->discharge1)
-               sharpsl_pm.machinfo->discharge1(0);
-
-       if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
-               udelay(100);
-               sharpsl_pm.machinfo->charge(1);
-               sharpsl_pm.machinfo->discharge(0);
-       }
-
-       temp = get_select_val(buff);
-       dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %ld\n", acin, temp, sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT));
-
-       if ((acin && (temp < sharpsl_pm.machinfo->fatal_acin_volt)) ||
-                       (!acin && (temp < sharpsl_pm.machinfo->fatal_noacin_volt)))
-               return -1;
-       return 0;
-}
-
 static int sharpsl_off_charge_error(void)
 {
        dev_err(sharpsl_pm.dev, "Offline Charger: Error occurred.\n");
index 392412ce4dac3831872ae749d3693002f86953b0..c773e4dded64d3be4803b1ac03d850e6ee07cde6 100644 (file)
@@ -768,8 +768,7 @@ static unsigned long viper_tpm;
 
 static int __init viper_tpm_setup(char *str)
 {
-       strict_strtoul(str, 10, &viper_tpm);
-       return 1;
+       return strict_strtoul(str, 10, &viper_tpm) >= 0;
 }
 
 __setup("tpm=", viper_tpm_setup);
index b91bc87b3dcf9a6a2a9ae33671c6ac053746f17c..fcb1d59f7aeccdf9cd3ebc641630e4f4b4be504f 100644 (file)
@@ -960,7 +960,9 @@ static int __init ecard_probe(int slot, unsigned irq, card_type_t type)
        *ecp = ec;
        slot_to_expcard[slot] = ec;
 
-       device_register(&ec->dev);
+       rc = device_register(&ec->dev);
+       if (rc)
+               goto nodev;
 
        return 0;
 
index 23ec97370f3272ea21ad6f745b859c5105ff04e2..ff141b0af26bfb3f2cc223a202c2d9f278a7a1ef 100644 (file)
@@ -232,7 +232,7 @@ struct irq_chip s3c2416_irq_second = {
 
 /* IRQ initialisation code */
 
-static int __init s3c2416_add_sub(unsigned int base,
+static int s3c2416_add_sub(unsigned int base,
                                   void (*demux)(unsigned int,
                                                 struct irq_desc *),
                                   struct irq_chip *chip,
@@ -251,7 +251,7 @@ static int __init s3c2416_add_sub(unsigned int base,
        return 0;
 }
 
-static void __init s3c2416_irq_add_second(void)
+static void s3c2416_irq_add_second(void)
 {
        unsigned long pend;
        unsigned long last;
@@ -287,7 +287,7 @@ static void __init s3c2416_irq_add_second(void)
        }
 }
 
-static int __init s3c2416_irq_add(struct device *dev,
+static int s3c2416_irq_add(struct device *dev,
                                  struct subsys_interface *sif)
 {
        printk(KERN_INFO "S3C2416: IRQ Support\n");
index ac2829f56d1277d3437b2c85a1043097c766282b..5e69109c0928e84db25222f95385432bb248994f 100644 (file)
@@ -222,7 +222,7 @@ static struct irq_chip s3c2443_irq_cam = {
 
 /* IRQ initialisation code */
 
-static int __init s3c2443_add_sub(unsigned int base,
+static int s3c2443_add_sub(unsigned int base,
                                   void (*demux)(unsigned int,
                                                 struct irq_desc *),
                                   struct irq_chip *chip,
@@ -241,7 +241,7 @@ static int __init s3c2443_add_sub(unsigned int base,
        return 0;
 }
 
-static int __init s3c2443_irq_add(struct device *dev,
+static int s3c2443_irq_add(struct device *dev,
                                  struct subsys_interface *sif)
 {
        printk("S3C2443: IRQ Support\n");
index db2787aa1e5e7fb5ee61dff9d5c62a861d1d76aa..f30d7fccbfeedd4e2a22e00703b3933231b03157 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
+#include <video/samsung_fimd.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
@@ -52,7 +53,6 @@
 #include <linux/platform_data/usb-s3c2410_udc.h>
 #include <linux/platform_data/s3c-hsudc.h>
 
-#include <plat/regs-fb-v4.h>
 #include <plat/fb.h>
 
 #include <plat/common-smdk.h>
index 17f8356177c1f537ded64b2ab0b6eaaa4cc3f2f0..ddf7a3c743acb2d38bf17b225881b7a546156417 100644 (file)
@@ -104,7 +104,7 @@ static struct s3c2410_hcd_info usb_simtec_info __initdata = {
 };
 
 
-int usb_simtec_init(void)
+int __init usb_simtec_init(void)
 {
        int ret;
 
index 15c58dfc4584f655b630b45d58798155551a4639..99e82ac81b694ce69e27c7e5c8b3a53fc8cef473 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/dm9000.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
@@ -44,7 +45,6 @@
 #include <plat/regs-serial.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/fb.h>
-#include <plat/regs-fb-v4.h>
 
 #include <plat/clock.h>
 #include <plat/devs.h>
index 8b4d46706645c91aa7716c599c3a9640a4f9b8fb..13b7eaa45fd04de2627e35111526a38737567d5f 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
+#include <video/samsung_fimd.h>
 #include <mach/hardware.h>
 #include <mach/map.h>
 
@@ -57,7 +58,6 @@
 #include <mach/regs-gpio-memport.h>
 
 #include <plat/regs-serial.h>
-#include <plat/regs-fb-v4.h>
 #include <plat/fb.h>
 #include <plat/sdhci.h>
 #include <plat/gpio-cfg.h>
index 02222b32b7d37e17c7d55ee054a6030376c63370..2b144893ddc4ca337e98356608d82ca102ba508d 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
+#include <video/samsung_fimd.h>
 #include <mach/hardware.h>
 #include <mach/map.h>
 
@@ -41,7 +42,6 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/regs-fb-v4.h>
 
 #include "common.h"
 
index 09311cc40115d7dbf25c40dfe98bd45c5ea0a289..07c349cca33329fad68fbb253cfa5915e8783237 100644 (file)
@@ -41,9 +41,9 @@
 #include <linux/platform_data/mtd-nand-s3c2410.h>
 #include <plat/regs-serial.h>
 #include <linux/platform_data/touchscreen-s3c2410.h>
-#include <plat/regs-fb-v4.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include "common.h"
 
index 46ee88d16815567c63574cedae2d8d53f292f5f3..e5f9a79b535d81bc7678ebc5315f99e4ac655ccb 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
@@ -43,7 +44,6 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/regs-fb-v4.h>
 
 #include "common.h"
 
index 6daca203e72b3eaea40d0792b0b8fd972918606d..7476f7c722ab18d86d7625caa0b5c6e7d41c3b1f 100644 (file)
@@ -42,9 +42,9 @@
 #include <linux/platform_data/mtd-nand-s3c2410.h>
 #include <plat/regs-serial.h>
 #include <linux/platform_data/touchscreen-s3c2410.h>
-#include <plat/regs-fb-v4.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include "common.h"
 
index d6266d8b43c91c049d2961e24dbdfd2b9ba7feac..96d6da2b6b5fc399d54f5d68449a423a913330b3 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+#include <video/samsung_fimd.h>
 #include <mach/map.h>
 #include <mach/regs-gpio.h>
 
@@ -28,7 +29,6 @@
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
-#include <plat/regs-fb-v4.h>
 
 #include "common.h"
 #include "mach-smartq.h"
index 0957d2a980e13f239e6deec8965e8c9939473e65..7d1167bdc921b2ef5ec7d838ca5131ab6a079c07 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+#include <video/samsung_fimd.h>
 #include <mach/map.h>
 #include <mach/regs-gpio.h>
 
@@ -28,7 +29,6 @@
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
-#include <plat/regs-fb-v4.h>
 
 #include "common.h"
 #include "mach-smartq.h"
index 2547a8846472180016b0bd24e42f4eb53b009b20..da1a771a29e9f1493ce192d35fde34f6fa23ed01 100644 (file)
@@ -43,6 +43,7 @@
 #endif
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
@@ -72,7 +73,6 @@
 #include <linux/platform_data/touchscreen-s3c2410.h>
 #include <plat/keypad.h>
 #include <plat/backlight.h>
-#include <plat/regs-fb-v4.h>
 
 #include "common.h"
 
index dea78a84824413cc9400c61d2827ffe8988bb4b4..96ea1fe0ec94a9d3b0393704b9bf63cbd63bf89b 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mmc/host.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
@@ -52,7 +53,6 @@
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
 #include <plat/fb.h>
-#include <plat/regs-fb.h>
 #include <plat/sdhci.h>
 
 #include "common.h"
index 6f14fc729b8fd206c32f177bcb5ec42224c1242f..12748b6eaa7b8af25e6ab9033a535e61cae98326 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mmc/host.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
@@ -52,7 +53,6 @@
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
 #include <plat/fb.h>
-#include <plat/regs-fb.h>
 #include <plat/sdhci.h>
 
 #include "common.h"
index 5d2c0934928b8b85f63fc525247fad486ef8da2a..dba7384a87bde67d48256dd3e0a95cc61735be55 100644 (file)
@@ -33,6 +33,7 @@
 #include <mach/regs-gpio.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <asm/irq.h>
 #include <asm/mach-types.h>
@@ -51,7 +52,6 @@
 #include <linux/platform_data/touchscreen-s3c2410.h>
 #include <linux/platform_data/asoc-s3c.h>
 #include <plat/backlight.h>
-#include <plat/regs-fb-v4.h>
 
 #include "common.h"
 
index 78028df86c5dd6d6411a46454ba1932bf980e07e..ee9fa5c2ef2caea3fb43185c1bf1dcee25c4af98 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 
+#include <video/samsung_fimd.h>
 #include <mach/map.h>
 #include <mach/regs-clock.h>
 
@@ -39,7 +40,6 @@
 #include <plat/fimc-core.h>
 #include <plat/sdhci.h>
 #include <plat/s5p-time.h>
-#include <plat/regs-fb-v4.h>
 
 #include "common.h"
 
index 00f1e47d490aeb587a4037f64378e99d46818fb8..55e1dba4ffde08bb0de1b57dec5189e5970cd1fd 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 
+#include <video/samsung_fimd.h>
 #include <mach/map.h>
 #include <mach/regs-clock.h>
 
@@ -49,7 +50,6 @@
 #include <plat/clock.h>
 #include <plat/s5p-time.h>
 #include <plat/mfc.h>
-#include <plat/regs-fb-v4.h>
 #include <plat/camport.h>
 
 #include <media/v4l2-mediabus.h>
index 7d6fab4205085672dc9cb2f2b3ffd79b45e82424..4cdb5bb7bbcf024613689228d746b914c9140de5 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/mach-types.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <mach/map.h>
 #include <mach/regs-clock.h>
@@ -46,7 +47,6 @@
 #include <plat/fb.h>
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
-#include <plat/regs-fb-v4.h>
 #include <plat/mfc.h>
 #include <plat/clock.h>
 
index e1ccda6128eb723640d4045697f791d58742a34a..6a7ad3c2a3fcd17d771f38dc4716c9f54af3185f 100644 (file)
@@ -388,7 +388,7 @@ static void __init map_sa1100_gpio_regs( void )
  */
 static void __init get_assabet_scr(void)
 {
-       unsigned long scr, i;
+       unsigned long uninitialized_var(scr), i;
 
        GPDR |= 0x3fc;                  /* Configure GPIO 9:2 as outputs */
        GPSR = 0x3fc;                   /* Write 0xFF to GPIO 9:2 */
index b8b4ab323a3ed9a0c6b8ad16c16acc9b1266044d..6d91a914c1dd794af1b78168adf051da28fd1c78 100644 (file)
@@ -41,7 +41,7 @@ static struct hw_pci shark_pci __initdata = {
 static int __init shark_pci_init(void)
 {
        if (!machine_is_shark())
-               return;
+               return -ENODEV;
 
        pcibios_min_io = 0x6000;
        pcibios_min_mem = 0x50000000;
index ed77ab8c91437c5bfc1cae270351b0bd06a253d6..d47e215aca87c51ba71d9ee070a4d07f21a92b7f 100644 (file)
@@ -100,7 +100,7 @@ static inline int shmobile_cpu_is_dead(unsigned int cpu) { return 1; }
 
 extern void shmobile_smp_init_cpus(unsigned int ncores);
 
-static inline void shmobile_init_late(void)
+static inline void __init shmobile_init_late(void)
 {
        shmobile_suspend_init();
        shmobile_cpuidle_init();
index e10648801b2ecd3560fec71f7e2dc3681d1e8bce..5633d698f1e189c29d04eb09f8f18276f9d85b73 100644 (file)
@@ -78,6 +78,9 @@ struct dw_dma_platform_data dmac_plat_data = {
        .nr_channels = 8,
        .chan_allocation_order = CHAN_ALLOCATION_DESCENDING,
        .chan_priority = CHAN_PRIORITY_DESCENDING,
+       .block_size = 4095U,
+       .nr_masters = 2,
+       .data_width = { 3, 3, 0, 0 },
 };
 
 void __init spear13xx_l2x0_init(void)
index 5f3c03b61f8e77caaab6ed00586e8f741e8a11c5..11680c532b383f302e4229446856fdb018935510 100644 (file)
@@ -16,7 +16,7 @@ config ARCH_TEGRA_2x_SOC
        select ARM_ERRATA_742230
        select ARM_ERRATA_751472
        select ARM_ERRATA_754327
-       select ARM_ERRATA_764369
+       select ARM_ERRATA_764369 if SMP
        select PL310_ERRATA_727915 if CACHE_L2X0
        select PL310_ERRATA_769419 if CACHE_L2X0
        select CPU_FREQ_TABLE if CPU_FREQ
@@ -37,7 +37,7 @@ config ARCH_TEGRA_3x_SOC
        select ARM_ERRATA_743622
        select ARM_ERRATA_751472
        select ARM_ERRATA_754322
-       select ARM_ERRATA_764369
+       select ARM_ERRATA_764369 if SMP
        select PL310_ERRATA_769419 if CACHE_L2X0
        select CPU_FREQ_TABLE if CPU_FREQ
        help
@@ -57,8 +57,6 @@ config TEGRA_AHB
          which controls AHB bus master arbitration and some
          perfomance parameters(priority, prefech size).
 
-comment "Tegra board type"
-
 choice
         prompt "Default low-level debug console UART"
         default TEGRA_DEBUG_UART_NONE
index c77c86c47369c8aa8aefbbdb671704d5e5a6f0c3..5848206ee9b9d02c62d1f0a558f0b8ba8c70596a 100644 (file)
@@ -5,9 +5,9 @@ config UX500_SOC_COMMON
        default y
        select ARM_GIC
        select HAS_MTU
-       select PL310_ERRATA_753970
+       select PL310_ERRATA_753970 if CACHE_PL310
        select ARM_ERRATA_754322
-       select ARM_ERRATA_764369
+       select ARM_ERRATA_764369 if SMP
        select CACHE_L2X0
        select PINCTRL
        select PINCTRL_NOMADIK
index bb9e2d23fee3fdf57afebdd128ebae6b06c89bec..e6e81fdaf10933be7c38f7623767d9d06fa14c9c 100644 (file)
  *
  */
 
-#define UART0_PHYS 0xd8200000
-#include <asm/io.h>
+#define UART0_PHYS     0xd8200000
+#define UART0_ADDR(x)  *(volatile unsigned char *)(UART0_PHYS + x)
 
 static void putc(const char c)
 {
-       while (readb(UART0_PHYS + 0x1c) & 0x2)
+       while (UART0_ADDR(0x1c) & 0x2)
                /* Tx busy, wait and poll */;
 
-       writeb(c, UART0_PHYS);
+       UART0_ADDR(0) = c;
 }
 
 static void flush(void)
index 587ea950d08b322966dce1ab3150fa42af59c1c0..8d3871f110a5533ba6f1db6c42302a798de52edb 100644 (file)
@@ -77,8 +77,11 @@ static void vt8500_power_off(void)
 
 void __init vt8500_init(void)
 {
-       struct device_node *np, *fb;
+       struct device_node *np;
+#if defined(CONFIG_FB_VT8500) || defined(CONFIG_FB_WM8505)
+       struct device_node *fb;
        void __iomem *gpio_base;
+#endif
 
 #ifdef CONFIG_FB_VT8500
        fb = of_find_compatible_node(NULL, NULL, "via,vt8500-fb");
index 101b9681c08c238a4487afca05df11fff15c9d23..c9a4963b5c3d3363210a53d11cc55d63d77965fd 100644 (file)
@@ -624,6 +624,23 @@ config ARM_THUMBEE
          Say Y here if you have a CPU with the ThumbEE extension and code to
          make use of it. Say N for code that can run on CPUs without ThumbEE.
 
+config ARM_VIRT_EXT
+       bool "Native support for the ARM Virtualization Extensions"
+       depends on MMU && CPU_V7
+       help
+         Enable the kernel to make use of the ARM Virtualization
+         Extensions to install hypervisors without run-time firmware
+         assistance.
+
+         A compliant bootloader is required in order to make maximum
+         use of this feature.  Refer to Documentation/arm/Booting for
+         details.
+
+         It is safe to enable this option even if the kernel may not be
+         booted in HYP mode, may not have support for the
+         virtualization extensions, or may be booted with a
+         non-compliant bootloader.
+
 config SWP_EMULATE
        bool "Emulate SWP/SWPB instructions"
        depends on !CPU_USE_DOMAINS && CPU_V7
index 072016371093546cc95519289b30a66b381d79a9..e505befe51b54b77e850049f38633c5d1c2c20af 100644 (file)
@@ -240,6 +240,9 @@ ENTRY(fa_dma_unmap_area)
        mov     pc, lr
 ENDPROC(fa_dma_unmap_area)
 
+       .globl  fa_flush_kern_cache_louis
+       .equ    fa_flush_kern_cache_louis, fa_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index 52e35f32eefb293589ce6c8ce11b4871cf178c62..8a3fadece8d3739b9d3199c5fa7d6de45bf385f4 100644 (file)
@@ -128,6 +128,9 @@ ENTRY(v3_dma_map_area)
 ENDPROC(v3_dma_unmap_area)
 ENDPROC(v3_dma_map_area)
 
+       .globl  v3_flush_kern_cache_louis
+       .equ    v3_flush_kern_cache_louis, v3_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index 022135d2b7e4394313e1bad6ad3deb67ab8e4e14..43e5d77be677a329f497f9829364f392b254fa75 100644 (file)
@@ -140,6 +140,9 @@ ENTRY(v4_dma_map_area)
 ENDPROC(v4_dma_unmap_area)
 ENDPROC(v4_dma_map_area)
 
+       .globl  v4_flush_kern_cache_louis
+       .equ    v4_flush_kern_cache_louis, v4_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index 8f1eeae340c84b6b948d3ca4a4f0af91250facb3..cd49453214070f24b8cab5c64b583c5aff8309e0 100644 (file)
@@ -251,6 +251,9 @@ ENTRY(v4wb_dma_unmap_area)
        mov     pc, lr
 ENDPROC(v4wb_dma_unmap_area)
 
+       .globl  v4wb_flush_kern_cache_louis
+       .equ    v4wb_flush_kern_cache_louis, v4wb_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index b34a5f908a82345bd6f4c4eb8b20f44f587cad48..11e5e5838bc59eb8d99e2e5d5d74830e86c652f0 100644 (file)
@@ -196,6 +196,9 @@ ENTRY(v4wt_dma_map_area)
 ENDPROC(v4wt_dma_unmap_area)
 ENDPROC(v4wt_dma_map_area)
 
+       .globl  v4wt_flush_kern_cache_louis
+       .equ    v4wt_flush_kern_cache_louis, v4wt_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index 4b10760c56d6fe081dd9ab0988119d2378cd9369..d8fd4d4bd3d45ecdc66ad2c74885795df9681ea7 100644 (file)
@@ -326,6 +326,9 @@ ENTRY(v6_dma_unmap_area)
        mov     pc, lr
 ENDPROC(v6_dma_unmap_area)
 
+       .globl  v6_flush_kern_cache_louis
+       .equ    v6_flush_kern_cache_louis, v6_flush_kern_cache_all
+
        __INITDATA
 
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
index 3b172275262e2c87070af4047a1123c2a6a1a6aa..cd956647c21a800d69ed3215a774b086fed008a1 100644 (file)
@@ -33,6 +33,24 @@ ENTRY(v7_flush_icache_all)
        mov     pc, lr
 ENDPROC(v7_flush_icache_all)
 
+ /*
+ *     v7_flush_dcache_louis()
+ *
+ *     Flush the D-cache up to the Level of Unification Inner Shareable
+ *
+ *     Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
+ */
+
+ENTRY(v7_flush_dcache_louis)
+       dmb                                     @ ensure ordering with previous memory accesses
+       mrc     p15, 1, r0, c0, c0, 1           @ read clidr, r0 = clidr
+       ands    r3, r0, #0xe00000               @ extract LoUIS from clidr
+       mov     r3, r3, lsr #20                 @ r3 = LoUIS * 2
+       moveq   pc, lr                          @ return if level == 0
+       mov     r10, #0                         @ r10 (starting level) = 0
+       b       flush_levels                    @ start flushing cache levels
+ENDPROC(v7_flush_dcache_louis)
+
 /*
  *     v7_flush_dcache_all()
  *
@@ -49,7 +67,7 @@ ENTRY(v7_flush_dcache_all)
        mov     r3, r3, lsr #23                 @ left align loc bit field
        beq     finished                        @ if loc is 0, then no need to clean
        mov     r10, #0                         @ start clean at cache level 0
-loop1:
+flush_levels:
        add     r2, r10, r10, lsr #1            @ work out 3x current cache level
        mov     r1, r0, lsr r2                  @ extract cache type bits from clidr
        and     r1, r1, #7                      @ mask of the bits for current cache only
@@ -71,9 +89,9 @@ loop1:
        clz     r5, r4                          @ find bit position of way size increment
        ldr     r7, =0x7fff
        ands    r7, r7, r1, lsr #13             @ extract max number of the index size
-loop2:
+loop1:
        mov     r9, r4                          @ create working copy of max way size
-loop3:
+loop2:
  ARM(  orr     r11, r10, r9, lsl r5    )       @ factor way and cache number into r11
  THUMB(        lsl     r6, r9, r5              )
  THUMB(        orr     r11, r10, r6            )       @ factor way and cache number into r11
@@ -82,13 +100,13 @@ loop3:
  THUMB(        orr     r11, r11, r6            )       @ factor index number into r11
        mcr     p15, 0, r11, c7, c14, 2         @ clean & invalidate by set/way
        subs    r9, r9, #1                      @ decrement the way
-       bge     loop3
-       subs    r7, r7, #1                      @ decrement the index
        bge     loop2
+       subs    r7, r7, #1                      @ decrement the index
+       bge     loop1
 skip:
        add     r10, r10, #2                    @ increment cache number
        cmp     r3, r10
-       bgt     loop1
+       bgt     flush_levels
 finished:
        mov     r10, #0                         @ swith back to cache level 0
        mcr     p15, 2, r10, c0, c0, 0          @ select current cache level in cssr
@@ -120,6 +138,24 @@ ENTRY(v7_flush_kern_cache_all)
        mov     pc, lr
 ENDPROC(v7_flush_kern_cache_all)
 
+ /*
+ *     v7_flush_kern_cache_louis(void)
+ *
+ *     Flush the data cache up to Level of Unification Inner Shareable.
+ *     Invalidate the I-cache to the point of unification.
+ */
+ENTRY(v7_flush_kern_cache_louis)
+ ARM(  stmfd   sp!, {r4-r5, r7, r9-r11, lr}    )
+ THUMB(        stmfd   sp!, {r4-r7, r9-r11, lr}        )
+       bl      v7_flush_dcache_louis
+       mov     r0, #0
+       ALT_SMP(mcr     p15, 0, r0, c7, c1, 0)  @ invalidate I-cache inner shareable
+       ALT_UP(mcr      p15, 0, r0, c7, c5, 0)  @ I+BTB cache invalidate
+ ARM(  ldmfd   sp!, {r4-r5, r7, r9-r11, lr}    )
+ THUMB(        ldmfd   sp!, {r4-r7, r9-r11, lr}        )
+       mov     pc, lr
+ENDPROC(v7_flush_kern_cache_louis)
+
 /*
  *     v7_flush_cache_all()
  *
index 0650bb87c1e3a68feb64f465bf547c2e3de52771..2bb61e703d6c4d042cbbb86e6c655cbc0e94d762 100644 (file)
@@ -368,6 +368,9 @@ ENTRY(arm1020_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm1020_dma_unmap_area)
 
+       .globl  arm1020_flush_kern_cache_louis
+       .equ    arm1020_flush_kern_cache_louis, arm1020_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm1020
 
index 4188478325a6398fbe8ada36c109694b81f177ea..8f96aa40f5107987edf065c451d4d0879e5e108c 100644 (file)
@@ -354,6 +354,9 @@ ENTRY(arm1020e_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm1020e_dma_unmap_area)
 
+       .globl  arm1020e_flush_kern_cache_louis
+       .equ    arm1020e_flush_kern_cache_louis, arm1020e_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm1020e
 
index 33c68824bff0999d6f718eb065f1c5b1daad9cac..8ebe4a469a22534c9a828681d57552a546fb820b 100644 (file)
@@ -343,6 +343,9 @@ ENTRY(arm1022_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm1022_dma_unmap_area)
 
+       .globl  arm1022_flush_kern_cache_louis
+       .equ    arm1022_flush_kern_cache_louis, arm1022_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm1022
 
index fbc1d5fc24dcd0b5df37e4f508b4ea7fb9c4bafc..093fc7e520c341fb270b45e3ef2f4fbed694ae3c 100644 (file)
@@ -337,6 +337,9 @@ ENTRY(arm1026_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm1026_dma_unmap_area)
 
+       .globl  arm1026_flush_kern_cache_louis
+       .equ    arm1026_flush_kern_cache_louis, arm1026_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm1026
 
index 1a8c138eb8975697b8d15dee01f71ad2e9e5917c..2c3b9421ab5eca938dfe9289fc39472259ada3c1 100644 (file)
@@ -319,6 +319,9 @@ ENTRY(arm920_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm920_dma_unmap_area)
 
+       .globl  arm920_flush_kern_cache_louis
+       .equ    arm920_flush_kern_cache_louis, arm920_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm920
 #endif
index 4c44d7e1c3ca214f4debab4538928ef68113bafd..4464c49d7449b386b04c017f33fdeb79ef718f05 100644 (file)
@@ -321,6 +321,9 @@ ENTRY(arm922_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm922_dma_unmap_area)
 
+       .globl  arm922_flush_kern_cache_louis
+       .equ    arm922_flush_kern_cache_louis, arm922_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm922
 #endif
index ec5b1180994fb7b01779a8c457737f803f613e75..281eb9b9c1d654061e0bc8d2e6d350f6d7a3b2ff 100644 (file)
@@ -376,6 +376,9 @@ ENTRY(arm925_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm925_dma_unmap_area)
 
+       .globl  arm925_flush_kern_cache_louis
+       .equ    arm925_flush_kern_cache_louis, arm925_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm925
 
index c31e62c606c0b6eebf5390c2de640a7fb63ad949..f1803f7e29728460965675b6722a978d0cc33dcd 100644 (file)
@@ -339,6 +339,9 @@ ENTRY(arm926_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm926_dma_unmap_area)
 
+       .globl  arm926_flush_kern_cache_louis
+       .equ    arm926_flush_kern_cache_louis, arm926_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm926
 
index a613a7dd71465c994f6d57093954d9110aee12e4..8da189d4a4021a9184d1c78ac4cda76209406f02 100644 (file)
@@ -267,6 +267,9 @@ ENTRY(arm940_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm940_dma_unmap_area)
 
+       .globl  arm940_flush_kern_cache_louis
+       .equ    arm940_flush_kern_cache_louis, arm940_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm940
 
index 9f4f2999fdd076e5c13aceaa9e5f3734c6ec65ba..f666cf34075a1a8e7e496fd9c0a09657a0627040 100644 (file)
@@ -310,6 +310,9 @@ ENTRY(arm946_dma_unmap_area)
        mov     pc, lr
 ENDPROC(arm946_dma_unmap_area)
 
+       .globl  arm946_flush_kern_cache_louis
+       .equ    arm946_flush_kern_cache_louis, arm946_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions arm946
 
index 23a8e4c7f2bdc5c8a2431e3aba75eea54e08a6b7..4106b09e0c29ad07530e095ca361e84f92489d32 100644 (file)
@@ -415,6 +415,9 @@ ENTRY(feroceon_dma_unmap_area)
        mov     pc, lr
 ENDPROC(feroceon_dma_unmap_area)
 
+       .globl  feroceon_flush_kern_cache_louis
+       .equ    feroceon_flush_kern_cache_louis, feroceon_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions feroceon
 
@@ -431,6 +434,7 @@ ENDPROC(feroceon_dma_unmap_area)
        range_alias flush_icache_all
        range_alias flush_user_cache_all
        range_alias flush_kern_cache_all
+       range_alias flush_kern_cache_louis
        range_alias flush_user_cache_range
        range_alias coherent_kern_range
        range_alias coherent_user_range
index 2d8ff3ad86d3e1a2b9d9abd83a1bdd3ab42eba3a..b29a2265af01b56f4c911b4c74fdd2cfadc3f892 100644 (file)
@@ -299,6 +299,7 @@ ENTRY(\name\()_processor_functions)
 ENTRY(\name\()_cache_fns)
        .long   \name\()_flush_icache_all
        .long   \name\()_flush_kern_cache_all
+       .long   \name\()_flush_kern_cache_louis
        .long   \name\()_flush_user_cache_all
        .long   \name\()_flush_user_cache_range
        .long   \name\()_coherent_kern_range
index fbb2124a547d125266d35cbce88348506c1eab65..82f9cdc751d6421d01bcb4eca3de51dd211f1868 100644 (file)
@@ -303,6 +303,9 @@ ENTRY(mohawk_dma_unmap_area)
        mov     pc, lr
 ENDPROC(mohawk_dma_unmap_area)
 
+       .globl  mohawk_flush_kern_cache_louis
+       .equ    mohawk_flush_kern_cache_louis, mohawk_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions mohawk
 
index c2e2b66f72b5cd08648085c28ffc5d8c2ee8359a..846d279f31764d7803fc6144df9517087286c768 100644 (file)
@@ -172,7 +172,7 @@ __v7_ca15mp_setup:
 __v7_setup:
        adr     r12, __v7_setup_stack           @ the local stack
        stmia   r12, {r0-r5, r7, r9, r11, lr}
-       bl      v7_flush_dcache_all
+       bl      v7_flush_dcache_louis
        ldmia   r12, {r0-r5, r7, r9, r11, lr}
 
        mrc     p15, 0, r0, c0, c0, 0           @ read main ID register
index b0d57869da2d95f1af47702bf039f3ef90ad5f02..eb93d6487f3598fcb0cc6e92c0f3e23faa36fb11 100644 (file)
@@ -337,6 +337,9 @@ ENTRY(xsc3_dma_unmap_area)
        mov     pc, lr
 ENDPROC(xsc3_dma_unmap_area)
 
+       .globl  xsc3_flush_kern_cache_louis
+       .equ    xsc3_flush_kern_cache_louis, xsc3_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions xsc3
 
index 4ffebaa595eec597d37e556bd66edc4af28f2a20..25510361aa181e7200d6f69a64d41ff6b8f8a8a6 100644 (file)
@@ -410,6 +410,9 @@ ENTRY(xscale_dma_unmap_area)
        mov     pc, lr
 ENDPROC(xscale_dma_unmap_area)
 
+       .globl  xscale_flush_kern_cache_louis
+       .equ    xscale_flush_kern_cache_louis, xscale_flush_kern_cache_all
+
        @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
        define_cache_functions xscale
 
@@ -439,6 +442,7 @@ ENDPROC(xscale_dma_unmap_area)
        a0_alias flush_icache_all
        a0_alias flush_user_cache_all
        a0_alias flush_kern_cache_all
+       a0_alias flush_kern_cache_louis
        a0_alias flush_user_cache_range
        a0_alias coherent_kern_range
        a0_alias coherent_user_range
index 1568f39fba8bec5ee2b67e459bf861c62d406d29..95b75cc70515efa8ffc0465cc44585b99ff70ede 100644 (file)
@@ -63,10 +63,6 @@ struct platform_device *__init imx_add_mxc_nand(
        /* AXI has to come first, that's how the mxc_nand driver expect it */
        struct resource res[] = {
                {
-                       .start = data->axibase,
-                       .end = data->axibase + SZ_16K - 1,
-                       .flags = IORESOURCE_MEM,
-               }, {
                        .start = data->iobase,
                        .end = data->iobase + data->iosize - 1,
                        .flags = IORESOURCE_MEM,
@@ -74,10 +70,13 @@ struct platform_device *__init imx_add_mxc_nand(
                        .start = data->irq,
                        .end = data->irq,
                        .flags = IORESOURCE_IRQ,
+               }, {
+                       .start = data->axibase,
+                       .end = data->axibase + SZ_16K - 1,
+                       .flags = IORESOURCE_MEM,
                },
        };
        return imx_add_platform_device("mxc_nand", data->id,
-                       res + !data->axibase,
-                       ARRAY_SIZE(res) - !data->axibase,
+                       res, ARRAY_SIZE(res) - !data->axibase,
                        pdata, sizeof(*pdata));
 }
index 826de74bfdd127a8ca5b763aa79336ccfda75dd8..c08a54d9d8897dd686462787d8d205206e00da84 100644 (file)
 #define NMK_GPIO_ALT_B 2
 #define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
 
+#define NMK_GPIO_ALT_CX_SHIFT 2
+#define NMK_GPIO_ALT_C1        ((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C2        ((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C3        ((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C4        ((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+
 /* Pull up/down values */
 enum nmk_gpio_pull {
        NMK_GPIO_PULL_NONE,
index 9c949c7c98a73e810558a542cb85608cad152f3c..3b8ec60af351500a5cbcb80c970b8026c7d8477d 100644 (file)
@@ -25,6 +25,8 @@
  *     bit 19..20 - SLPM direction
  *     bit 21..22 - SLPM Value (if output)
  *     bit 23..25 - PDIS value (if input)
+ *     bit     26 - Gpio mode
+ *     bit     27 - Sleep mode
  *
  * to facilitate the definition, the following macros are provided
  *
index ca83a7659aefa29a132cfdff4754b7c17705493e..c9d1c3603bbff9c5b42c2c0c304bba1cf35be766 100644 (file)
@@ -43,11 +43,13 @@ config OMAP_DEBUG_DEVICES
 
 config OMAP_DEBUG_LEDS
        def_bool y if NEW_LEDS
+       select LEDS_CLASS
        depends on OMAP_DEBUG_DEVICES
 
 config POWER_AVS_OMAP
        bool "AVS(Adaptive Voltage Scaling) support for OMAP IP versions 1&2"
        depends on POWER_AVS && (ARCH_OMAP3 || ARCH_OMAP4) && PM
+       select POWER_SUPPLY
        help
          Say Y to enable AVS(Adaptive Voltage Scaling)
          support on OMAP containing the version 1 or
index 2e826f1faf7b39dd425116f6d202a9853b6674d1..87ba8dd0d7910c2072e2b22fa5f4a4f58f79fbc9 100644 (file)
@@ -52,22 +52,29 @@ static u32 notrace omap_32k_read_sched_clock(void)
  * nsecs and adds to a monotonically increasing timespec.
  */
 static struct timespec persistent_ts;
-static cycles_t cycles, last_cycles;
+static cycles_t cycles;
 static unsigned int persistent_mult, persistent_shift;
+static DEFINE_SPINLOCK(read_persistent_clock_lock);
+
 static void omap_read_persistent_clock(struct timespec *ts)
 {
        unsigned long long nsecs;
-       cycles_t delta;
-       struct timespec *tsp = &persistent_ts;
+       cycles_t last_cycles;
+       unsigned long flags;
+
+       spin_lock_irqsave(&read_persistent_clock_lock, flags);
 
        last_cycles = cycles;
        cycles = sync32k_cnt_reg ? __raw_readl(sync32k_cnt_reg) : 0;
-       delta = cycles - last_cycles;
 
-       nsecs = clocksource_cyc2ns(delta, persistent_mult, persistent_shift);
+       nsecs = clocksource_cyc2ns(cycles - last_cycles,
+                                       persistent_mult, persistent_shift);
+
+       timespec_add_ns(&persistent_ts, nsecs);
+
+       *ts = persistent_ts;
 
-       timespec_add_ns(tsp, nsecs);
-       *ts = *tsp;
+       spin_unlock_irqrestore(&read_persistent_clock_lock, flags);
 }
 
 /**
index 6013831a043e320fafd5e718a558d422fa67a624..a5683a84c6ee0e313cb8f9daeeb7c72106952a4e 100644 (file)
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
-#include <linux/i2c-omap.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 
 #include <mach/irqs.h>
 #include <plat/i2c.h>
-#include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 
 #define OMAP_I2C_SIZE          0x3f
@@ -129,16 +127,6 @@ static inline int omap1_i2c_add_bus(int bus_id)
 
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
-/*
- * XXX This function is a temporary compatibility wrapper - only
- * needed until the I2C driver can be converted to call
- * omap_pm_set_max_dev_wakeup_lat() and handle a return code.
- */
-static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
-{
-       omap_pm_set_max_mpu_wakeup_lat(dev, t);
-}
-
 static inline int omap2_i2c_add_bus(int bus_id)
 {
        int l;
@@ -170,15 +158,6 @@ static inline int omap2_i2c_add_bus(int bus_id)
        dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr;
        pdata->flags = dev_attr->flags;
 
-       /*
-        * When waiting for completion of a i2c transfer, we need to
-        * set a wake up latency constraint for the MPU. This is to
-        * ensure quick enough wakeup from idle, when transfer
-        * completes.
-        * Only omap3 has support for constraints
-        */
-       if (cpu_is_omap34xx())
-               pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
        pdev = omap_device_build(name, bus_id, oh, pdata,
                        sizeof(struct omap_i2c_bus_platform_data),
                        NULL, 0, 0);
index 9f6413324df9bfe2016be58ac38f7b8a9676eb47..9722f418ae1fa845b4008afd3a38b722ecf942d2 100644 (file)
@@ -38,7 +38,7 @@ int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t)
        if (!dev || t < -1) {
                WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
                return -EINVAL;
-       };
+       }
 
        if (t == -1)
                pr_debug("OMAP PM: remove max MPU wakeup latency constraint: dev %s\n",
@@ -67,7 +67,7 @@ int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r)
            agent_id != OCP_TARGET_AGENT)) {
                WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
                return -EINVAL;
-       };
+       }
 
        if (r == 0)
                pr_debug("OMAP PM: remove min bus tput constraint: dev %s for agent_id %d\n",
@@ -93,7 +93,7 @@ int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev,
        if (!req_dev || !dev || t < -1) {
                WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
                return -EINVAL;
-       };
+       }
 
        if (t == -1)
                pr_debug("OMAP PM: remove max device latency constraint: dev %s\n",
@@ -123,7 +123,7 @@ int omap_pm_set_max_sdma_lat(struct device *dev, long t)
        if (!dev || t < -1) {
                WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
                return -EINVAL;
-       };
+       }
 
        if (t == -1)
                pr_debug("OMAP PM: remove max DMA latency constraint: dev %s\n",
index cee85a55bd82d3ae3e5ef0874500320e4b359bf7..7a7d1f2a65e99495e849db5449bbb81d008facf1 100644 (file)
@@ -725,7 +725,7 @@ struct platform_device __init *omap_device_build_ss(const char *pdev_name, int p
                dev_set_name(&pdev->dev, "%s", pdev->name);
 
        od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt);
-       if (!od)
+       if (IS_ERR(od))
                goto odbs_exit1;
 
        ret = platform_device_add_data(pdev, pdata, pdata_len);
diff --git a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h b/arch/arm/plat-samsung/include/plat/regs-fb-v4.h
deleted file mode 100644 (file)
index 4c3647f..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/* arch/arm/plat-samsung/include/plat/regs-fb-v4.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      http://armlinux.simtec.co.uk/
- *      Ben Dooks <ben@simtec.co.uk>
- *
- * S3C64XX - new-style framebuffer register definitions
- *
- * This is the register set for the new style framebuffer interface
- * found from the S3C2443 onwards and specifically the S3C64XX series
- * S3C6400 and S3C6410.
- *
- * The file contains the cpu specific items which change between whichever
- * architecture is selected. See <plat/regs-fb.h> for the core definitions
- * that are the same.
- *
- * 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 the core definitions here, in case we really do need to
- * override them at a later date.
-*/
-
-#include <plat/regs-fb.h>
-
-#define S3C_FB_MAX_WIN (5)  /* number of hardware windows available. */
-#define VIDCON1_FSTATUS_EVEN   (1 << 15)
-
-/* Video timing controls */
-#define VIDTCON0                               (0x10)
-#define VIDTCON1                               (0x14)
-#define VIDTCON2                               (0x18)
-
-/* Window position controls */
-
-#define WINCON(_win)                           (0x20 + ((_win) * 4))
-
-/* OSD1 and OSD4 do not have register D */
-
-#define VIDOSD_BASE                            (0x40)
-
-#define VIDINTCON0                             (0x130)
-
-/* WINCONx */
-
-#define WINCONx_CSCWIDTH_MASK                  (0x3 << 26)
-#define WINCONx_CSCWIDTH_SHIFT                 (26)
-#define WINCONx_CSCWIDTH_WIDE                  (0x0 << 26)
-#define WINCONx_CSCWIDTH_NARROW                        (0x3 << 26)
-
-#define WINCONx_ENLOCAL                                (1 << 22)
-#define WINCONx_BUFSTATUS                      (1 << 21)
-#define WINCONx_BUFSEL                         (1 << 20)
-#define WINCONx_BUFAUTOEN                      (1 << 19)
-#define WINCONx_YCbCr                          (1 << 13)
-
-#define WINCON1_LOCALSEL_CAMIF                 (1 << 23)
-
-#define WINCON2_LOCALSEL_CAMIF                 (1 << 23)
-#define WINCON2_BLD_PIX                                (1 << 6)
-
-#define WINCON2_ALPHA_SEL                      (1 << 1)
-#define WINCON2_BPPMODE_MASK                   (0xf << 2)
-#define WINCON2_BPPMODE_SHIFT                  (2)
-#define WINCON2_BPPMODE_1BPP                   (0x0 << 2)
-#define WINCON2_BPPMODE_2BPP                   (0x1 << 2)
-#define WINCON2_BPPMODE_4BPP                   (0x2 << 2)
-#define WINCON2_BPPMODE_8BPP_1232              (0x4 << 2)
-#define WINCON2_BPPMODE_16BPP_565              (0x5 << 2)
-#define WINCON2_BPPMODE_16BPP_A1555            (0x6 << 2)
-#define WINCON2_BPPMODE_16BPP_I1555            (0x7 << 2)
-#define WINCON2_BPPMODE_18BPP_666              (0x8 << 2)
-#define WINCON2_BPPMODE_18BPP_A1665            (0x9 << 2)
-#define WINCON2_BPPMODE_19BPP_A1666            (0xa << 2)
-#define WINCON2_BPPMODE_24BPP_888              (0xb << 2)
-#define WINCON2_BPPMODE_24BPP_A1887            (0xc << 2)
-#define WINCON2_BPPMODE_25BPP_A1888            (0xd << 2)
-#define WINCON2_BPPMODE_28BPP_A4888            (0xd << 2)
-
-#define WINCON3_BLD_PIX                                (1 << 6)
-
-#define WINCON3_ALPHA_SEL                      (1 << 1)
-#define WINCON3_BPPMODE_MASK                   (0xf << 2)
-#define WINCON3_BPPMODE_SHIFT                  (2)
-#define WINCON3_BPPMODE_1BPP                   (0x0 << 2)
-#define WINCON3_BPPMODE_2BPP                   (0x1 << 2)
-#define WINCON3_BPPMODE_4BPP                   (0x2 << 2)
-#define WINCON3_BPPMODE_16BPP_565              (0x5 << 2)
-#define WINCON3_BPPMODE_16BPP_A1555            (0x6 << 2)
-#define WINCON3_BPPMODE_16BPP_I1555            (0x7 << 2)
-#define WINCON3_BPPMODE_18BPP_666              (0x8 << 2)
-#define WINCON3_BPPMODE_18BPP_A1665            (0x9 << 2)
-#define WINCON3_BPPMODE_19BPP_A1666            (0xa << 2)
-#define WINCON3_BPPMODE_24BPP_888              (0xb << 2)
-#define WINCON3_BPPMODE_24BPP_A1887            (0xc << 2)
-#define WINCON3_BPPMODE_25BPP_A1888            (0xd << 2)
-#define WINCON3_BPPMODE_28BPP_A4888            (0xd << 2)
-
-#define VIDINTCON0_FIFIOSEL_WINDOW2            (0x10 << 5)
-#define VIDINTCON0_FIFIOSEL_WINDOW3            (0x20 << 5)
-#define VIDINTCON0_FIFIOSEL_WINDOW4            (0x40 << 5)
-
-#define DITHMODE                               (0x170)
-#define WINxMAP(_win)                          (0x180 + ((_win) * 4))
-
-
-#define DITHMODE_R_POS_MASK                    (0x3 << 5)
-#define DITHMODE_R_POS_SHIFT                   (5)
-#define DITHMODE_R_POS_8BIT                    (0x0 << 5)
-#define DITHMODE_R_POS_6BIT                    (0x1 << 5)
-#define DITHMODE_R_POS_5BIT                    (0x2 << 5)
-
-#define DITHMODE_G_POS_MASK                    (0x3 << 3)
-#define DITHMODE_G_POS_SHIFT                   (3)
-#define DITHMODE_G_POS_8BIT                    (0x0 << 3)
-#define DITHMODE_G_POS_6BIT                    (0x1 << 3)
-#define DITHMODE_G_POS_5BIT                    (0x2 << 3)
-
-#define DITHMODE_B_POS_MASK                    (0x3 << 1)
-#define DITHMODE_B_POS_SHIFT                   (1)
-#define DITHMODE_B_POS_8BIT                    (0x0 << 1)
-#define DITHMODE_B_POS_6BIT                    (0x1 << 1)
-#define DITHMODE_B_POS_5BIT                    (0x2 << 1)
-
-#define DITHMODE_DITH_EN                       (1 << 0)
-
-#define WPALCON                                        (0x1A0)
-
-/* Palette control */
-/* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L),
- * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */
-#define WPALCON_W4PAL_16BPP_A555               (1 << 8)
-#define WPALCON_W3PAL_16BPP_A555               (1 << 7)
-#define WPALCON_W2PAL_16BPP_A555               (1 << 6)
-
-
-/* Notes on per-window bpp settings
- *
- * Value       Win0     Win1     Win2     Win3     Win 4
- * 0000                1(P)     1(P)     1(P)     1(P)     1(P)
- * 0001                2(P)     2(P)     2(P)     2(P)     2(P)
- * 0010                4(P)     4(P)     4(P)     4(P)     -none-
- * 0011                8(P)     8(P)     -none-   -none-   -none-
- * 0100                -none-   8(A232)  8(A232)  -none-   -none-
- * 0101                16(565)  16(565)  16(565)  16(565)   16(565)
- * 0110                -none-   16(A555) 16(A555) 16(A555)  16(A555)
- * 0111                16(I555) 16(I565) 16(I555) 16(I555)  16(I555)
- * 1000                18(666)  18(666)  18(666)  18(666)   18(666)
- * 1001                -none-   18(A665) 18(A665) 18(A665)  16(A665)
- * 1010                -none-   19(A666) 19(A666) 19(A666)  19(A666)
- * 1011                24(888)  24(888)  24(888)  24(888)   24(888)
- * 1100                -none-   24(A887) 24(A887) 24(A887)  24(A887)
- * 1101                -none-   25(A888) 25(A888) 25(A888)  25(A888)
- * 1110                -none-   -none-   -none-   -none-    -none-
- * 1111                -none-   -none-   -none-   -none-    -none-
-*/
index 683c466c0e6a7242200a5f637a981ef011577bf8..147459327601ce50c85269b9b6143f2d072c60cd 100644 (file)
 #include <linux/spinlock.h>
 #include <mach/regs-clock.h>
 
-static int __s5p_mipi_phy_control(struct platform_device *pdev,
-                                 bool on, u32 reset)
+static int __s5p_mipi_phy_control(int id, bool on, u32 reset)
 {
        static DEFINE_SPINLOCK(lock);
        void __iomem *addr;
        unsigned long flags;
-       int pid;
        u32 cfg;
 
-       if (!pdev)
+       id = max(0, id);
+       if (id > 1)
                return -EINVAL;
 
-       pid = (pdev->id == -1) ? 0 : pdev->id;
-
-       if (pid != 0 && pid != 1)
-               return -EINVAL;
-
-       addr = S5P_MIPI_DPHY_CONTROL(pid);
+       addr = S5P_MIPI_DPHY_CONTROL(id);
 
        spin_lock_irqsave(&lock, flags);
 
@@ -52,12 +46,12 @@ static int __s5p_mipi_phy_control(struct platform_device *pdev,
        return 0;
 }
 
-int s5p_csis_phy_enable(struct platform_device *pdev, bool on)
+int s5p_csis_phy_enable(int id, bool on)
 {
-       return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_SRESETN);
+       return __s5p_mipi_phy_control(id, on, S5P_MIPI_DPHY_SRESETN);
 }
 
 int s5p_dsim_phy_enable(struct platform_device *pdev, bool on)
 {
-       return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_MRESETN);
+       return __s5p_mipi_phy_control(pdev->id, on, S5P_MIPI_DPHY_MRESETN);
 }
index 35924a542d4334358e9527d040f35e78e495cd27..fe77e51a7847bf872ebcc7cb18102d71c1b0af4a 100644 (file)
@@ -1,6 +1,4 @@
-include include/asm-generic/Kbuild.asm
 
-header-y += hwcap.h
 
 generic-y += bug.h
 generic-y += bugs.h
index db05f97661127ef5c16a0ab9c7c42794a1cee8f1..6d4482fa35bcbc183bf64d9239a4a5a87bb86705 100644 (file)
 #ifndef __ASM_HWCAP_H
 #define __ASM_HWCAP_H
 
-/*
- * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
- */
-#define HWCAP_FP               (1 << 0)
-#define HWCAP_ASIMD            (1 << 1)
+#include <uapi/asm/hwcap.h>
 
 #define COMPAT_HWCAP_HALF      (1 << 1)
 #define COMPAT_HWCAP_THUMB     (1 << 2)
@@ -35,7 +31,6 @@
 #define COMPAT_HWCAP_IDIVT     (1 << 18)
 #define COMPAT_HWCAP_IDIV      (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT)
 
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 /*
  * This yields a mask that user programs can use to figure out what
@@ -51,5 +46,3 @@
 extern unsigned int elf_hwcap;
 #endif
 #endif
-
-#endif
index 0fa5d6c9ef76ad87ca1e28690c0cb7c49dee30c0..b04d3404f0d1e4426e34553afe883dce562c4481 100644 (file)
@@ -19,9 +19,7 @@
 #ifndef __ASM_PTRACE_H
 #define __ASM_PTRACE_H
 
-#include <linux/types.h>
-
-#include <asm/hwcap.h>
+#include <uapi/asm/ptrace.h>
 
 /* AArch32-specific ptrace requests */
 #define COMPAT_PTRACE_GETREGS          12
 #define COMPAT_PTRACE_SETVFPREGS       28
 #define COMPAT_PTRACE_GETHBPREGS       29
 #define COMPAT_PTRACE_SETHBPREGS       30
-
-/*
- * PSR bits
- */
-#define PSR_MODE_EL0t  0x00000000
-#define PSR_MODE_EL1t  0x00000004
-#define PSR_MODE_EL1h  0x00000005
-#define PSR_MODE_EL2t  0x00000008
-#define PSR_MODE_EL2h  0x00000009
-#define PSR_MODE_EL3t  0x0000000c
-#define PSR_MODE_EL3h  0x0000000d
-#define PSR_MODE_MASK  0x0000000f
-
-/* AArch32 CPSR bits */
-#define PSR_MODE32_BIT         0x00000010
 #define COMPAT_PSR_MODE_USR    0x00000010
 #define COMPAT_PSR_T_BIT       0x00000020
 #define COMPAT_PSR_IT_MASK     0x0600fc00      /* If-Then execution state mask */
-
-/* AArch64 SPSR bits */
-#define PSR_F_BIT      0x00000040
-#define PSR_I_BIT      0x00000080
-#define PSR_A_BIT      0x00000100
-#define PSR_D_BIT      0x00000200
-#define PSR_Q_BIT      0x08000000
-#define PSR_V_BIT      0x10000000
-#define PSR_C_BIT      0x20000000
-#define PSR_Z_BIT      0x40000000
-#define PSR_N_BIT      0x80000000
-
-/*
- * Groups of PSR bits
- */
-#define PSR_f          0xff000000      /* Flags                */
-#define PSR_s          0x00ff0000      /* Status               */
-#define PSR_x          0x0000ff00      /* Extension            */
-#define PSR_c          0x000000ff      /* Control              */
-
 /*
  * These are 'magic' values for PTRACE_PEEKUSR that return info about where a
  * process is located in memory.
  */
-#define PT_TEXT_ADDR           0x10000
-#define PT_DATA_ADDR           0x10004
-#define PT_TEXT_END_ADDR       0x10008
-
+#define COMPAT_PT_TEXT_ADDR            0x10000
+#define COMPAT_PT_DATA_ADDR            0x10004
+#define COMPAT_PT_TEXT_END_ADDR                0x10008
 #ifndef __ASSEMBLY__
 
-/*
- * User structures for general purpose, floating point and debug registers.
- */
-struct user_pt_regs {
-       __u64           regs[31];
-       __u64           sp;
-       __u64           pc;
-       __u64           pstate;
-};
-
-struct user_fpsimd_state {
-       __uint128_t     vregs[32];
-       __u32           fpsr;
-       __u32           fpcr;
-};
-
-struct user_hwdebug_state {
-       __u32           dbg_info;
-       struct {
-               __u64   addr;
-               __u32   ctrl;
-       }               dbg_regs[16];
-};
-
-#ifdef __KERNEL__
-
 /* sizeof(struct user) for AArch32 */
 #define COMPAT_USER_SZ 296
 /* AArch32 uses x13 as the stack pointer... */
@@ -200,8 +136,5 @@ extern unsigned long profile_pc(struct pt_regs *regs);
 
 extern int aarch32_break_trap(struct pt_regs *regs);
 
-#endif /* __KERNEL__ */
-
 #endif /* __ASSEMBLY__ */
-
 #endif
index 573cec778819e43b11d367408dad752b955307e8..dca1094acc74c4e0047bad12096ebffb048fa2be 100644 (file)
 #ifndef __ASM_SIGCONTEXT_H
 #define __ASM_SIGCONTEXT_H
 
-#include <linux/types.h>
+#include <uapi/asm/sigcontext.h>
 
-/*
- * Signal context structure - contains all info to do with the state
- * before the signal handler was invoked.
- */
-struct sigcontext {
-       __u64 fault_address;
-       /* AArch64 registers */
-       __u64 regs[31];
-       __u64 sp;
-       __u64 pc;
-       __u64 pstate;
-       /* 4K reserved for FP/SIMD state and future expansion */
-       __u8 __reserved[4096] __attribute__((__aligned__(16)));
-};
-
-/*
- * Header to be used at the beginning of structures extending the user
- * context. Such structures must be placed after the rt_sigframe on the stack
- * and be 16-byte aligned. The last structure must be a dummy one with the
- * magic and size set to 0.
- */
-struct _aarch64_ctx {
-       __u32 magic;
-       __u32 size;
-};
-
-#define FPSIMD_MAGIC   0x46508001
-
-struct fpsimd_context {
-       struct _aarch64_ctx head;
-       __u32 fpsr;
-       __u32 fpcr;
-       __uint128_t vregs[32];
-};
-
-#ifdef __KERNEL__
 /*
  * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
  * user space as it will change with the addition of new context. User space
@@ -65,5 +29,3 @@ struct aux_context {
        struct _aarch64_ctx end;
 };
 #endif
-
-#endif
index a9f580c28f7ba1920d782931344b19a51b9a7ce8..15e35598ac407a99fb7d48770f00b298ee52ea0e 100644 (file)
@@ -16,9 +16,8 @@
 #ifndef __ASM_STAT_H
 #define __ASM_STAT_H
 
-#include <asm-generic/stat.h>
+#include <uapi/asm/stat.h>
 
-#ifdef __KERNEL__
 #ifdef CONFIG_COMPAT
 
 #include <asm/compat.h>
@@ -60,5 +59,3 @@ struct stat64 {
 
 #endif
 #endif
-
-#endif
index 8f03dee066ed0a16e56b94bbe361b49372bf07d2..63f853f8b718026a69342ce8bb46ff6fd948066e 100644 (file)
  * 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 __SYSCALL_COMPAT
-#include <asm-generic/unistd.h>
-#endif
-
-#ifdef __KERNEL__
 #ifdef CONFIG_COMPAT
-#include <asm/unistd32.h>
-#endif
+#define __ARCH_WANT_COMPAT_IPC_PARSE_VERSION
+#define __ARCH_WANT_COMPAT_STAT64
+#define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_PAUSE
+#define __ARCH_WANT_SYS_GETPGRP
+#define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_SYS_NICE
+#define __ARCH_WANT_SYS_SIGPENDING
+#define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_COMPAT_SYS_SENDFILE
 #endif
+#include <uapi/asm/unistd.h>
index ba42d41fc5c2398a97d5a0647067584a987cdc6b..6d909faebf28d155020ef96e17654d5ae74bed6f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Based on arch/arm/include/asm/unistd.h
+ * AArch32 (compat) system call definitions.
  *
  * Copyright (C) 2001-2005 Russell King
  * Copyright (C) 2012 ARM Ltd.
 #define __SYSCALL(x, y)
 #endif
 
+__SYSCALL(0,   sys_restart_syscall)
+__SYSCALL(1,   sys_exit)
+__SYSCALL(2,   compat_sys_fork_wrapper)
+__SYSCALL(3,   sys_read)
+__SYSCALL(4,   sys_write)
+__SYSCALL(5,   compat_sys_open)
+__SYSCALL(6,   sys_close)
+__SYSCALL(7,   sys_ni_syscall)                 /* 7 was sys_waitpid */
+__SYSCALL(8,   sys_creat)
+__SYSCALL(9,   sys_link)
+__SYSCALL(10,  sys_unlink)
+__SYSCALL(11,  compat_sys_execve_wrapper)
+__SYSCALL(12,  sys_chdir)
+__SYSCALL(13,  sys_ni_syscall)                 /* 13 was sys_time */
+__SYSCALL(14,  sys_mknod)
+__SYSCALL(15,  sys_chmod)
+__SYSCALL(16,  sys_lchown16)
+__SYSCALL(17,  sys_ni_syscall)                 /* 17 was sys_break */
+__SYSCALL(18,  sys_ni_syscall)                 /* 18 was sys_stat */
+__SYSCALL(19,  compat_sys_lseek_wrapper)
+__SYSCALL(20,  sys_getpid)
+__SYSCALL(21,  compat_sys_mount)
+__SYSCALL(22,  sys_ni_syscall)                 /* 22 was sys_umount */
+__SYSCALL(23,  sys_setuid16)
+__SYSCALL(24,  sys_getuid16)
+__SYSCALL(25,  sys_ni_syscall)                 /* 25 was sys_stime */
+__SYSCALL(26,  compat_sys_ptrace)
+__SYSCALL(27,  sys_ni_syscall)                 /* 27 was sys_alarm */
+__SYSCALL(28,  sys_ni_syscall)                 /* 28 was sys_fstat */
+__SYSCALL(29,  sys_pause)
+__SYSCALL(30,  sys_ni_syscall)                 /* 30 was sys_utime */
+__SYSCALL(31,  sys_ni_syscall)                 /* 31 was sys_stty */
+__SYSCALL(32,  sys_ni_syscall)                 /* 32 was sys_gtty */
+__SYSCALL(33,  sys_access)
+__SYSCALL(34,  sys_nice)
+__SYSCALL(35,  sys_ni_syscall)                 /* 35 was sys_ftime */
+__SYSCALL(36,  sys_sync)
+__SYSCALL(37,  sys_kill)
+__SYSCALL(38,  sys_rename)
+__SYSCALL(39,  sys_mkdir)
+__SYSCALL(40,  sys_rmdir)
+__SYSCALL(41,  sys_dup)
+__SYSCALL(42,  sys_pipe)
+__SYSCALL(43,  compat_sys_times)
+__SYSCALL(44,  sys_ni_syscall)                 /* 44 was sys_prof */
+__SYSCALL(45,  sys_brk)
+__SYSCALL(46,  sys_setgid16)
+__SYSCALL(47,  sys_getgid16)
+__SYSCALL(48,  sys_ni_syscall)                 /* 48 was sys_signal */
+__SYSCALL(49,  sys_geteuid16)
+__SYSCALL(50,  sys_getegid16)
+__SYSCALL(51,  sys_acct)
+__SYSCALL(52,  sys_umount)
+__SYSCALL(53,  sys_ni_syscall)                 /* 53 was sys_lock */
+__SYSCALL(54,  compat_sys_ioctl)
+__SYSCALL(55,  compat_sys_fcntl)
+__SYSCALL(56,  sys_ni_syscall)                 /* 56 was sys_mpx */
+__SYSCALL(57,  sys_setpgid)
+__SYSCALL(58,  sys_ni_syscall)                 /* 58 was sys_ulimit */
+__SYSCALL(59,  sys_ni_syscall)                 /* 59 was sys_olduname */
+__SYSCALL(60,  sys_umask)
+__SYSCALL(61,  sys_chroot)
+__SYSCALL(62,  compat_sys_ustat)
+__SYSCALL(63,  sys_dup2)
+__SYSCALL(64,  sys_getppid)
+__SYSCALL(65,  sys_getpgrp)
+__SYSCALL(66,  sys_setsid)
+__SYSCALL(67,  compat_sys_sigaction)
+__SYSCALL(68,  sys_ni_syscall)                 /* 68 was sys_sgetmask */
+__SYSCALL(69,  sys_ni_syscall)                 /* 69 was sys_ssetmask */
+__SYSCALL(70,  sys_setreuid16)
+__SYSCALL(71,  sys_setregid16)
+__SYSCALL(72,  compat_sys_sigsuspend)
+__SYSCALL(73,  compat_sys_sigpending)
+__SYSCALL(74,  sys_sethostname)
+__SYSCALL(75,  compat_sys_setrlimit)
+__SYSCALL(76,  sys_ni_syscall)                 /* 76 was compat_sys_getrlimit */
+__SYSCALL(77,  compat_sys_getrusage)
+__SYSCALL(78,  compat_sys_gettimeofday)
+__SYSCALL(79,  compat_sys_settimeofday)
+__SYSCALL(80,  sys_getgroups16)
+__SYSCALL(81,  sys_setgroups16)
+__SYSCALL(82,  sys_ni_syscall)                 /* 82 was compat_sys_select */
+__SYSCALL(83,  sys_symlink)
+__SYSCALL(84,  sys_ni_syscall)                 /* 84 was sys_lstat */
+__SYSCALL(85,  sys_readlink)
+__SYSCALL(86,  sys_uselib)
+__SYSCALL(87,  sys_swapon)
+__SYSCALL(88,  sys_reboot)
+__SYSCALL(89,  sys_ni_syscall)                 /* 89 was sys_readdir */
+__SYSCALL(90,  sys_ni_syscall)                 /* 90 was sys_mmap */
+__SYSCALL(91,  sys_munmap)
+__SYSCALL(92,  sys_truncate)
+__SYSCALL(93,  sys_ftruncate)
+__SYSCALL(94,  sys_fchmod)
+__SYSCALL(95,  sys_fchown16)
+__SYSCALL(96,  sys_getpriority)
+__SYSCALL(97,  sys_setpriority)
+__SYSCALL(98,  sys_ni_syscall)                 /* 98 was sys_profil */
+__SYSCALL(99,  compat_sys_statfs)
+__SYSCALL(100, compat_sys_fstatfs)
+__SYSCALL(101, sys_ni_syscall)                 /* 101 was sys_ioperm */
+__SYSCALL(102, sys_ni_syscall)                 /* 102 was sys_socketcall */
+__SYSCALL(103, sys_syslog)
+__SYSCALL(104, compat_sys_setitimer)
+__SYSCALL(105, compat_sys_getitimer)
+__SYSCALL(106, compat_sys_newstat)
+__SYSCALL(107, compat_sys_newlstat)
+__SYSCALL(108, compat_sys_newfstat)
+__SYSCALL(109, sys_ni_syscall)                 /* 109 was sys_uname */
+__SYSCALL(110, sys_ni_syscall)                 /* 110 was sys_iopl */
+__SYSCALL(111, sys_vhangup)
+__SYSCALL(112, sys_ni_syscall)                 /* 112 was sys_idle */
+__SYSCALL(113, sys_ni_syscall)                 /* 113 was sys_syscall */
+__SYSCALL(114, compat_sys_wait4)
+__SYSCALL(115, sys_swapoff)
+__SYSCALL(116, compat_sys_sysinfo)
+__SYSCALL(117, sys_ni_syscall)                 /* 117 was sys_ipc */
+__SYSCALL(118, sys_fsync)
+__SYSCALL(119, compat_sys_sigreturn_wrapper)
+__SYSCALL(120, compat_sys_clone_wrapper)
+__SYSCALL(121, sys_setdomainname)
+__SYSCALL(122, sys_newuname)
+__SYSCALL(123, sys_ni_syscall)                 /* 123 was sys_modify_ldt */
+__SYSCALL(124, compat_sys_adjtimex)
+__SYSCALL(125, sys_mprotect)
+__SYSCALL(126, compat_sys_sigprocmask)
+__SYSCALL(127, sys_ni_syscall)                 /* 127 was sys_create_module */
+__SYSCALL(128, sys_init_module)
+__SYSCALL(129, sys_delete_module)
+__SYSCALL(130, sys_ni_syscall)                 /* 130 was sys_get_kernel_syms */
+__SYSCALL(131, sys_quotactl)
+__SYSCALL(132, sys_getpgid)
+__SYSCALL(133, sys_fchdir)
+__SYSCALL(134, sys_bdflush)
+__SYSCALL(135, sys_sysfs)
+__SYSCALL(136, sys_personality)
+__SYSCALL(137, sys_ni_syscall)                 /* 137 was sys_afs_syscall */
+__SYSCALL(138, sys_setfsuid16)
+__SYSCALL(139, sys_setfsgid16)
+__SYSCALL(140, sys_llseek)
+__SYSCALL(141, compat_sys_getdents)
+__SYSCALL(142, compat_sys_select)
+__SYSCALL(143, sys_flock)
+__SYSCALL(144, sys_msync)
+__SYSCALL(145, compat_sys_readv)
+__SYSCALL(146, compat_sys_writev)
+__SYSCALL(147, sys_getsid)
+__SYSCALL(148, sys_fdatasync)
+__SYSCALL(149, compat_sys_sysctl)
+__SYSCALL(150, sys_mlock)
+__SYSCALL(151, sys_munlock)
+__SYSCALL(152, sys_mlockall)
+__SYSCALL(153, sys_munlockall)
+__SYSCALL(154, sys_sched_setparam)
+__SYSCALL(155, sys_sched_getparam)
+__SYSCALL(156, sys_sched_setscheduler)
+__SYSCALL(157, sys_sched_getscheduler)
+__SYSCALL(158, sys_sched_yield)
+__SYSCALL(159, sys_sched_get_priority_max)
+__SYSCALL(160, sys_sched_get_priority_min)
+__SYSCALL(161, compat_sys_sched_rr_get_interval)
+__SYSCALL(162, compat_sys_nanosleep)
+__SYSCALL(163, sys_mremap)
+__SYSCALL(164, sys_setresuid16)
+__SYSCALL(165, sys_getresuid16)
+__SYSCALL(166, sys_ni_syscall)                 /* 166 was sys_vm86 */
+__SYSCALL(167, sys_ni_syscall)                 /* 167 was sys_query_module */
+__SYSCALL(168, sys_poll)
+__SYSCALL(169, sys_ni_syscall)
+__SYSCALL(170, sys_setresgid16)
+__SYSCALL(171, sys_getresgid16)
+__SYSCALL(172, sys_prctl)
+__SYSCALL(173, compat_sys_rt_sigreturn_wrapper)
+__SYSCALL(174, compat_sys_rt_sigaction)
+__SYSCALL(175, compat_sys_rt_sigprocmask)
+__SYSCALL(176, compat_sys_rt_sigpending)
+__SYSCALL(177, compat_sys_rt_sigtimedwait)
+__SYSCALL(178, compat_sys_rt_sigqueueinfo)
+__SYSCALL(179, compat_sys_rt_sigsuspend)
+__SYSCALL(180, compat_sys_pread64_wrapper)
+__SYSCALL(181, compat_sys_pwrite64_wrapper)
+__SYSCALL(182, sys_chown16)
+__SYSCALL(183, sys_getcwd)
+__SYSCALL(184, sys_capget)
+__SYSCALL(185, sys_capset)
+__SYSCALL(186, compat_sys_sigaltstack_wrapper)
+__SYSCALL(187, compat_sys_sendfile)
+__SYSCALL(188, sys_ni_syscall)                 /* 188 reserved */
+__SYSCALL(189, sys_ni_syscall)                 /* 189 reserved */
+__SYSCALL(190, compat_sys_vfork_wrapper)
+__SYSCALL(191, compat_sys_getrlimit)           /* SuS compliant getrlimit */
+__SYSCALL(192, sys_mmap_pgoff)
+__SYSCALL(193, compat_sys_truncate64_wrapper)
+__SYSCALL(194, compat_sys_ftruncate64_wrapper)
+__SYSCALL(195, sys_stat64)
+__SYSCALL(196, sys_lstat64)
+__SYSCALL(197, sys_fstat64)
+__SYSCALL(198, sys_lchown)
+__SYSCALL(199, sys_getuid)
+__SYSCALL(200, sys_getgid)
+__SYSCALL(201, sys_geteuid)
+__SYSCALL(202, sys_getegid)
+__SYSCALL(203, sys_setreuid)
+__SYSCALL(204, sys_setregid)
+__SYSCALL(205, sys_getgroups)
+__SYSCALL(206, sys_setgroups)
+__SYSCALL(207, sys_fchown)
+__SYSCALL(208, sys_setresuid)
+__SYSCALL(209, sys_getresuid)
+__SYSCALL(210, sys_setresgid)
+__SYSCALL(211, sys_getresgid)
+__SYSCALL(212, sys_chown)
+__SYSCALL(213, sys_setuid)
+__SYSCALL(214, sys_setgid)
+__SYSCALL(215, sys_setfsuid)
+__SYSCALL(216, sys_setfsgid)
+__SYSCALL(217, compat_sys_getdents64)
+__SYSCALL(218, sys_pivot_root)
+__SYSCALL(219, sys_mincore)
+__SYSCALL(220, sys_madvise)
+__SYSCALL(221, compat_sys_fcntl64)
+__SYSCALL(222, sys_ni_syscall)                 /* 222 for tux */
+__SYSCALL(223, sys_ni_syscall)                 /* 223 is unused */
+__SYSCALL(224, sys_gettid)
+__SYSCALL(225, compat_sys_readahead_wrapper)
+__SYSCALL(226, sys_setxattr)
+__SYSCALL(227, sys_lsetxattr)
+__SYSCALL(228, sys_fsetxattr)
+__SYSCALL(229, sys_getxattr)
+__SYSCALL(230, sys_lgetxattr)
+__SYSCALL(231, sys_fgetxattr)
+__SYSCALL(232, sys_listxattr)
+__SYSCALL(233, sys_llistxattr)
+__SYSCALL(234, sys_flistxattr)
+__SYSCALL(235, sys_removexattr)
+__SYSCALL(236, sys_lremovexattr)
+__SYSCALL(237, sys_fremovexattr)
+__SYSCALL(238, sys_tkill)
+__SYSCALL(239, sys_sendfile64)
+__SYSCALL(240, compat_sys_futex)
+__SYSCALL(241, compat_sys_sched_setaffinity)
+__SYSCALL(242, compat_sys_sched_getaffinity)
+__SYSCALL(243, compat_sys_io_setup)
+__SYSCALL(244, sys_io_destroy)
+__SYSCALL(245, compat_sys_io_getevents)
+__SYSCALL(246, compat_sys_io_submit)
+__SYSCALL(247, sys_io_cancel)
+__SYSCALL(248, sys_exit_group)
+__SYSCALL(249, compat_sys_lookup_dcookie)
+__SYSCALL(250, sys_epoll_create)
+__SYSCALL(251, sys_epoll_ctl)
+__SYSCALL(252, sys_epoll_wait)
+__SYSCALL(253, sys_remap_file_pages)
+__SYSCALL(254, sys_ni_syscall)                 /* 254 for set_thread_area */
+__SYSCALL(255, sys_ni_syscall)                 /* 255 for get_thread_area */
+__SYSCALL(256, sys_set_tid_address)
+__SYSCALL(257, compat_sys_timer_create)
+__SYSCALL(258, compat_sys_timer_settime)
+__SYSCALL(259, compat_sys_timer_gettime)
+__SYSCALL(260, sys_timer_getoverrun)
+__SYSCALL(261, sys_timer_delete)
+__SYSCALL(262, compat_sys_clock_settime)
+__SYSCALL(263, compat_sys_clock_gettime)
+__SYSCALL(264, compat_sys_clock_getres)
+__SYSCALL(265, compat_sys_clock_nanosleep)
+__SYSCALL(266, compat_sys_statfs64_wrapper)
+__SYSCALL(267, compat_sys_fstatfs64_wrapper)
+__SYSCALL(268, sys_tgkill)
+__SYSCALL(269, compat_sys_utimes)
+__SYSCALL(270, compat_sys_fadvise64_64_wrapper)
+__SYSCALL(271, sys_pciconfig_iobase)
+__SYSCALL(272, sys_pciconfig_read)
+__SYSCALL(273, sys_pciconfig_write)
+__SYSCALL(274, compat_sys_mq_open)
+__SYSCALL(275, sys_mq_unlink)
+__SYSCALL(276, compat_sys_mq_timedsend)
+__SYSCALL(277, compat_sys_mq_timedreceive)
+__SYSCALL(278, compat_sys_mq_notify)
+__SYSCALL(279, compat_sys_mq_getsetattr)
+__SYSCALL(280, compat_sys_waitid)
+__SYSCALL(281, sys_socket)
+__SYSCALL(282, sys_bind)
+__SYSCALL(283, sys_connect)
+__SYSCALL(284, sys_listen)
+__SYSCALL(285, sys_accept)
+__SYSCALL(286, sys_getsockname)
+__SYSCALL(287, sys_getpeername)
+__SYSCALL(288, sys_socketpair)
+__SYSCALL(289, sys_send)
+__SYSCALL(290, sys_sendto)
+__SYSCALL(291, compat_sys_recv)
+__SYSCALL(292, compat_sys_recvfrom)
+__SYSCALL(293, sys_shutdown)
+__SYSCALL(294, compat_sys_setsockopt)
+__SYSCALL(295, compat_sys_getsockopt)
+__SYSCALL(296, compat_sys_sendmsg)
+__SYSCALL(297, compat_sys_recvmsg)
+__SYSCALL(298, sys_semop)
+__SYSCALL(299, sys_semget)
+__SYSCALL(300, compat_sys_semctl)
+__SYSCALL(301, compat_sys_msgsnd)
+__SYSCALL(302, compat_sys_msgrcv)
+__SYSCALL(303, sys_msgget)
+__SYSCALL(304, compat_sys_msgctl)
+__SYSCALL(305, compat_sys_shmat)
+__SYSCALL(306, sys_shmdt)
+__SYSCALL(307, sys_shmget)
+__SYSCALL(308, compat_sys_shmctl)
+__SYSCALL(309, sys_add_key)
+__SYSCALL(310, sys_request_key)
+__SYSCALL(311, compat_sys_keyctl)
+__SYSCALL(312, compat_sys_semtimedop)
+__SYSCALL(313, sys_ni_syscall)
+__SYSCALL(314, sys_ioprio_set)
+__SYSCALL(315, sys_ioprio_get)
+__SYSCALL(316, sys_inotify_init)
+__SYSCALL(317, sys_inotify_add_watch)
+__SYSCALL(318, sys_inotify_rm_watch)
+__SYSCALL(319, compat_sys_mbind)
+__SYSCALL(320, compat_sys_get_mempolicy)
+__SYSCALL(321, compat_sys_set_mempolicy)
+__SYSCALL(322, compat_sys_openat)
+__SYSCALL(323, sys_mkdirat)
+__SYSCALL(324, sys_mknodat)
+__SYSCALL(325, sys_fchownat)
+__SYSCALL(326, compat_sys_futimesat)
+__SYSCALL(327, sys_fstatat64)
+__SYSCALL(328, sys_unlinkat)
+__SYSCALL(329, sys_renameat)
+__SYSCALL(330, sys_linkat)
+__SYSCALL(331, sys_symlinkat)
+__SYSCALL(332, sys_readlinkat)
+__SYSCALL(333, sys_fchmodat)
+__SYSCALL(334, sys_faccessat)
+__SYSCALL(335, compat_sys_pselect6)
+__SYSCALL(336, compat_sys_ppoll)
+__SYSCALL(337, sys_unshare)
+__SYSCALL(338, compat_sys_set_robust_list)
+__SYSCALL(339, compat_sys_get_robust_list)
+__SYSCALL(340, sys_splice)
+__SYSCALL(341, compat_sys_sync_file_range2_wrapper)
+__SYSCALL(342, sys_tee)
+__SYSCALL(343, compat_sys_vmsplice)
+__SYSCALL(344, compat_sys_move_pages)
+__SYSCALL(345, sys_getcpu)
+__SYSCALL(346, compat_sys_epoll_pwait)
+__SYSCALL(347, compat_sys_kexec_load)
+__SYSCALL(348, compat_sys_utimensat)
+__SYSCALL(349, compat_sys_signalfd)
+__SYSCALL(350, sys_timerfd_create)
+__SYSCALL(351, sys_eventfd)
+__SYSCALL(352, compat_sys_fallocate_wrapper)
+__SYSCALL(353, compat_sys_timerfd_settime)
+__SYSCALL(354, compat_sys_timerfd_gettime)
+__SYSCALL(355, compat_sys_signalfd4)
+__SYSCALL(356, sys_eventfd2)
+__SYSCALL(357, sys_epoll_create1)
+__SYSCALL(358, sys_dup3)
+__SYSCALL(359, sys_pipe2)
+__SYSCALL(360, sys_inotify_init1)
+__SYSCALL(361, compat_sys_preadv)
+__SYSCALL(362, compat_sys_pwritev)
+__SYSCALL(363, compat_sys_rt_tgsigqueueinfo)
+__SYSCALL(364, sys_perf_event_open)
+__SYSCALL(365, compat_sys_recvmmsg)
+__SYSCALL(366, sys_accept4)
+__SYSCALL(367, sys_fanotify_init)
+__SYSCALL(368, compat_sys_fanotify_mark_wrapper)
+__SYSCALL(369, sys_prlimit64)
+__SYSCALL(370, sys_name_to_handle_at)
+__SYSCALL(371, sys_open_by_handle_at)
+__SYSCALL(372, sys_clock_adjtime)
+__SYSCALL(373, sys_syncfs)
+
+#define __NR_compat_syscalls           374
+
 /*
- * This file contains the system call numbers.
+ * Compat syscall numbers used by the AArch64 kernel.
  */
+#define __NR_compat_restart_syscall    0
+#define __NR_compat_sigreturn          119
+#define __NR_compat_rt_sigreturn       173
 
-#ifdef __SYSCALL_COMPAT
-
-#define __NR_restart_syscall           0
-__SYSCALL(__NR_restart_syscall, sys_restart_syscall)
-#define __NR_exit                      1
-__SYSCALL(__NR_exit, sys_exit)
-#define __NR_fork                      2
-__SYSCALL(__NR_fork, sys_fork)
-#define __NR_read                      3
-__SYSCALL(__NR_read, sys_read)
-#define __NR_write                     4
-__SYSCALL(__NR_write, sys_write)
-#define __NR_open                      5
-__SYSCALL(__NR_open, sys_open)
-#define __NR_close                     6
-__SYSCALL(__NR_close, sys_close)
-__SYSCALL(7, sys_ni_syscall)           /* 7 was sys_waitpid */
-#define __NR_creat                     8
-__SYSCALL(__NR_creat, sys_creat)
-#define __NR_link                      9
-__SYSCALL(__NR_link, sys_link)
-#define __NR_unlink                    10
-__SYSCALL(__NR_unlink, sys_unlink)
-#define __NR_execve                    11
-__SYSCALL(__NR_execve, sys_execve)
-#define __NR_chdir                     12
-__SYSCALL(__NR_chdir, sys_chdir)
-__SYSCALL(13, sys_ni_syscall)          /* 13 was sys_time */
-#define __NR_mknod                     14
-__SYSCALL(__NR_mknod, sys_mknod)
-#define __NR_chmod                     15
-__SYSCALL(__NR_chmod, sys_chmod)
-#define __NR_lchown                    16
-__SYSCALL(__NR_lchown, sys_lchown16)
-__SYSCALL(17, sys_ni_syscall)          /* 17 was sys_break */
-__SYSCALL(18, sys_ni_syscall)          /* 18 was sys_stat */
-#define __NR_lseek                     19
-__SYSCALL(__NR_lseek, sys_lseek)
-#define __NR_getpid                    20
-__SYSCALL(__NR_getpid, sys_getpid)
-#define __NR_mount                     21
-__SYSCALL(__NR_mount, sys_mount)
-__SYSCALL(22, sys_ni_syscall)          /* 22 was sys_umount */
-#define __NR_setuid                    23
-__SYSCALL(__NR_setuid, sys_setuid16)
-#define __NR_getuid                    24
-__SYSCALL(__NR_getuid, sys_getuid16)
-__SYSCALL(25, sys_ni_syscall)          /* 25 was sys_stime */
-#define __NR_ptrace                    26
-__SYSCALL(__NR_ptrace, sys_ptrace)
-__SYSCALL(27, sys_ni_syscall)          /* 27 was sys_alarm */
-__SYSCALL(28, sys_ni_syscall)          /* 28 was sys_fstat */
-#define __NR_pause                     29
-__SYSCALL(__NR_pause, sys_pause)
-__SYSCALL(30, sys_ni_syscall)          /* 30 was sys_utime */
-__SYSCALL(31, sys_ni_syscall)          /* 31 was sys_stty */
-__SYSCALL(32, sys_ni_syscall)          /* 32 was sys_gtty */
-#define __NR_access                    33
-__SYSCALL(__NR_access, sys_access)
-#define __NR_nice                      34
-__SYSCALL(__NR_nice, sys_nice)
-__SYSCALL(35, sys_ni_syscall)          /* 35 was sys_ftime */
-#define __NR_sync                      36
-__SYSCALL(__NR_sync, sys_sync)
-#define __NR_kill                      37
-__SYSCALL(__NR_kill, sys_kill)
-#define __NR_rename                    38
-__SYSCALL(__NR_rename, sys_rename)
-#define __NR_mkdir                     39
-__SYSCALL(__NR_mkdir, sys_mkdir)
-#define __NR_rmdir                     40
-__SYSCALL(__NR_rmdir, sys_rmdir)
-#define __NR_dup                       41
-__SYSCALL(__NR_dup, sys_dup)
-#define __NR_pipe                      42
-__SYSCALL(__NR_pipe, sys_pipe)
-#define __NR_times                     43
-__SYSCALL(__NR_times, sys_times)
-__SYSCALL(44, sys_ni_syscall)          /* 44 was sys_prof */
-#define __NR_brk                       45
-__SYSCALL(__NR_brk, sys_brk)
-#define __NR_setgid                    46
-__SYSCALL(__NR_setgid, sys_setgid16)
-#define __NR_getgid                    47
-__SYSCALL(__NR_getgid, sys_getgid16)
-__SYSCALL(48, sys_ni_syscall)          /* 48 was sys_signal */
-#define __NR_geteuid                   49
-__SYSCALL(__NR_geteuid, sys_geteuid16)
-#define __NR_getegid                   50
-__SYSCALL(__NR_getegid, sys_getegid16)
-#define __NR_acct                      51
-__SYSCALL(__NR_acct, sys_acct)
-#define __NR_umount2                   52
-__SYSCALL(__NR_umount2, sys_umount)
-__SYSCALL(53, sys_ni_syscall)          /* 53 was sys_lock */
-#define __NR_ioctl                     54
-__SYSCALL(__NR_ioctl, sys_ioctl)
-#define __NR_fcntl                     55
-__SYSCALL(__NR_fcntl, sys_fcntl)
-__SYSCALL(56, sys_ni_syscall)          /* 56 was sys_mpx */
-#define __NR_setpgid                   57
-__SYSCALL(__NR_setpgid, sys_setpgid)
-__SYSCALL(58, sys_ni_syscall)          /* 58 was sys_ulimit */
-__SYSCALL(59, sys_ni_syscall)          /* 59 was sys_olduname */
-#define __NR_umask                     60
-__SYSCALL(__NR_umask, sys_umask)
-#define __NR_chroot                    61
-__SYSCALL(__NR_chroot, sys_chroot)
-#define __NR_ustat                     62
-__SYSCALL(__NR_ustat, sys_ustat)
-#define __NR_dup2                      63
-__SYSCALL(__NR_dup2, sys_dup2)
-#define __NR_getppid                   64
-__SYSCALL(__NR_getppid, sys_getppid)
-#define __NR_getpgrp                   65
-__SYSCALL(__NR_getpgrp, sys_getpgrp)
-#define __NR_setsid                    66
-__SYSCALL(__NR_setsid, sys_setsid)
-#define __NR_sigaction                 67
-__SYSCALL(__NR_sigaction, sys_sigaction)
-__SYSCALL(68, sys_ni_syscall)          /* 68 was sys_sgetmask */
-__SYSCALL(69, sys_ni_syscall)          /* 69 was sys_ssetmask */
-#define __NR_setreuid                  70
-__SYSCALL(__NR_setreuid, sys_setreuid16)
-#define __NR_setregid                  71
-__SYSCALL(__NR_setregid, sys_setregid16)
-#define __NR_sigsuspend                        72
-__SYSCALL(__NR_sigsuspend, sys_sigsuspend)
-#define __NR_sigpending                        73
-__SYSCALL(__NR_sigpending, sys_sigpending)
-#define __NR_sethostname               74
-__SYSCALL(__NR_sethostname, sys_sethostname)
-#define __NR_setrlimit                 75
-__SYSCALL(__NR_setrlimit, sys_setrlimit)
-__SYSCALL(76, sys_ni_syscall)          /* 76 was sys_getrlimit */
-#define __NR_getrusage                 77
-__SYSCALL(__NR_getrusage, sys_getrusage)
-#define __NR_gettimeofday              78
-__SYSCALL(__NR_gettimeofday, sys_gettimeofday)
-#define __NR_settimeofday              79
-__SYSCALL(__NR_settimeofday, sys_settimeofday)
-#define __NR_getgroups                 80
-__SYSCALL(__NR_getgroups, sys_getgroups16)
-#define __NR_setgroups                 81
-__SYSCALL(__NR_setgroups, sys_setgroups16)
-__SYSCALL(82, sys_ni_syscall)          /* 82 was sys_select */
-#define __NR_symlink                   83
-__SYSCALL(__NR_symlink, sys_symlink)
-__SYSCALL(84, sys_ni_syscall)          /* 84 was sys_lstat */
-#define __NR_readlink                  85
-__SYSCALL(__NR_readlink, sys_readlink)
-#define __NR_uselib                    86
-__SYSCALL(__NR_uselib, sys_uselib)
-#define __NR_swapon                    87
-__SYSCALL(__NR_swapon, sys_swapon)
-#define __NR_reboot                    88
-__SYSCALL(__NR_reboot, sys_reboot)
-__SYSCALL(89, sys_ni_syscall)          /* 89 was sys_readdir */
-__SYSCALL(90, sys_ni_syscall)          /* 90 was sys_mmap */
-#define __NR_munmap                    91
-__SYSCALL(__NR_munmap, sys_munmap)
-#define __NR_truncate                  92
-__SYSCALL(__NR_truncate, sys_truncate)
-#define __NR_ftruncate                 93
-__SYSCALL(__NR_ftruncate, sys_ftruncate)
-#define __NR_fchmod                    94
-__SYSCALL(__NR_fchmod, sys_fchmod)
-#define __NR_fchown                    95
-__SYSCALL(__NR_fchown, sys_fchown16)
-#define __NR_getpriority               96
-__SYSCALL(__NR_getpriority, sys_getpriority)
-#define __NR_setpriority               97
-__SYSCALL(__NR_setpriority, sys_setpriority)
-__SYSCALL(98, sys_ni_syscall)          /* 98 was sys_profil */
-#define __NR_statfs                    99
-__SYSCALL(__NR_statfs, sys_statfs)
-#define __NR_fstatfs                   100
-__SYSCALL(__NR_fstatfs, sys_fstatfs)
-__SYSCALL(101, sys_ni_syscall)         /* 101 was sys_ioperm */
-__SYSCALL(102, sys_ni_syscall)         /* 102 was sys_socketcall */
-#define __NR_syslog                    103
-__SYSCALL(__NR_syslog, sys_syslog)
-#define __NR_setitimer                 104
-__SYSCALL(__NR_setitimer, sys_setitimer)
-#define __NR_getitimer                 105
-__SYSCALL(__NR_getitimer, sys_getitimer)
-#define __NR_stat                      106
-__SYSCALL(__NR_stat, sys_newstat)
-#define __NR_lstat                     107
-__SYSCALL(__NR_lstat, sys_newlstat)
-#define __NR_fstat                     108
-__SYSCALL(__NR_fstat, sys_newfstat)
-__SYSCALL(109, sys_ni_syscall)         /* 109 was sys_uname */
-__SYSCALL(110, sys_ni_syscall)         /* 110 was sys_iopl */
-#define __NR_vhangup                   111
-__SYSCALL(__NR_vhangup, sys_vhangup)
-__SYSCALL(112, sys_ni_syscall)         /* 112 was sys_idle */
-__SYSCALL(113, sys_ni_syscall)         /* 113 was sys_syscall */
-#define __NR_wait4                     114
-__SYSCALL(__NR_wait4, sys_wait4)
-#define __NR_swapoff                   115
-__SYSCALL(__NR_swapoff, sys_swapoff)
-#define __NR_sysinfo                   116
-__SYSCALL(__NR_sysinfo, sys_sysinfo)
-__SYSCALL(117, sys_ni_syscall)         /* 117 was sys_ipc */
-#define __NR_fsync                     118
-__SYSCALL(__NR_fsync, sys_fsync)
-#define __NR_sigreturn                 119
-__SYSCALL(__NR_sigreturn, sys_sigreturn)
-#define __NR_clone                     120
-__SYSCALL(__NR_clone, sys_clone)
-#define __NR_setdomainname             121
-__SYSCALL(__NR_setdomainname, sys_setdomainname)
-#define __NR_uname                     122
-__SYSCALL(__NR_uname, sys_newuname)
-__SYSCALL(123, sys_ni_syscall)         /* 123 was sys_modify_ldt */
-#define __NR_adjtimex                  124
-__SYSCALL(__NR_adjtimex, sys_adjtimex)
-#define __NR_mprotect                  125
-__SYSCALL(__NR_mprotect, sys_mprotect)
-#define __NR_sigprocmask               126
-__SYSCALL(__NR_sigprocmask, sys_sigprocmask)
-__SYSCALL(127, sys_ni_syscall)         /* 127 was sys_create_module */
-#define __NR_init_module               128
-__SYSCALL(__NR_init_module, sys_init_module)
-#define __NR_delete_module             129
-__SYSCALL(__NR_delete_module, sys_delete_module)
-__SYSCALL(130, sys_ni_syscall)         /* 130 was sys_get_kernel_syms */
-#define __NR_quotactl                  131
-__SYSCALL(__NR_quotactl, sys_quotactl)
-#define __NR_getpgid                   132
-__SYSCALL(__NR_getpgid, sys_getpgid)
-#define __NR_fchdir                    133
-__SYSCALL(__NR_fchdir, sys_fchdir)
-#define __NR_bdflush                   134
-__SYSCALL(__NR_bdflush, sys_bdflush)
-#define __NR_sysfs                     135
-__SYSCALL(__NR_sysfs, sys_sysfs)
-#define __NR_personality               136
-__SYSCALL(__NR_personality, sys_personality)
-__SYSCALL(137, sys_ni_syscall)         /* 137 was sys_afs_syscall */
-#define __NR_setfsuid                  138
-__SYSCALL(__NR_setfsuid, sys_setfsuid16)
-#define __NR_setfsgid                  139
-__SYSCALL(__NR_setfsgid, sys_setfsgid16)
-#define __NR__llseek                   140
-__SYSCALL(__NR__llseek, sys_llseek)
-#define __NR_getdents                  141
-__SYSCALL(__NR_getdents, sys_getdents)
-#define __NR__newselect                        142
-__SYSCALL(__NR__newselect, sys_select)
-#define __NR_flock                     143
-__SYSCALL(__NR_flock, sys_flock)
-#define __NR_msync                     144
-__SYSCALL(__NR_msync, sys_msync)
-#define __NR_readv                     145
-__SYSCALL(__NR_readv, sys_readv)
-#define __NR_writev                    146
-__SYSCALL(__NR_writev, sys_writev)
-#define __NR_getsid                    147
-__SYSCALL(__NR_getsid, sys_getsid)
-#define __NR_fdatasync                 148
-__SYSCALL(__NR_fdatasync, sys_fdatasync)
-#define __NR__sysctl                   149
-__SYSCALL(__NR__sysctl, sys_sysctl)
-#define __NR_mlock                     150
-__SYSCALL(__NR_mlock, sys_mlock)
-#define __NR_munlock                   151
-__SYSCALL(__NR_munlock, sys_munlock)
-#define __NR_mlockall                  152
-__SYSCALL(__NR_mlockall, sys_mlockall)
-#define __NR_munlockall                        153
-__SYSCALL(__NR_munlockall, sys_munlockall)
-#define __NR_sched_setparam            154
-__SYSCALL(__NR_sched_setparam, sys_sched_setparam)
-#define __NR_sched_getparam            155
-__SYSCALL(__NR_sched_getparam, sys_sched_getparam)
-#define __NR_sched_setscheduler                156
-__SYSCALL(__NR_sched_setscheduler, sys_sched_setscheduler)
-#define __NR_sched_getscheduler                157
-__SYSCALL(__NR_sched_getscheduler, sys_sched_getscheduler)
-#define __NR_sched_yield               158
-__SYSCALL(__NR_sched_yield, sys_sched_yield)
-#define __NR_sched_get_priority_max    159
-__SYSCALL(__NR_sched_get_priority_max, sys_sched_get_priority_max)
-#define __NR_sched_get_priority_min    160
-__SYSCALL(__NR_sched_get_priority_min, sys_sched_get_priority_min)
-#define __NR_sched_rr_get_interval     161
-__SYSCALL(__NR_sched_rr_get_interval, sys_sched_rr_get_interval)
-#define __NR_nanosleep                 162
-__SYSCALL(__NR_nanosleep, sys_nanosleep)
-#define __NR_mremap                    163
-__SYSCALL(__NR_mremap, sys_mremap)
-#define __NR_setresuid                 164
-__SYSCALL(__NR_setresuid, sys_setresuid16)
-#define __NR_getresuid                 165
-__SYSCALL(__NR_getresuid, sys_getresuid16)
-__SYSCALL(166, sys_ni_syscall)         /* 166 was sys_vm86 */
-__SYSCALL(167, sys_ni_syscall)         /* 167 was sys_query_module */
-#define __NR_poll                      168
-__SYSCALL(__NR_poll, sys_poll)
-#define __NR_nfsservctl                        169
-__SYSCALL(__NR_nfsservctl, sys_ni_syscall)
-#define __NR_setresgid                 170
-__SYSCALL(__NR_setresgid, sys_setresgid16)
-#define __NR_getresgid                 171
-__SYSCALL(__NR_getresgid, sys_getresgid16)
-#define __NR_prctl                     172
-__SYSCALL(__NR_prctl, sys_prctl)
-#define __NR_rt_sigreturn              173
-__SYSCALL(__NR_rt_sigreturn, sys_rt_sigreturn)
-#define __NR_rt_sigaction              174
-__SYSCALL(__NR_rt_sigaction, sys_rt_sigaction)
-#define __NR_rt_sigprocmask            175
-__SYSCALL(__NR_rt_sigprocmask, sys_rt_sigprocmask)
-#define __NR_rt_sigpending             176
-__SYSCALL(__NR_rt_sigpending, sys_rt_sigpending)
-#define __NR_rt_sigtimedwait           177
-__SYSCALL(__NR_rt_sigtimedwait, sys_rt_sigtimedwait)
-#define __NR_rt_sigqueueinfo           178
-__SYSCALL(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo)
-#define __NR_rt_sigsuspend             179
-__SYSCALL(__NR_rt_sigsuspend, sys_rt_sigsuspend)
-#define __NR_pread64                   180
-__SYSCALL(__NR_pread64, sys_pread64)
-#define __NR_pwrite64                  181
-__SYSCALL(__NR_pwrite64, sys_pwrite64)
-#define __NR_chown                     182
-__SYSCALL(__NR_chown, sys_chown16)
-#define __NR_getcwd                    183
-__SYSCALL(__NR_getcwd, sys_getcwd)
-#define __NR_capget                    184
-__SYSCALL(__NR_capget, sys_capget)
-#define __NR_capset                    185
-__SYSCALL(__NR_capset, sys_capset)
-#define __NR_sigaltstack               186
-__SYSCALL(__NR_sigaltstack, sys_sigaltstack)
-#define __NR_sendfile                  187
-__SYSCALL(__NR_sendfile, sys_sendfile)
-__SYSCALL(188, sys_ni_syscall)         /* 188 reserved */
-__SYSCALL(189, sys_ni_syscall)         /* 189 reserved */
-#define __NR_vfork                     190
-__SYSCALL(__NR_vfork, sys_vfork)
-#define __NR_ugetrlimit                        191     /* SuS compliant getrlimit */
-__SYSCALL(__NR_ugetrlimit, sys_getrlimit)
-#define __NR_mmap2                     192
-__SYSCALL(__NR_mmap2, sys_mmap2)
-#define __NR_truncate64                        193
-__SYSCALL(__NR_truncate64, sys_truncate64)
-#define __NR_ftruncate64               194
-__SYSCALL(__NR_ftruncate64, sys_ftruncate64)
-#define __NR_stat64                    195
-__SYSCALL(__NR_stat64, sys_stat64)
-#define __NR_lstat64                   196
-__SYSCALL(__NR_lstat64, sys_lstat64)
-#define __NR_fstat64                   197
-__SYSCALL(__NR_fstat64, sys_fstat64)
-#define __NR_lchown32                  198
-__SYSCALL(__NR_lchown32, sys_lchown)
-#define __NR_getuid32                  199
-__SYSCALL(__NR_getuid32, sys_getuid)
-#define __NR_getgid32                  200
-__SYSCALL(__NR_getgid32, sys_getgid)
-#define __NR_geteuid32                 201
-__SYSCALL(__NR_geteuid32, sys_geteuid)
-#define __NR_getegid32                 202
-__SYSCALL(__NR_getegid32, sys_getegid)
-#define __NR_setreuid32                        203
-__SYSCALL(__NR_setreuid32, sys_setreuid)
-#define __NR_setregid32                        204
-__SYSCALL(__NR_setregid32, sys_setregid)
-#define __NR_getgroups32               205
-__SYSCALL(__NR_getgroups32, sys_getgroups)
-#define __NR_setgroups32               206
-__SYSCALL(__NR_setgroups32, sys_setgroups)
-#define __NR_fchown32                  207
-__SYSCALL(__NR_fchown32, sys_fchown)
-#define __NR_setresuid32               208
-__SYSCALL(__NR_setresuid32, sys_setresuid)
-#define __NR_getresuid32               209
-__SYSCALL(__NR_getresuid32, sys_getresuid)
-#define __NR_setresgid32               210
-__SYSCALL(__NR_setresgid32, sys_setresgid)
-#define __NR_getresgid32               211
-__SYSCALL(__NR_getresgid32, sys_getresgid)
-#define __NR_chown32                   212
-__SYSCALL(__NR_chown32, sys_chown)
-#define __NR_setuid32                  213
-__SYSCALL(__NR_setuid32, sys_setuid)
-#define __NR_setgid32                  214
-__SYSCALL(__NR_setgid32, sys_setgid)
-#define __NR_setfsuid32                        215
-__SYSCALL(__NR_setfsuid32, sys_setfsuid)
-#define __NR_setfsgid32                        216
-__SYSCALL(__NR_setfsgid32, sys_setfsgid)
-#define __NR_getdents64                        217
-__SYSCALL(__NR_getdents64, sys_getdents64)
-#define __NR_pivot_root                        218
-__SYSCALL(__NR_pivot_root, sys_pivot_root)
-#define __NR_mincore                   219
-__SYSCALL(__NR_mincore, sys_mincore)
-#define __NR_madvise                   220
-__SYSCALL(__NR_madvise, sys_madvise)
-#define __NR_fcntl64                   221
-__SYSCALL(__NR_fcntl64, sys_fcntl64)
-__SYSCALL(222, sys_ni_syscall)         /* 222 for tux */
-__SYSCALL(223, sys_ni_syscall)         /* 223 is unused */
-#define __NR_gettid                    224
-__SYSCALL(__NR_gettid, sys_gettid)
-#define __NR_readahead                 225
-__SYSCALL(__NR_readahead, sys_readahead)
-#define __NR_setxattr                  226
-__SYSCALL(__NR_setxattr, sys_setxattr)
-#define __NR_lsetxattr                 227
-__SYSCALL(__NR_lsetxattr, sys_lsetxattr)
-#define __NR_fsetxattr                 228
-__SYSCALL(__NR_fsetxattr, sys_fsetxattr)
-#define __NR_getxattr                  229
-__SYSCALL(__NR_getxattr, sys_getxattr)
-#define __NR_lgetxattr                 230
-__SYSCALL(__NR_lgetxattr, sys_lgetxattr)
-#define __NR_fgetxattr                 231
-__SYSCALL(__NR_fgetxattr, sys_fgetxattr)
-#define __NR_listxattr                 232
-__SYSCALL(__NR_listxattr, sys_listxattr)
-#define __NR_llistxattr                        233
-__SYSCALL(__NR_llistxattr, sys_llistxattr)
-#define __NR_flistxattr                        234
-__SYSCALL(__NR_flistxattr, sys_flistxattr)
-#define __NR_removexattr               235
-__SYSCALL(__NR_removexattr, sys_removexattr)
-#define __NR_lremovexattr              236
-__SYSCALL(__NR_lremovexattr, sys_lremovexattr)
-#define __NR_fremovexattr              237
-__SYSCALL(__NR_fremovexattr, sys_fremovexattr)
-#define __NR_tkill                     238
-__SYSCALL(__NR_tkill, sys_tkill)
-#define __NR_sendfile64                        239
-__SYSCALL(__NR_sendfile64, sys_sendfile64)
-#define __NR_futex                     240
-__SYSCALL(__NR_futex, sys_futex)
-#define __NR_sched_setaffinity         241
-__SYSCALL(__NR_sched_setaffinity, sys_sched_setaffinity)
-#define __NR_sched_getaffinity         242
-__SYSCALL(__NR_sched_getaffinity, sys_sched_getaffinity)
-#define __NR_io_setup                  243
-__SYSCALL(__NR_io_setup, sys_io_setup)
-#define __NR_io_destroy                        244
-__SYSCALL(__NR_io_destroy, sys_io_destroy)
-#define __NR_io_getevents              245
-__SYSCALL(__NR_io_getevents, sys_io_getevents)
-#define __NR_io_submit                 246
-__SYSCALL(__NR_io_submit, sys_io_submit)
-#define __NR_io_cancel                 247
-__SYSCALL(__NR_io_cancel, sys_io_cancel)
-#define __NR_exit_group                        248
-__SYSCALL(__NR_exit_group, sys_exit_group)
-#define __NR_lookup_dcookie            249
-__SYSCALL(__NR_lookup_dcookie, sys_lookup_dcookie)
-#define __NR_epoll_create              250
-__SYSCALL(__NR_epoll_create, sys_epoll_create)
-#define __NR_epoll_ctl                 251
-__SYSCALL(__NR_epoll_ctl, sys_epoll_ctl)
-#define __NR_epoll_wait                        252
-__SYSCALL(__NR_epoll_wait, sys_epoll_wait)
-#define __NR_remap_file_pages          253
-__SYSCALL(__NR_remap_file_pages, sys_remap_file_pages)
-__SYSCALL(254, sys_ni_syscall)         /* 254 for set_thread_area */
-__SYSCALL(255, sys_ni_syscall)         /* 255 for get_thread_area */
-#define __NR_set_tid_address           256
-__SYSCALL(__NR_set_tid_address, sys_set_tid_address)
-#define __NR_timer_create              257
-__SYSCALL(__NR_timer_create, sys_timer_create)
-#define __NR_timer_settime             258
-__SYSCALL(__NR_timer_settime, sys_timer_settime)
-#define __NR_timer_gettime             259
-__SYSCALL(__NR_timer_gettime, sys_timer_gettime)
-#define __NR_timer_getoverrun          260
-__SYSCALL(__NR_timer_getoverrun, sys_timer_getoverrun)
-#define __NR_timer_delete              261
-__SYSCALL(__NR_timer_delete, sys_timer_delete)
-#define __NR_clock_settime             262
-__SYSCALL(__NR_clock_settime, sys_clock_settime)
-#define __NR_clock_gettime             263
-__SYSCALL(__NR_clock_gettime, sys_clock_gettime)
-#define __NR_clock_getres              264
-__SYSCALL(__NR_clock_getres, sys_clock_getres)
-#define __NR_clock_nanosleep           265
-__SYSCALL(__NR_clock_nanosleep, sys_clock_nanosleep)
-#define __NR_statfs64                  266
-__SYSCALL(__NR_statfs64, sys_statfs64)
-#define __NR_fstatfs64                 267
-__SYSCALL(__NR_fstatfs64, sys_fstatfs64)
-#define __NR_tgkill                    268
-__SYSCALL(__NR_tgkill, sys_tgkill)
-#define __NR_utimes                    269
-__SYSCALL(__NR_utimes, sys_utimes)
-#define __NR_fadvise64                 270
-__SYSCALL(__NR_fadvise64, sys_fadvise64_64)
-#define __NR_pciconfig_iobase          271
-__SYSCALL(__NR_pciconfig_iobase, sys_pciconfig_iobase)
-#define __NR_pciconfig_read            272
-__SYSCALL(__NR_pciconfig_read, sys_pciconfig_read)
-#define __NR_pciconfig_write           273
-__SYSCALL(__NR_pciconfig_write, sys_pciconfig_write)
-#define __NR_mq_open                   274
-__SYSCALL(__NR_mq_open, sys_mq_open)
-#define __NR_mq_unlink                 275
-__SYSCALL(__NR_mq_unlink, sys_mq_unlink)
-#define __NR_mq_timedsend              276
-__SYSCALL(__NR_mq_timedsend, sys_mq_timedsend)
-#define __NR_mq_timedreceive           277
-__SYSCALL(__NR_mq_timedreceive, sys_mq_timedreceive)
-#define __NR_mq_notify                 278
-__SYSCALL(__NR_mq_notify, sys_mq_notify)
-#define __NR_mq_getsetattr             279
-__SYSCALL(__NR_mq_getsetattr, sys_mq_getsetattr)
-#define __NR_waitid                    280
-__SYSCALL(__NR_waitid, sys_waitid)
-#define __NR_socket                    281
-__SYSCALL(__NR_socket, sys_socket)
-#define __NR_bind                      282
-__SYSCALL(__NR_bind, sys_bind)
-#define __NR_connect                   283
-__SYSCALL(__NR_connect, sys_connect)
-#define __NR_listen                    284
-__SYSCALL(__NR_listen, sys_listen)
-#define __NR_accept                    285
-__SYSCALL(__NR_accept, sys_accept)
-#define __NR_getsockname               286
-__SYSCALL(__NR_getsockname, sys_getsockname)
-#define __NR_getpeername               287
-__SYSCALL(__NR_getpeername, sys_getpeername)
-#define __NR_socketpair                        288
-__SYSCALL(__NR_socketpair, sys_socketpair)
-#define __NR_send                      289
-__SYSCALL(__NR_send, sys_send)
-#define __NR_sendto                    290
-__SYSCALL(__NR_sendto, sys_sendto)
-#define __NR_recv                      291
-__SYSCALL(__NR_recv, sys_recv)
-#define __NR_recvfrom                  292
-__SYSCALL(__NR_recvfrom, sys_recvfrom)
-#define __NR_shutdown                  293
-__SYSCALL(__NR_shutdown, sys_shutdown)
-#define __NR_setsockopt                        294
-__SYSCALL(__NR_setsockopt, sys_setsockopt)
-#define __NR_getsockopt                        295
-__SYSCALL(__NR_getsockopt, sys_getsockopt)
-#define __NR_sendmsg                   296
-__SYSCALL(__NR_sendmsg, sys_sendmsg)
-#define __NR_recvmsg                   297
-__SYSCALL(__NR_recvmsg, sys_recvmsg)
-#define __NR_semop                     298
-__SYSCALL(__NR_semop, sys_semop)
-#define __NR_semget                    299
-__SYSCALL(__NR_semget, sys_semget)
-#define __NR_semctl                    300
-__SYSCALL(__NR_semctl, sys_semctl)
-#define __NR_msgsnd                    301
-__SYSCALL(__NR_msgsnd, sys_msgsnd)
-#define __NR_msgrcv                    302
-__SYSCALL(__NR_msgrcv, sys_msgrcv)
-#define __NR_msgget                    303
-__SYSCALL(__NR_msgget, sys_msgget)
-#define __NR_msgctl                    304
-__SYSCALL(__NR_msgctl, sys_msgctl)
-#define __NR_shmat                     305
-__SYSCALL(__NR_shmat, sys_shmat)
-#define __NR_shmdt                     306
-__SYSCALL(__NR_shmdt, sys_shmdt)
-#define __NR_shmget                    307
-__SYSCALL(__NR_shmget, sys_shmget)
-#define __NR_shmctl                    308
-__SYSCALL(__NR_shmctl, sys_shmctl)
-#define __NR_add_key                   309
-__SYSCALL(__NR_add_key, sys_add_key)
-#define __NR_request_key               310
-__SYSCALL(__NR_request_key, sys_request_key)
-#define __NR_keyctl                    311
-__SYSCALL(__NR_keyctl, sys_keyctl)
-#define __NR_semtimedop                        312
-__SYSCALL(__NR_semtimedop, sys_semtimedop)
-#define __NR_vserver                   313
-__SYSCALL(__NR_vserver, sys_ni_syscall)
-#define __NR_ioprio_set                        314
-__SYSCALL(__NR_ioprio_set, sys_ioprio_set)
-#define __NR_ioprio_get                        315
-__SYSCALL(__NR_ioprio_get, sys_ioprio_get)
-#define __NR_inotify_init              316
-__SYSCALL(__NR_inotify_init, sys_inotify_init)
-#define __NR_inotify_add_watch         317
-__SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch)
-#define __NR_inotify_rm_watch          318
-__SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch)
-#define __NR_mbind                     319
-__SYSCALL(__NR_mbind, sys_mbind)
-#define __NR_get_mempolicy             320
-__SYSCALL(__NR_get_mempolicy, sys_get_mempolicy)
-#define __NR_set_mempolicy             321
-__SYSCALL(__NR_set_mempolicy, sys_set_mempolicy)
-#define __NR_openat                    322
-__SYSCALL(__NR_openat, sys_openat)
-#define __NR_mkdirat                   323
-__SYSCALL(__NR_mkdirat, sys_mkdirat)
-#define __NR_mknodat                   324
-__SYSCALL(__NR_mknodat, sys_mknodat)
-#define __NR_fchownat                  325
-__SYSCALL(__NR_fchownat, sys_fchownat)
-#define __NR_futimesat                 326
-__SYSCALL(__NR_futimesat, sys_futimesat)
-#define __NR_fstatat64                 327
-__SYSCALL(__NR_fstatat64, sys_fstatat64)
-#define __NR_unlinkat                  328
-__SYSCALL(__NR_unlinkat, sys_unlinkat)
-#define __NR_renameat                  329
-__SYSCALL(__NR_renameat, sys_renameat)
-#define __NR_linkat                    330
-__SYSCALL(__NR_linkat, sys_linkat)
-#define __NR_symlinkat                 331
-__SYSCALL(__NR_symlinkat, sys_symlinkat)
-#define __NR_readlinkat                        332
-__SYSCALL(__NR_readlinkat, sys_readlinkat)
-#define __NR_fchmodat                  333
-__SYSCALL(__NR_fchmodat, sys_fchmodat)
-#define __NR_faccessat                 334
-__SYSCALL(__NR_faccessat, sys_faccessat)
-#define __NR_pselect6                  335
-__SYSCALL(__NR_pselect6, sys_pselect6)
-#define __NR_ppoll                     336
-__SYSCALL(__NR_ppoll, sys_ppoll)
-#define __NR_unshare                   337
-__SYSCALL(__NR_unshare, sys_unshare)
-#define __NR_set_robust_list           338
-__SYSCALL(__NR_set_robust_list, sys_set_robust_list)
-#define __NR_get_robust_list           339
-__SYSCALL(__NR_get_robust_list, sys_get_robust_list)
-#define __NR_splice                    340
-__SYSCALL(__NR_splice, sys_splice)
-#define __NR_sync_file_range2          341
-__SYSCALL(__NR_sync_file_range2, sys_sync_file_range2)
-#define __NR_tee                       342
-__SYSCALL(__NR_tee, sys_tee)
-#define __NR_vmsplice                  343
-__SYSCALL(__NR_vmsplice, sys_vmsplice)
-#define __NR_move_pages                        344
-__SYSCALL(__NR_move_pages, sys_move_pages)
-#define __NR_getcpu                    345
-__SYSCALL(__NR_getcpu, sys_getcpu)
-#define __NR_epoll_pwait               346
-__SYSCALL(__NR_epoll_pwait, sys_epoll_pwait)
-#define __NR_kexec_load                        347
-__SYSCALL(__NR_kexec_load, sys_kexec_load)
-#define __NR_utimensat                 348
-__SYSCALL(__NR_utimensat, sys_utimensat)
-#define __NR_signalfd                  349
-__SYSCALL(__NR_signalfd, sys_signalfd)
-#define __NR_timerfd_create            350
-__SYSCALL(__NR_timerfd_create, sys_timerfd_create)
-#define __NR_eventfd                   351
-__SYSCALL(__NR_eventfd, sys_eventfd)
-#define __NR_fallocate                 352
-__SYSCALL(__NR_fallocate, sys_fallocate)
-#define __NR_timerfd_settime           353
-__SYSCALL(__NR_timerfd_settime, sys_timerfd_settime)
-#define __NR_timerfd_gettime           354
-__SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime)
-#define __NR_signalfd4                 355
-__SYSCALL(__NR_signalfd4, sys_signalfd4)
-#define __NR_eventfd2                  356
-__SYSCALL(__NR_eventfd2, sys_eventfd2)
-#define __NR_epoll_create1             357
-__SYSCALL(__NR_epoll_create1, sys_epoll_create1)
-#define __NR_dup3                      358
-__SYSCALL(__NR_dup3, sys_dup3)
-#define __NR_pipe2                     359
-__SYSCALL(__NR_pipe2, sys_pipe2)
-#define __NR_inotify_init1             360
-__SYSCALL(__NR_inotify_init1, sys_inotify_init1)
-#define __NR_preadv                    361
-__SYSCALL(__NR_preadv, sys_preadv)
-#define __NR_pwritev                   362
-__SYSCALL(__NR_pwritev, sys_pwritev)
-#define __NR_rt_tgsigqueueinfo         363
-__SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo)
-#define __NR_perf_event_open           364
-__SYSCALL(__NR_perf_event_open, sys_perf_event_open)
-#define __NR_recvmmsg                  365
-__SYSCALL(__NR_recvmmsg, sys_recvmmsg)
-#define __NR_accept4                   366
-__SYSCALL(__NR_accept4, sys_accept4)
-#define __NR_fanotify_init             367
-__SYSCALL(__NR_fanotify_init, sys_fanotify_init)
-#define __NR_fanotify_mark             368
-__SYSCALL(__NR_fanotify_mark, sys_fanotify_mark)
-#define __NR_prlimit64                 369
-__SYSCALL(__NR_prlimit64, sys_prlimit64)
-#define __NR_name_to_handle_at         370
-__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
-#define __NR_open_by_handle_at         371
-__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at)
-#define __NR_clock_adjtime             372
-__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime)
-#define __NR_syncfs                    373
-__SYSCALL(__NR_syncfs, sys_syncfs)
 
 /*
  * The following SVCs are ARM private.
@@ -737,19 +412,3 @@ __SYSCALL(__NR_syncfs, sys_syncfs)
 #define __ARM_NR_COMPAT_BASE           0x0f0000
 #define __ARM_NR_compat_cacheflush     (__ARM_NR_COMPAT_BASE+2)
 #define __ARM_NR_compat_set_tls                (__ARM_NR_COMPAT_BASE+5)
-
-#endif /* __SYSCALL_COMPAT */
-
-#define __NR_compat_syscalls           374
-
-#define __ARCH_WANT_COMPAT_IPC_PARSE_VERSION
-#define __ARCH_WANT_COMPAT_STAT64
-#define __ARCH_WANT_SYS_GETHOSTNAME
-#define __ARCH_WANT_SYS_PAUSE
-#define __ARCH_WANT_SYS_GETPGRP
-#define __ARCH_WANT_SYS_LLSEEK
-#define __ARCH_WANT_SYS_NICE
-#define __ARCH_WANT_SYS_SIGPENDING
-#define __ARCH_WANT_SYS_SIGPROCMASK
-#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
-#define __ARCH_WANT_COMPAT_SYS_SENDFILE
index baebb3da1d44160fc6f6f259886656e6f494b167..ca5b65f75c7bbc9771c8caac282a91d96fc3e619 100644 (file)
@@ -1,3 +1,17 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += auxvec.h
+header-y += bitsperlong.h
+header-y += byteorder.h
+header-y += fcntl.h
+header-y += hwcap.h
+header-y += param.h
+header-y += ptrace.h
+header-y += setup.h
+header-y += sigcontext.h
+header-y += siginfo.h
+header-y += signal.h
+header-y += stat.h
+header-y += statfs.h
+header-y += unistd.h
diff --git a/arch/arm64/include/uapi/asm/hwcap.h b/arch/arm64/include/uapi/asm/hwcap.h
new file mode 100644 (file)
index 0000000..eea4975
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _UAPI__ASM_HWCAP_H
+#define _UAPI__ASM_HWCAP_H
+
+/*
+ * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
+ */
+#define HWCAP_FP               (1 << 0)
+#define HWCAP_ASIMD            (1 << 1)
+
+
+#endif /* _UAPI__ASM_HWCAP_H */
diff --git a/arch/arm64/include/uapi/asm/ptrace.h b/arch/arm64/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..9b131b4
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Based on arch/arm/include/asm/ptrace.h
+ *
+ * Copyright (C) 1996-2003 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _UAPI__ASM_PTRACE_H
+#define _UAPI__ASM_PTRACE_H
+
+#include <linux/types.h>
+
+#include <asm/hwcap.h>
+
+
+/*
+ * PSR bits
+ */
+#define PSR_MODE_EL0t  0x00000000
+#define PSR_MODE_EL1t  0x00000004
+#define PSR_MODE_EL1h  0x00000005
+#define PSR_MODE_EL2t  0x00000008
+#define PSR_MODE_EL2h  0x00000009
+#define PSR_MODE_EL3t  0x0000000c
+#define PSR_MODE_EL3h  0x0000000d
+#define PSR_MODE_MASK  0x0000000f
+
+/* AArch32 CPSR bits */
+#define PSR_MODE32_BIT         0x00000010
+
+/* AArch64 SPSR bits */
+#define PSR_F_BIT      0x00000040
+#define PSR_I_BIT      0x00000080
+#define PSR_A_BIT      0x00000100
+#define PSR_D_BIT      0x00000200
+#define PSR_Q_BIT      0x08000000
+#define PSR_V_BIT      0x10000000
+#define PSR_C_BIT      0x20000000
+#define PSR_Z_BIT      0x40000000
+#define PSR_N_BIT      0x80000000
+
+/*
+ * Groups of PSR bits
+ */
+#define PSR_f          0xff000000      /* Flags                */
+#define PSR_s          0x00ff0000      /* Status               */
+#define PSR_x          0x0000ff00      /* Extension            */
+#define PSR_c          0x000000ff      /* Control              */
+
+
+#ifndef __ASSEMBLY__
+
+/*
+ * User structures for general purpose, floating point and debug registers.
+ */
+struct user_pt_regs {
+       __u64           regs[31];
+       __u64           sp;
+       __u64           pc;
+       __u64           pstate;
+};
+
+struct user_fpsimd_state {
+       __uint128_t     vregs[32];
+       __u32           fpsr;
+       __u32           fpcr;
+};
+
+struct user_hwdebug_state {
+       __u32           dbg_info;
+       struct {
+               __u64   addr;
+               __u32   ctrl;
+       }               dbg_regs[16];
+};
+
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _UAPI__ASM_PTRACE_H */
diff --git a/arch/arm64/include/uapi/asm/sigcontext.h b/arch/arm64/include/uapi/asm/sigcontext.h
new file mode 100644 (file)
index 0000000..690ad51
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _UAPI__ASM_SIGCONTEXT_H
+#define _UAPI__ASM_SIGCONTEXT_H
+
+#include <linux/types.h>
+
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked.
+ */
+struct sigcontext {
+       __u64 fault_address;
+       /* AArch64 registers */
+       __u64 regs[31];
+       __u64 sp;
+       __u64 pc;
+       __u64 pstate;
+       /* 4K reserved for FP/SIMD state and future expansion */
+       __u8 __reserved[4096] __attribute__((__aligned__(16)));
+};
+
+/*
+ * Header to be used at the beginning of structures extending the user
+ * context. Such structures must be placed after the rt_sigframe on the stack
+ * and be 16-byte aligned. The last structure must be a dummy one with the
+ * magic and size set to 0.
+ */
+struct _aarch64_ctx {
+       __u32 magic;
+       __u32 size;
+};
+
+#define FPSIMD_MAGIC   0x46508001
+
+struct fpsimd_context {
+       struct _aarch64_ctx head;
+       __u32 fpsr;
+       __u32 fpcr;
+       __uint128_t vregs[32];
+};
+
+
+#endif /* _UAPI__ASM_SIGCONTEXT_H */
diff --git a/arch/arm64/include/uapi/asm/stat.h b/arch/arm64/include/uapi/asm/stat.h
new file mode 100644 (file)
index 0000000..eeb702e
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <asm-generic/stat.h>
diff --git a/arch/arm64/include/uapi/asm/unistd.h b/arch/arm64/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..1caadc2
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <asm-generic/unistd.h>
index 6538928ff1ab7bd494df8687645ed323325ecbc3..a6f3f7da6880bbcfc8ef307206421cf85540d7da 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/errno.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
+#include <asm/unistd32.h>
 
 /*
  * Bad Abort numbers
index ac3550ecc7b5c1f15c09bd3a20be8f5b459570bb..2ea3968367c265f99830db7f365668919f5f6a7c 100644 (file)
@@ -823,11 +823,11 @@ static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
        if (off & 3)
                return -EIO;
 
-       if (off == PT_TEXT_ADDR)
+       if (off == COMPAT_PT_TEXT_ADDR)
                tmp = tsk->mm->start_code;
-       else if (off == PT_DATA_ADDR)
+       else if (off == COMPAT_PT_DATA_ADDR)
                tmp = tsk->mm->start_data;
-       else if (off == PT_TEXT_END_ADDR)
+       else if (off == COMPAT_PT_TEXT_END_ADDR)
                tmp = tsk->mm->end_code;
        else if (off < sizeof(compat_elf_gregset_t))
                return copy_regset_to_user(tsk, &user_aarch32_view,
index 0790a87a4346eb3b0d1825dcdfb599d828243b78..4654824747a4c99d2c6ee831adaf99cf86298464 100644 (file)
@@ -18,8 +18,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#define __SYSCALL_COMPAT
-
 #include <linux/compat.h>
 #include <linux/signal.h>
 #include <linux/syscalls.h>
@@ -28,7 +26,7 @@
 #include <asm/fpsimd.h>
 #include <asm/signal32.h>
 #include <asm/uaccess.h>
-#include <asm/unistd.h>
+#include <asm/unistd32.h>
 
 struct compat_sigaction {
        compat_uptr_t                   sa_handler;
@@ -126,19 +124,19 @@ struct compat_rt_sigframe {
  * For ARM syscalls, the syscall number has to be loaded into r7.
  * We do not support an OABI userspace.
  */
-#define MOV_R7_NR_SIGRETURN    (0xe3a07000 | __NR_sigreturn)
-#define SVC_SYS_SIGRETURN      (0xef000000 | __NR_sigreturn)
-#define MOV_R7_NR_RT_SIGRETURN (0xe3a07000 | __NR_rt_sigreturn)
-#define SVC_SYS_RT_SIGRETURN   (0xef000000 | __NR_rt_sigreturn)
+#define MOV_R7_NR_SIGRETURN    (0xe3a07000 | __NR_compat_sigreturn)
+#define SVC_SYS_SIGRETURN      (0xef000000 | __NR_compat_sigreturn)
+#define MOV_R7_NR_RT_SIGRETURN (0xe3a07000 | __NR_compat_rt_sigreturn)
+#define SVC_SYS_RT_SIGRETURN   (0xef000000 | __NR_compat_rt_sigreturn)
 
 /*
  * For Thumb syscalls, we also pass the syscall number via r7. We therefore
  * need two 16-bit instructions.
  */
-#define SVC_THUMB_SIGRETURN    (((0xdf00 | __NR_sigreturn) << 16) | \
-                                  0x2700 | __NR_sigreturn)
-#define SVC_THUMB_RT_SIGRETURN (((0xdf00 | __NR_rt_sigreturn) << 16) | \
-                                  0x2700 | __NR_rt_sigreturn)
+#define SVC_THUMB_SIGRETURN    (((0xdf00 | __NR_compat_sigreturn) << 16) | \
+                                  0x2700 | __NR_compat_sigreturn)
+#define SVC_THUMB_RT_SIGRETURN (((0xdf00 | __NR_compat_rt_sigreturn) << 16) | \
+                                  0x2700 | __NR_compat_rt_sigreturn)
 
 const compat_ulong_t aarch32_sigret_code[6] = {
        /*
@@ -819,5 +817,5 @@ asmlinkage int compat_sys_rt_sigqueueinfo(int pid, int sig,
 
 void compat_setup_restart_syscall(struct pt_regs *regs)
 {
-       regs->regs[7] = __NR_restart_syscall;
+       regs->regs[7] = __NR_compat_restart_syscall;
 }
index 905fcfb0ddd0b284b42237e82da9041e3050cee3..b120df37de3552e5a68479294ef9e6b037ea97fb 100644 (file)
@@ -50,13 +50,13 @@ asmlinkage long sys_execve(const char __user *filenamei,
                           struct pt_regs *regs)
 {
        long error;
-       char * filename;
+       struct filename *filename;
 
        filename = getname(filenamei);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
 out:
        return error;
index 5e4dc93cc31fd19c36d2c073c5bc59aff4f1b716..54c4aec47a088f9d32382980011b3cab6336fb80 100644 (file)
@@ -147,136 +147,12 @@ compat_sys_fanotify_mark_wrapper:
        b       sys_fanotify_mark
 ENDPROC(compat_sys_fanotify_mark_wrapper)
 
-/*
- * Use the compat system call wrappers.
- */
-#define sys_fork               compat_sys_fork_wrapper
-#define sys_open               compat_sys_open
-#define sys_execve             compat_sys_execve_wrapper
-#define sys_lseek              compat_sys_lseek_wrapper
-#define sys_mount              compat_sys_mount
-#define sys_ptrace             compat_sys_ptrace
-#define sys_times              compat_sys_times
-#define sys_ioctl              compat_sys_ioctl
-#define sys_fcntl              compat_sys_fcntl
-#define sys_ustat              compat_sys_ustat
-#define sys_sigaction          compat_sys_sigaction
-#define sys_sigsuspend         compat_sys_sigsuspend
-#define sys_sigpending         compat_sys_sigpending
-#define sys_setrlimit          compat_sys_setrlimit
-#define sys_getrusage          compat_sys_getrusage
-#define sys_gettimeofday       compat_sys_gettimeofday
-#define sys_settimeofday       compat_sys_settimeofday
-#define sys_statfs             compat_sys_statfs
-#define sys_fstatfs            compat_sys_fstatfs
-#define sys_setitimer          compat_sys_setitimer
-#define sys_getitimer          compat_sys_getitimer
-#define sys_newstat            compat_sys_newstat
-#define sys_newlstat           compat_sys_newlstat
-#define sys_newfstat           compat_sys_newfstat
-#define sys_wait4              compat_sys_wait4
-#define sys_sysinfo            compat_sys_sysinfo
-#define sys_sigreturn          compat_sys_sigreturn_wrapper
-#define sys_clone              compat_sys_clone_wrapper
-#define sys_adjtimex           compat_sys_adjtimex
-#define sys_sigprocmask                compat_sys_sigprocmask
-#define sys_getdents           compat_sys_getdents
-#define sys_select             compat_sys_select
-#define sys_readv              compat_sys_readv
-#define sys_writev             compat_sys_writev
-#define sys_sysctl             compat_sys_sysctl
-#define sys_sched_rr_get_interval compat_sys_sched_rr_get_interval
-#define sys_nanosleep          compat_sys_nanosleep
-#define sys_rt_sigreturn       compat_sys_rt_sigreturn_wrapper
-#define sys_rt_sigaction       compat_sys_rt_sigaction
-#define sys_rt_sigprocmask     compat_sys_rt_sigprocmask
-#define sys_rt_sigpending      compat_sys_rt_sigpending
-#define sys_rt_sigtimedwait    compat_sys_rt_sigtimedwait
-#define sys_rt_sigqueueinfo    compat_sys_rt_sigqueueinfo
-#define sys_rt_sigsuspend      compat_sys_rt_sigsuspend
-#define sys_pread64            compat_sys_pread64_wrapper
-#define sys_pwrite64           compat_sys_pwrite64_wrapper
-#define sys_sigaltstack                compat_sys_sigaltstack_wrapper
-#define sys_sendfile           compat_sys_sendfile
-#define sys_vfork              compat_sys_vfork_wrapper
-#define sys_getrlimit          compat_sys_getrlimit
-#define sys_mmap2              sys_mmap_pgoff
-#define sys_truncate64         compat_sys_truncate64_wrapper
-#define sys_ftruncate64                compat_sys_ftruncate64_wrapper
-#define sys_getdents64         compat_sys_getdents64
-#define sys_fcntl64            compat_sys_fcntl64
-#define sys_readahead          compat_sys_readahead_wrapper
-#define sys_futex              compat_sys_futex
-#define sys_sched_setaffinity  compat_sys_sched_setaffinity
-#define sys_sched_getaffinity  compat_sys_sched_getaffinity
-#define sys_io_setup           compat_sys_io_setup
-#define sys_io_getevents       compat_sys_io_getevents
-#define sys_io_submit          compat_sys_io_submit
-#define sys_lookup_dcookie     compat_sys_lookup_dcookie
-#define sys_timer_create       compat_sys_timer_create
-#define sys_timer_settime      compat_sys_timer_settime
-#define sys_timer_gettime      compat_sys_timer_gettime
-#define sys_clock_settime      compat_sys_clock_settime
-#define sys_clock_gettime      compat_sys_clock_gettime
-#define sys_clock_getres       compat_sys_clock_getres
-#define sys_clock_nanosleep    compat_sys_clock_nanosleep
-#define sys_statfs64           compat_sys_statfs64_wrapper
-#define sys_fstatfs64          compat_sys_fstatfs64_wrapper
-#define sys_utimes             compat_sys_utimes
-#define sys_fadvise64_64       compat_sys_fadvise64_64_wrapper
-#define sys_mq_open            compat_sys_mq_open
-#define sys_mq_timedsend       compat_sys_mq_timedsend
-#define sys_mq_timedreceive    compat_sys_mq_timedreceive
-#define sys_mq_notify          compat_sys_mq_notify
-#define sys_mq_getsetattr      compat_sys_mq_getsetattr
-#define sys_waitid             compat_sys_waitid
-#define sys_recv               compat_sys_recv
-#define sys_recvfrom           compat_sys_recvfrom
-#define sys_setsockopt         compat_sys_setsockopt
-#define sys_getsockopt         compat_sys_getsockopt
-#define sys_sendmsg            compat_sys_sendmsg
-#define sys_recvmsg            compat_sys_recvmsg
-#define sys_semctl             compat_sys_semctl
-#define sys_msgsnd             compat_sys_msgsnd
-#define sys_msgrcv             compat_sys_msgrcv
-#define sys_msgctl             compat_sys_msgctl
-#define sys_shmat              compat_sys_shmat
-#define sys_shmctl             compat_sys_shmctl
-#define sys_keyctl             compat_sys_keyctl
-#define sys_semtimedop         compat_sys_semtimedop
-#define sys_mbind              compat_sys_mbind
-#define sys_get_mempolicy      compat_sys_get_mempolicy
-#define sys_set_mempolicy      compat_sys_set_mempolicy
-#define sys_openat             compat_sys_openat
-#define sys_futimesat          compat_sys_futimesat
-#define sys_pselect6           compat_sys_pselect6
-#define sys_ppoll              compat_sys_ppoll
-#define sys_set_robust_list    compat_sys_set_robust_list
-#define sys_get_robust_list    compat_sys_get_robust_list
-#define sys_sync_file_range2   compat_sys_sync_file_range2_wrapper
-#define sys_vmsplice           compat_sys_vmsplice
-#define sys_move_pages         compat_sys_move_pages
-#define sys_epoll_pwait                compat_sys_epoll_pwait
-#define sys_kexec_load         compat_sys_kexec_load
-#define sys_utimensat          compat_sys_utimensat
-#define sys_signalfd           compat_sys_signalfd
-#define sys_fallocate          compat_sys_fallocate_wrapper
-#define sys_timerfd_settime    compat_sys_timerfd_settime
-#define sys_timerfd_gettime    compat_sys_timerfd_gettime
-#define sys_signalfd4          compat_sys_signalfd4
-#define sys_preadv             compat_sys_preadv
-#define sys_pwritev            compat_sys_pwritev
-#define sys_rt_tgsigqueueinfo  compat_sys_rt_tgsigqueueinfo
-#define sys_recvmmsg           compat_sys_recvmmsg
-#define sys_fanotify_mark      compat_sys_fanotify_mark_wrapper
-
 #undef __SYSCALL
 #define __SYSCALL(x, y)                .quad   y       // x
-#define __SYSCALL_COMPAT
 
 /*
  * The system calls table must be 4KB aligned.
  */
        .align  12
 ENTRY(compat_sys_call_table)
-#include <asm/unistd.h>
+#include <asm/unistd32.h>
index 93f10e27dc796764d50d6c4d18b7310cd36cbeb5..906e3bd270b06de91bbab8505df7877ca0300922 100644 (file)
@@ -18,8 +18,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#define __SYSCALL_COMPAT
-
 #include <linux/compat.h>
 #include <linux/personality.h>
 #include <linux/sched.h>
@@ -28,7 +26,7 @@
 #include <linux/uaccess.h>
 
 #include <asm/cacheflush.h>
-#include <asm/unistd.h>
+#include <asm/unistd32.h>
 
 asmlinkage int compat_sys_fork(struct pt_regs *regs)
 {
@@ -56,14 +54,14 @@ asmlinkage int compat_sys_execve(const char __user *filenamei,
                                 struct pt_regs *regs)
 {
        int error;
-       char * filename;
+       struct filename *filename;
 
        filename = getname(filenamei);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = compat_do_execve(filename, compat_ptr(argv), compat_ptr(envp),
-                                regs);
+       error = compat_do_execve(filename->name, compat_ptr(argv),
+                                       compat_ptr(envp), regs);
        putname(filename);
 out:
        return error;
index e3ba7bca06fae732929e28a4b00be0374883de17..be0433ee5a8ec79c86a1d049cca58a6890df3230 100644 (file)
@@ -1,5 +1,6 @@
 include include/asm-generic/Kbuild.asm
 
 generic-y      += clkdev.h
+generic-y      += exec.h
 
 header-y       += cachectl.h
diff --git a/arch/avr32/include/asm/exec.h b/arch/avr32/include/asm/exec.h
deleted file mode 100644 (file)
index f467be8..0000000
+++ /dev/null
@@ -1,13 +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_EXEC_H
-#define __ASM_AVR32_EXEC_H
-
-#define arch_align_stack(x)    (x)
-
-#endif /* __ASM_AVR32_EXEC_H */
index e5deda4691db248781f0d127ca4b383cea4b794d..6dc62e1f94c7801532c9a3bc0be13abe3f8009e4 100644 (file)
@@ -77,8 +77,6 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_TRACE       0       /* syscall trace active */
 #define TIF_SIGPENDING          1       /* signal pending */
 #define TIF_NEED_RESCHED        2       /* rescheduling necessary */
-#define TIF_POLLING_NRFLAG      3       /* true if poll_idle() is polling
-                                          TIF_NEED_RESCHED */
 #define TIF_BREAKPOINT         4       /* enter monitor mode on return */
 #define TIF_SINGLE_STEP                5       /* single step in progress */
 #define TIF_MEMDIE             6       /* is terminating due to OOM killer */
@@ -91,10 +89,9 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
+#define _TIF_BREAKPOINT                (1 << TIF_BREAKPOINT)
 #define _TIF_SINGLE_STEP       (1 << TIF_SINGLE_STEP)
 #define _TIF_MEMDIE            (1 << TIF_MEMDIE)
-#define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
 #define _TIF_CPU_GOING_TO_SLEEP (1 << TIF_CPU_GOING_TO_SLEEP)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
 
@@ -102,17 +99,14 @@ static inline struct thread_info *current_thread_info(void)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK                         \
-       ((1 << TIF_SIGPENDING)                  \
+       (_TIF_SIGPENDING                        \
         | _TIF_NOTIFY_RESUME                   \
-        | (1 << TIF_NEED_RESCHED)              \
-        | (1 << TIF_POLLING_NRFLAG)            \
-        | (1 << TIF_BREAKPOINT)                \
-        | (1 << TIF_RESTORE_SIGMASK))
+        | _TIF_NEED_RESCHED                    \
+        | _TIF_BREAKPOINT)
 
 /* work to do on any return to userspace */
-#define _TIF_ALLWORK_MASK      (_TIF_WORK_MASK | (1 << TIF_SYSCALL_TRACE) | \
-                                _TIF_NOTIFY_RESUME)
+#define _TIF_ALLWORK_MASK      (_TIF_WORK_MASK | _TIF_SYSCALL_TRACE)
 /* work to do on return from debug mode */
-#define _TIF_DBGWORK_MASK      (_TIF_WORK_MASK & ~(1 << TIF_BREAKPOINT))
+#define _TIF_DBGWORK_MASK      (_TIF_WORK_MASK & ~_TIF_BREAKPOINT)
 
 #endif /* __ASM_AVR32_THREAD_INFO_H */
index 92c5af98a6f76be5f762b2e8c05936ddde5dfdc4..1bb0a8abd79b5078267ad4e6c9c84832033d0e92 100644 (file)
@@ -388,14 +388,14 @@ asmlinkage int sys_execve(const char __user *ufilename,
                          struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(ufilename);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename, uargv, uenvp, regs);
+       error = do_execve(filename->name, uargv, uenvp, regs);
        putname(filename);
 
 out:
index d552a854dacccbbc8b5f8131bbdaa2203ffb74fa..5e01c3a40cedfbbd607ce6d23a8477e9bd9da470 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
-#include <linux/freezer.h>
 #include <linux/tracehook.h>
 
 #include <asm/uaccess.h>
index 0445c4fd67e311e864cf6f9d8e70f4ef3bb530f6..b323d8d3185b35b91a21da1857bcd340d935449c 100644 (file)
@@ -605,6 +605,9 @@ static void __init genclk_init_parent(struct clk *clk)
 
 static struct dw_dma_platform_data dw_dmac0_data = {
        .nr_channels    = 3,
+       .block_size     = 4095U,
+       .nr_masters     = 2,
+       .data_width     = { 2, 2, 0, 0 },
 };
 
 static struct resource dw_dmac0_resource[] = {
index 0fdc4ecaa5317a4de2f1850251c3d618db03a96e..91988370b75e03b9603abdd7939faed63f496220 100644 (file)
@@ -57,7 +57,6 @@ CONFIG_MTD_PLATRAM=y
 CONFIG_MTD_PHRAM=y
 CONFIG_MTD_BLOCK2MTD=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_PLATFORM=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
index 53ad10005ae37db4fbf6c3d6cb21eee6485b8db6..3894005337ba7d8628de4f7de2f9f7dd8f5b603d 100644 (file)
@@ -96,8 +96,6 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_TRACE      0       /* syscall trace active */
 #define TIF_SIGPENDING         1       /* signal pending */
 #define TIF_NEED_RESCHED       2       /* rescheduling necessary */
-#define TIF_POLLING_NRFLAG     3       /* true if poll_idle() is polling
-                                          TIF_NEED_RESCHED */
 #define TIF_MEMDIE             4       /* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK    5       /* restore signal mask in do_signal() */
 #define TIF_IRQ_SYNC           7       /* sync pipeline stage */
@@ -108,8 +106,6 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
-#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_IRQ_SYNC          (1<<TIF_IRQ_SYNC)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_SINGLESTEP                (1<<TIF_SINGLESTEP)
index 62bcea7dcc6dff30bdaa5a4793ab336aef5ed688..bb1cc721fcf7e18ee26b5bf7a7bc0b2912815ad6 100644 (file)
@@ -213,14 +213,14 @@ asmlinkage int sys_execve(const char __user *name,
                          const char __user *const __user *envp)
 {
        int error;
-       char *filename;
+       struct filename *filename;
        struct pt_regs *regs = (struct pt_regs *)((&name) + 6);
 
        filename = getname(name);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                return error;
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
        return error;
 }
index 6682b73a8523f789bf2e3fa722f068f1ef4ebf79..6ed20a1a4af9619951e560f2de692b15b6f850ba 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/tty.h>
 #include <linux/personality.h>
 #include <linux/binfmts.h>
-#include <linux/freezer.h>
 #include <linux/uaccess.h>
 #include <linux/tracehook.h>
 
index 983c859e40b7b57e5eb1da68094524b7fe1c1301..45268b50c0c88907e09a738a3d60f55c4ac2afe5 100644 (file)
@@ -17,6 +17,7 @@ config C6X
        select OF
        select OF_EARLY_FLATTREE
        select GENERIC_CLOCKEVENTS
+       select GENERIC_KERNEL_THREAD
 
 config MMU
        def_bool n
index 277f1a4ecb0954ca63c5c64e1314973d0a9dddd3..112a496d835589b27d3685cb1bf48768688a65a9 100644 (file)
@@ -1,4 +1,3 @@
-include include/asm-generic/Kbuild.asm
 
 generic-y += atomic.h
 generic-y += auxvec.h
@@ -12,6 +11,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 += futex.h
diff --git a/arch/c6x/include/asm/exec.h b/arch/c6x/include/asm/exec.h
deleted file mode 100644 (file)
index 0fea482..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_C6X_EXEC_H
-#define _ASM_C6X_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* _ASM_C6X_EXEC_H */
index c50af7ef1c96a5538252474e6ab37681141583a5..b9eb3da7f278dac858bfb2191094f9fc837ac5c8 100644 (file)
@@ -92,8 +92,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 #define copy_segments(tsk, mm)         do { } while (0)
 #define release_segments(mm)           do { } while (0)
 
index b04ff5964258bea32365c1edc15157a8aa04174f..76da6ad6610822eafd5546430f97c62b1ecca206 100644 (file)
 #ifndef _ASM_C6X_PTRACE_H
 #define _ASM_C6X_PTRACE_H
 
-#define BKPT_OPCODE    0x56454314      /* illegal opcode */
-
-#ifdef _BIG_ENDIAN
-#define PT_LO(odd, even)  odd
-#define PT_HI(odd, even)  even
-#else
-#define PT_LO(odd, even)  even
-#define PT_HI(odd, even)  odd
-#endif
-
-#define PT_A4_ORG  PT_LO(1, 0)
-#define PT_TSR    PT_HI(1, 0)
-#define PT_ILC    PT_LO(3, 2)
-#define PT_RILC    PT_HI(3, 2)
-#define PT_CSR    PT_LO(5, 4)
-#define PT_PC     PT_HI(5, 4)
-#define PT_B16    PT_LO(7, 6)
-#define PT_B17    PT_HI(7, 6)
-#define PT_B18    PT_LO(9, 8)
-#define PT_B19    PT_HI(9, 8)
-#define PT_B20    PT_LO(11, 10)
-#define PT_B21    PT_HI(11, 10)
-#define PT_B22    PT_LO(13, 12)
-#define PT_B23    PT_HI(13, 12)
-#define PT_B24    PT_LO(15, 14)
-#define PT_B25    PT_HI(15, 14)
-#define PT_B26    PT_LO(17, 16)
-#define PT_B27    PT_HI(17, 16)
-#define PT_B28    PT_LO(19, 18)
-#define PT_B29    PT_HI(19, 18)
-#define PT_B30    PT_LO(21, 20)
-#define PT_B31    PT_HI(21, 20)
-#define PT_B0     PT_LO(23, 22)
-#define PT_B1     PT_HI(23, 22)
-#define PT_B2     PT_LO(25, 24)
-#define PT_B3     PT_HI(25, 24)
-#define PT_B4     PT_LO(27, 26)
-#define PT_B5     PT_HI(27, 26)
-#define PT_B6     PT_LO(29, 28)
-#define PT_B7     PT_HI(29, 28)
-#define PT_B8     PT_LO(31, 30)
-#define PT_B9     PT_HI(31, 30)
-#define PT_B10    PT_LO(33, 32)
-#define PT_B11    PT_HI(33, 32)
-#define PT_B12    PT_LO(35, 34)
-#define PT_B13    PT_HI(35, 34)
-#define PT_A16    PT_LO(37, 36)
-#define PT_A17    PT_HI(37, 36)
-#define PT_A18    PT_LO(39, 38)
-#define PT_A19    PT_HI(39, 38)
-#define PT_A20    PT_LO(41, 40)
-#define PT_A21    PT_HI(41, 40)
-#define PT_A22    PT_LO(43, 42)
-#define PT_A23    PT_HI(43, 42)
-#define PT_A24    PT_LO(45, 44)
-#define PT_A25    PT_HI(45, 44)
-#define PT_A26    PT_LO(47, 46)
-#define PT_A27    PT_HI(47, 46)
-#define PT_A28    PT_LO(49, 48)
-#define PT_A29    PT_HI(49, 48)
-#define PT_A30    PT_LO(51, 50)
-#define PT_A31    PT_HI(51, 50)
-#define PT_A0     PT_LO(53, 52)
-#define PT_A1     PT_HI(53, 52)
-#define PT_A2     PT_LO(55, 54)
-#define PT_A3     PT_HI(55, 54)
-#define PT_A4     PT_LO(57, 56)
-#define PT_A5     PT_HI(57, 56)
-#define PT_A6     PT_LO(59, 58)
-#define PT_A7     PT_HI(59, 58)
-#define PT_A8     PT_LO(61, 60)
-#define PT_A9     PT_HI(61, 60)
-#define PT_A10    PT_LO(63, 62)
-#define PT_A11    PT_HI(63, 62)
-#define PT_A12    PT_LO(65, 64)
-#define PT_A13    PT_HI(65, 64)
-#define PT_A14    PT_LO(67, 66)
-#define PT_A15    PT_HI(67, 66)
-#define PT_B14    PT_LO(69, 68)
-#define PT_B15    PT_HI(69, 68)
-
-#define NR_PTREGS  70
-
-#define PT_DP     PT_B14  /* Data Segment Pointer (B14) */
-#define PT_SP     PT_B15  /* Stack Pointer (B15)  */
-
-#define PTRACE_GETFDPIC                31      /* get the ELF fdpic loadmap address */
-
-#define PTRACE_GETFDPIC_EXEC   0       /* [addr] request the executable loadmap */
-#define PTRACE_GETFDPIC_INTERP 1       /* [addr] request the interpreter loadmap */
+#include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
-
 #ifdef _BIG_ENDIAN
-#define REG_PAIR(odd, even) unsigned long odd; unsigned long even
 #else
-#define REG_PAIR(odd, even) unsigned long even; unsigned long odd
 #endif
 
-/*
- * this struct defines the way the registers are stored on the
- * stack during a system call. fields defined with REG_PAIR
- * are saved and restored using double-word memory operations
- * which means the word ordering of the pair depends on endianess.
- */
-struct pt_regs {
-       REG_PAIR(tsr, orig_a4);
-       REG_PAIR(rilc, ilc);
-       REG_PAIR(pc, csr);
-
-       REG_PAIR(b17, b16);
-       REG_PAIR(b19, b18);
-       REG_PAIR(b21, b20);
-       REG_PAIR(b23, b22);
-       REG_PAIR(b25, b24);
-       REG_PAIR(b27, b26);
-       REG_PAIR(b29, b28);
-       REG_PAIR(b31, b30);
-
-       REG_PAIR(b1, b0);
-       REG_PAIR(b3, b2);
-       REG_PAIR(b5, b4);
-       REG_PAIR(b7, b6);
-       REG_PAIR(b9, b8);
-       REG_PAIR(b11, b10);
-       REG_PAIR(b13, b12);
-
-       REG_PAIR(a17, a16);
-       REG_PAIR(a19, a18);
-       REG_PAIR(a21, a20);
-       REG_PAIR(a23, a22);
-       REG_PAIR(a25, a24);
-       REG_PAIR(a27, a26);
-       REG_PAIR(a29, a28);
-       REG_PAIR(a31, a30);
-
-       REG_PAIR(a1, a0);
-       REG_PAIR(a3, a2);
-       REG_PAIR(a5, a4);
-       REG_PAIR(a7, a6);
-       REG_PAIR(a9, a8);
-       REG_PAIR(a11, a10);
-       REG_PAIR(a13, a12);
-
-       REG_PAIR(a15, a14);
-       REG_PAIR(sp, dp);
-};
-
-#ifdef __KERNEL__
-
 #include <linux/linkage.h>
 
 #define user_mode(regs)        ((((regs)->tsr) & 0x40) != 0)
@@ -174,6 +31,5 @@ extern void show_regs(struct pt_regs *);
 extern asmlinkage unsigned long syscall_trace_entry(struct pt_regs *regs);
 extern asmlinkage void syscall_trace_exit(struct pt_regs *regs);
 
-#endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_C6X_PTRACE_H */
index aed53da703c9ae7bb3b78e1b2d285fefd4ecaa0d..e7b8991dc07c69c25425fce66c16306dcede12d1 100644 (file)
@@ -44,11 +44,6 @@ extern int sys_cache_sync(unsigned long s, unsigned long e);
 struct pt_regs;
 
 extern asmlinkage long sys_c6x_clone(struct pt_regs *regs);
-extern asmlinkage long sys_c6x_execve(const char __user *name,
-                                     const char __user *const __user *argv,
-                                     const char __user *const __user *envp,
-                                     struct pt_regs *regs);
-
 
 #include <asm-generic/syscalls.h>
 
index 1710bcbb8d093bda2965d4d7e3c779963eeb6f7f..4c8dc562bd90dce27d0236140434a34120fe33d7 100644 (file)
@@ -97,7 +97,6 @@ struct thread_info *current_thread_info(void)
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_RESTORE_SIGMASK    4       /* restore signal mask in do_signal() */
 
-#define TIF_POLLING_NRFLAG     16      /* true if polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE             17      /* OOM killer killed process */
 
 #define TIF_WORK_MASK          0x00007FFE /* work on irq/exception return */
index baebb3da1d44160fc6f6f259886656e6f494b167..c312b424c4331b58aed335e43a3044e6088fce2c 100644 (file)
@@ -1,3 +1,10 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += byteorder.h
+header-y += kvm_para.h
+header-y += ptrace.h
+header-y += setup.h
+header-y += sigcontext.h
+header-y += swab.h
+header-y += unistd.h
diff --git a/arch/c6x/include/uapi/asm/ptrace.h b/arch/c6x/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..cc0a4d9
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ *  Copyright (C) 2004, 2006, 2009, 2010 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
+ *
+ *  Updated for 2.6.34: Mark Salter <msalter@redhat.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 _UAPI_ASM_C6X_PTRACE_H
+#define _UAPI_ASM_C6X_PTRACE_H
+
+#define BKPT_OPCODE    0x56454314      /* illegal opcode */
+
+#ifdef _BIG_ENDIAN
+#define PT_LO(odd, even)  odd
+#define PT_HI(odd, even)  even
+#else
+#define PT_LO(odd, even)  even
+#define PT_HI(odd, even)  odd
+#endif
+
+#define PT_A4_ORG  PT_LO(1, 0)
+#define PT_TSR    PT_HI(1, 0)
+#define PT_ILC    PT_LO(3, 2)
+#define PT_RILC    PT_HI(3, 2)
+#define PT_CSR    PT_LO(5, 4)
+#define PT_PC     PT_HI(5, 4)
+#define PT_B16    PT_LO(7, 6)
+#define PT_B17    PT_HI(7, 6)
+#define PT_B18    PT_LO(9, 8)
+#define PT_B19    PT_HI(9, 8)
+#define PT_B20    PT_LO(11, 10)
+#define PT_B21    PT_HI(11, 10)
+#define PT_B22    PT_LO(13, 12)
+#define PT_B23    PT_HI(13, 12)
+#define PT_B24    PT_LO(15, 14)
+#define PT_B25    PT_HI(15, 14)
+#define PT_B26    PT_LO(17, 16)
+#define PT_B27    PT_HI(17, 16)
+#define PT_B28    PT_LO(19, 18)
+#define PT_B29    PT_HI(19, 18)
+#define PT_B30    PT_LO(21, 20)
+#define PT_B31    PT_HI(21, 20)
+#define PT_B0     PT_LO(23, 22)
+#define PT_B1     PT_HI(23, 22)
+#define PT_B2     PT_LO(25, 24)
+#define PT_B3     PT_HI(25, 24)
+#define PT_B4     PT_LO(27, 26)
+#define PT_B5     PT_HI(27, 26)
+#define PT_B6     PT_LO(29, 28)
+#define PT_B7     PT_HI(29, 28)
+#define PT_B8     PT_LO(31, 30)
+#define PT_B9     PT_HI(31, 30)
+#define PT_B10    PT_LO(33, 32)
+#define PT_B11    PT_HI(33, 32)
+#define PT_B12    PT_LO(35, 34)
+#define PT_B13    PT_HI(35, 34)
+#define PT_A16    PT_LO(37, 36)
+#define PT_A17    PT_HI(37, 36)
+#define PT_A18    PT_LO(39, 38)
+#define PT_A19    PT_HI(39, 38)
+#define PT_A20    PT_LO(41, 40)
+#define PT_A21    PT_HI(41, 40)
+#define PT_A22    PT_LO(43, 42)
+#define PT_A23    PT_HI(43, 42)
+#define PT_A24    PT_LO(45, 44)
+#define PT_A25    PT_HI(45, 44)
+#define PT_A26    PT_LO(47, 46)
+#define PT_A27    PT_HI(47, 46)
+#define PT_A28    PT_LO(49, 48)
+#define PT_A29    PT_HI(49, 48)
+#define PT_A30    PT_LO(51, 50)
+#define PT_A31    PT_HI(51, 50)
+#define PT_A0     PT_LO(53, 52)
+#define PT_A1     PT_HI(53, 52)
+#define PT_A2     PT_LO(55, 54)
+#define PT_A3     PT_HI(55, 54)
+#define PT_A4     PT_LO(57, 56)
+#define PT_A5     PT_HI(57, 56)
+#define PT_A6     PT_LO(59, 58)
+#define PT_A7     PT_HI(59, 58)
+#define PT_A8     PT_LO(61, 60)
+#define PT_A9     PT_HI(61, 60)
+#define PT_A10    PT_LO(63, 62)
+#define PT_A11    PT_HI(63, 62)
+#define PT_A12    PT_LO(65, 64)
+#define PT_A13    PT_HI(65, 64)
+#define PT_A14    PT_LO(67, 66)
+#define PT_A15    PT_HI(67, 66)
+#define PT_B14    PT_LO(69, 68)
+#define PT_B15    PT_HI(69, 68)
+
+#define NR_PTREGS  70
+
+#define PT_DP     PT_B14  /* Data Segment Pointer (B14) */
+#define PT_SP     PT_B15  /* Stack Pointer (B15)  */
+
+#define PTRACE_GETFDPIC                31      /* get the ELF fdpic loadmap address */
+
+#define PTRACE_GETFDPIC_EXEC   0       /* [addr] request the executable loadmap */
+#define PTRACE_GETFDPIC_INTERP 1       /* [addr] request the interpreter loadmap */
+
+#ifndef __ASSEMBLY__
+
+#ifdef _BIG_ENDIAN
+#define REG_PAIR(odd, even) unsigned long odd; unsigned long even
+#else
+#define REG_PAIR(odd, even) unsigned long even; unsigned long odd
+#endif
+
+/*
+ * this struct defines the way the registers are stored on the
+ * stack during a system call. fields defined with REG_PAIR
+ * are saved and restored using double-word memory operations
+ * which means the word ordering of the pair depends on endianess.
+ */
+struct pt_regs {
+       REG_PAIR(tsr, orig_a4);
+       REG_PAIR(rilc, ilc);
+       REG_PAIR(pc, csr);
+
+       REG_PAIR(b17, b16);
+       REG_PAIR(b19, b18);
+       REG_PAIR(b21, b20);
+       REG_PAIR(b23, b22);
+       REG_PAIR(b25, b24);
+       REG_PAIR(b27, b26);
+       REG_PAIR(b29, b28);
+       REG_PAIR(b31, b30);
+
+       REG_PAIR(b1, b0);
+       REG_PAIR(b3, b2);
+       REG_PAIR(b5, b4);
+       REG_PAIR(b7, b6);
+       REG_PAIR(b9, b8);
+       REG_PAIR(b11, b10);
+       REG_PAIR(b13, b12);
+
+       REG_PAIR(a17, a16);
+       REG_PAIR(a19, a18);
+       REG_PAIR(a21, a20);
+       REG_PAIR(a23, a22);
+       REG_PAIR(a25, a24);
+       REG_PAIR(a27, a26);
+       REG_PAIR(a29, a28);
+       REG_PAIR(a31, a30);
+
+       REG_PAIR(a1, a0);
+       REG_PAIR(a3, a2);
+       REG_PAIR(a5, a4);
+       REG_PAIR(a7, a6);
+       REG_PAIR(a9, a8);
+       REG_PAIR(a11, a10);
+       REG_PAIR(a13, a12);
+
+       REG_PAIR(a15, a14);
+       REG_PAIR(sp, dp);
+};
+
+#endif /* __ASSEMBLY__ */
+#endif /* _UAPI_ASM_C6X_PTRACE_H */
similarity index 92%
rename from arch/c6x/include/asm/unistd.h
rename to arch/c6x/include/uapi/asm/unistd.h
index ed2259043eec278b5a792b0660a326e66e292142..4ff747d12dad317e408c86bf8df6285bb31d980b 100644 (file)
@@ -14,6 +14,9 @@
  *   more details.
  */
 
+#define __ARCH_WANT_KERNEL_EXECVE
+#define __ARCH_WANT_SYS_EXECVE
+
 /* Use the standard ABI for syscalls. */
 #include <asm-generic/unistd.h>
 
index 759ad6d207b620eacd90ce906132492ac1a5ec1e..60f1e437745dd2f60eb5bf5a9c9c2c92326e6b1c 100644 (file)
@@ -116,7 +116,6 @@ void foo(void)
        DEFINE(_TIF_NOTIFY_RESUME, (1<<TIF_NOTIFY_RESUME));
        DEFINE(_TIF_SIGPENDING, (1<<TIF_SIGPENDING));
        DEFINE(_TIF_NEED_RESCHED, (1<<TIF_NEED_RESCHED));
-       DEFINE(_TIF_POLLING_NRFLAG, (1<<TIF_POLLING_NRFLAG));
 
        DEFINE(_TIF_ALLWORK_MASK, TIF_ALLWORK_MASK);
        DEFINE(_TIF_WORK_MASK, TIF_WORK_MASK);
index 30b37e5f4a6110aa9f00a58dc4ca5cf97c7327db..5449c36018fe2d269b2daaa162a25a39bfa53c9b 100644 (file)
@@ -400,6 +400,32 @@ ret_from_fork_2:
        STW     .D2T2   B0,*+SP(REGS_A4+8)
 ENDPROC(ret_from_fork)
 
+ENTRY(ret_from_kernel_thread)
+#ifdef CONFIG_C6X_BIG_KERNEL
+       MVKL    .S1     schedule_tail,A0
+       MVKH    .S1     schedule_tail,A0
+       B       .S2X    A0
+#else
+       B       .S2     schedule_tail
+#endif
+       LDW     .D2T2   *+SP(REGS_A0+8),B10 /* get fn  */
+       ADDKPC  .S2     0f,B3,3
+0:
+       B       .S2     B10                /* call fn */
+       LDW     .D2T1   *+SP(REGS_A1+8),A4 /* get arg */
+       MVKL    .S2     sys_exit,B11
+       MVKH    .S2     sys_exit,B11
+       ADDKPC  .S2     0f,B3,1
+0:
+       BNOP    .S2     B11,5   /* jump to sys_exit */
+ENDPROC(ret_from_kernel_thread)
+
+ENTRY(ret_from_kernel_execve)
+       GET_THREAD_INFO A12
+       BNOP    .S2     syscall_exit,4
+       ADD     .D2X    A4,-8,SP
+ENDPROC(ret_from_kernel_execve)
+
        ;;
        ;; These are the interrupt handlers, responsible for calling __do_IRQ()
        ;; int6 is used for syscalls (see _system_call entry)
@@ -593,13 +619,6 @@ ENTRY(sys_sigaltstack)
        NOP     4
 ENDPROC(sys_sigaltstack)
 
-       ;; kernel_execve
-ENTRY(kernel_execve)
-       MVK     .S2     __NR_execve,B0
-       SWE
-       BNOP    .S2     B3,5
-ENDPROC(kernel_execve)
-
        ;;
        ;; Special system calls
        ;; return address is in B3
@@ -628,29 +647,6 @@ ENTRY(sys_rt_sigreturn)
 #endif
 ENDPROC(sys_rt_sigreturn)
 
-ENTRY(sys_execve)
-       ADDAW   .D2     SP,2,B6         ; put regs addr in 4th parameter
-                                       ; & adjust regs stack addr
-       LDW     .D2T2   *+SP(REGS_B4+8),B4
-
-       ;; c6x_execve(char *name, char **argv,
-       ;;            char **envp, struct pt_regs *regs)
-#ifdef CONFIG_C6X_BIG_KERNEL
- ||    MVKL    .S1     sys_c6x_execve,A0
-       MVKH    .S1     sys_c6x_execve,A0
-       B       .S2X    A0
-#else
- ||    B       .S2     sys_c6x_execve
-#endif
-       STW     .D2T2   B3,*SP--[2]
-       ADDKPC  .S2     ret_from_c6x_execve,B3,3
-
-ret_from_c6x_execve:
-       LDW     .D2T2   *++SP[2],B3
-       NOP     4
-       BNOP    .S2     B3,5
-ENDPROC(sys_execve)
-
 ENTRY(sys_pread_c6x)
        MV      .D2X    A8,B7
 #ifdef CONFIG_C6X_BIG_KERNEL
index 45e924a636a0c6772f0ae31cc27599d31ba437c7..2770d9a9a84edbc4d66b9cbae3e39aff8f001d38 100644 (file)
@@ -25,6 +25,7 @@ void  (*c6x_restart)(void);
 void   (*c6x_halt)(void);
 
 extern asmlinkage void ret_from_fork(void);
+extern asmlinkage void ret_from_kernel_thread(void);
 
 /*
  * power off function, if any
@@ -103,37 +104,6 @@ void machine_power_off(void)
        halt_loop();
 }
 
-static void kernel_thread_helper(int dummy, void *arg, int (*fn)(void *))
-{
-       do_exit(fn(arg));
-}
-
-/*
- * Create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       /*
-        * copy_thread sets a4 to zero (child return from fork)
-        * so we can't just set things up to directly return to
-        * fn.
-        */
-       memset(&regs, 0, sizeof(regs));
-       regs.b4 = (unsigned long) arg;
-       regs.a6 = (unsigned long) fn;
-       regs.pc = (unsigned long) kernel_thread_helper;
-       local_save_flags(regs.csr);
-       regs.csr |= 1;
-       regs.tsr = 5; /* Set GEE and GIE in TSR */
-
-       /* Ok, create the new process.. */
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, -1, &regs,
-                      0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 void flush_thread(void)
 {
 }
@@ -191,22 +161,24 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 
        childregs = task_pt_regs(p);
 
-       *childregs = *regs;
-       childregs->a4 = 0;
-
-       if (usp == -1)
+       if (!regs) {
                /* case of  __kernel_thread: we return to supervisor space */
+               memset(childregs, 0, sizeof(struct pt_regs));
                childregs->sp = (unsigned long)(childregs + 1);
-       else
+               p->thread.pc = (unsigned long) ret_from_kernel_thread;
+               childregs->a0 = usp;            /* function */
+               childregs->a1 = ustk_size;      /* argument */
+       } else {
                /* Otherwise use the given stack */
+               *childregs = *regs;
                childregs->sp = usp;
+               p->thread.pc = (unsigned long) ret_from_fork;
+       }
 
        /* Set usp/ksp */
        p->thread.usp = childregs->sp;
-       /* switch_to uses stack to save/restore 14 callee-saved regs */
        thread_saved_ksp(p) = (unsigned long)childregs - 8;
-       p->thread.pc = (unsigned int) ret_from_fork;
-       p->thread.wchan = (unsigned long) ret_from_fork;
+       p->thread.wchan = p->thread.pc;
 #ifdef __DSBT__
        {
                unsigned long dp;
@@ -221,28 +193,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        return 0;
 }
 
-/*
- * c6x_execve() executes a new program.
- */
-SYSCALL_DEFINE4(c6x_execve, const char __user *, name,
-               const char __user *const __user *, argv,
-               const char __user *const __user *, envp,
-               struct pt_regs *, regs)
-{
-       int error;
-       char *filename;
-
-       filename = getname(name);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-
-       error = do_execve(filename, argv, envp, regs);
-       putname(filename);
-out:
-       return error;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
        return p->thread.wchan;
index bee8df43c201848e6c20439b88811efae05dfdd8..15ac7150371f719965479c9447a4bfd70b600512 100644 (file)
@@ -212,14 +212,14 @@ asmlinkage int sys_execve(const char *fname,
                          struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(fname);
        error = PTR_ERR(filename);
 
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
  out:
        return error;
index 0570e8ce603d1575943e24271cbb1f597d2dfe73..4e9992246359ee7a21e9052f56f60e589b8c72a8 100644 (file)
@@ -224,7 +224,7 @@ sys_execve(const char *fname,
           struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(fname);
        error = PTR_ERR(filename);
@@ -232,7 +232,7 @@ sys_execve(const char *fname,
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
  out:
        return error;
index a8eab26a1ec752e38d794c767bd96d5aac5373ae..ff1bf7fcae8e116d86f23a7c05d825fd4ebc60b5 100644 (file)
@@ -9,3 +9,4 @@ header-y += rs485.h
 header-y += sync_serial.h
 
 generic-y += clkdev.h
+generic-y += exec.h
diff --git a/arch/cris/include/asm/exec.h b/arch/cris/include/asm/exec.h
deleted file mode 100644 (file)
index 9665dab..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_CRIS_EXEC_H
-#define __ASM_CRIS_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* __ASM_CRIS_EXEC_H */
index 5b1c448df5c0caab0dd5e50539547cb72753b177..07c8c40c52b312ddfee756ca8ea5b0619ddb4a65 100644 (file)
@@ -78,15 +78,12 @@ struct thread_info {
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_RESTORE_SIGMASK    9       /* restore signal mask in do_signal() */
-#define TIF_POLLING_NRFLAG     16      /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE             17      /* is terminating due to OOM killer */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
-#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
-#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 
 #define _TIF_WORK_MASK         0x0000FFFE      /* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK      0x0000FFFF      /* work to do on any return to u-space */
index 9d262645f6675275c9e2c7adca9a66b114d03b88..b7412504f08a2c91635c6f75da624a59b6a6a953 100644 (file)
@@ -12,6 +12,7 @@ config FRV
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select GENERIC_CPU_DEVICES
        select ARCH_WANT_IPC_PARSE_VERSION
+       select GENERIC_KERNEL_THREAD
 
 config ZONE_DMA
        bool
index 13cd044aabdfe43ece5b8345f291e1291e86c6e7..251bd7125576861ca09380768a0279dae258f753 100644 (file)
@@ -3,3 +3,4 @@ include include/asm-generic/Kbuild.asm
 header-y += registers.h
 header-y += termios.h
 generic-y += clkdev.h
+generic-y += exec.h
diff --git a/arch/frv/include/asm/exec.h b/arch/frv/include/asm/exec.h
deleted file mode 100644 (file)
index 65c9130..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* 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 dccb9d162318bf9d9f6d93c0ee54a9a18d0a3158..a34f309e580199b5f573db3f975a199cd74d5372 100644 (file)
@@ -92,14 +92,12 @@ extern struct task_struct *__kernel_current_task;
 
 /*
  * do necessary setup to start up a newly executed thread.
- * - need to discard the frame stacked by init() invoking the execve syscall
  */
 #define start_thread(_regs, _pc, _usp)                 \
 do {                                                   \
-       __frame = __kernel_frame0_ptr;                  \
-       __frame->pc     = (_pc);                        \
-       __frame->psr    &= ~PSR_S;                      \
-       __frame->sp     = (_usp);                       \
+       _regs->pc       = (_pc);                        \
+       _regs->psr      &= ~PSR_S;                      \
+       _regs->sp       = (_usp);                       \
 } while(0)
 
 /* Free all resources held by a thread. */
@@ -107,7 +105,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-extern asmlinkage int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 extern asmlinkage void save_user_regs(struct user_context *target);
 extern asmlinkage void *restore_user_regs(const struct user_context *target, ...);
 
index ef6635ca4ecb3f73a4d7bad1cd044d9b0a1e9750..bd534b2d02583e0c3f64a7d8d97f4a2f79d7dbf4 100644 (file)
@@ -76,6 +76,7 @@ register struct pt_regs *__frame asm("gr28");
 #define user_mode(regs)                        (!((regs)->psr & PSR_S))
 #define instruction_pointer(regs)      ((regs)->pc)
 #define user_stack_pointer(regs)       ((regs)->sp)
+#define current_pt_regs()              (__frame)
 
 extern unsigned long user_stack(const struct pt_regs *);
 #define profile_pc(regs) ((regs)->pc)
index 0ff03a33c81e8b193da81f690ce94c0f0c9ad82b..bebd7eadc7720c3e3ddac4fe455a8bef37308042 100644 (file)
@@ -94,7 +94,6 @@ register struct thread_info *__current_thread_info asm("gr15");
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_SINGLESTEP         4       /* restore singlestep on return to user mode */
 #define TIF_RESTORE_SIGMASK    5       /* restore signal mask in do_signal() */
-#define TIF_POLLING_NRFLAG     6       /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE             7       /* is terminating due to OOM killer */
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
@@ -102,8 +101,6 @@ register struct thread_info *__current_thread_info asm("gr15");
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP                (1 << TIF_SINGLESTEP)
-#define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
-#define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK         \
index 67f23a311db6e3d5a55ef88b3243c7c01705b469..b6b07e55e4731fc2ba547d202657bbac98b08707 100644 (file)
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
index ad4087b69968b051ffd557ad6cb8cd2fcc9b40fb..3cbb3294b9f9ae61022e1c38cdf5799f48e34a6e 100644 (file)
@@ -7,8 +7,8 @@ heads-$(CONFIG_MMU)             := head-mmu-fr451.o
 
 extra-y:= head.o vmlinux.lds
 
-obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \
-        kernel_execve.o process.o traps.o ptrace.o signal.o dma.o \
+obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o \
+        process.o traps.o ptrace.o signal.o dma.o \
         sys_frv.o time.o setup.o frv_ksyms.o \
         debug-stub.o irq.o sleep.o uaccess.o
 
index 7d5e000fd32e0e4d40c78c2fcec1806f17bb1286..002732960315ee429d3cce6a95c8a0440064c64d 100644 (file)
@@ -863,6 +863,19 @@ ret_from_fork:
        setlos.p        #0,gr8
        bra             __syscall_exit
 
+       .globl          ret_from_kernel_thread
+ret_from_kernel_thread:
+       lddi.p          @(gr28,#REG_GR(8)),gr20
+       call            schedule_tail
+       or.p            gr20,gr20,gr8
+       calll           @(gr21,gr0)
+       bra             sys_exit
+
+       .globl          ret_from_kernel_execve
+ret_from_kernel_execve:
+       ori             gr28,0,sp
+       bra             __syscall_exit
+
 ###################################################################################################
 #
 # Return to user mode is not as complex as all this looks,
index a89803b58b9a970c47c0784ca1be398478de6142..86c516d96dcda69760dd5c86687e027dfadb4bed 100644 (file)
@@ -30,7 +30,6 @@ EXPORT_SYMBOL(ip_fast_csum);
 EXPORT_SYMBOL(local_irq_count);
 EXPORT_SYMBOL(local_bh_count);
 #endif
-EXPORT_SYMBOL(kernel_thread);
 
 EXPORT_SYMBOL(__res_bus_clock_speed_HZ);
 EXPORT_SYMBOL(__page_offset);
diff --git a/arch/frv/kernel/kernel_execve.S b/arch/frv/kernel/kernel_execve.S
deleted file mode 100644 (file)
index 9b074a1..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/* in-kernel program execution
- *
- * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/linkage.h>
-#include <asm/unistd.h>
-
-###############################################################################
-#
-# Do a system call from kernel instead of calling sys_execve so we end up with
-# proper pt_regs.
-#
-# int kernel_execve(const char *filename, char *const argv[], char *const envp[])
-#
-# On entry: GR8/GR9/GR10: arguments to function
-# On return: GR8: syscall return.
-#
-###############################################################################
-       .globl          kernel_execve
-       .type           kernel_execve,@function
-kernel_execve:
-       setlos          __NR_execve,gr7
-       tira            gr0,#0
-       bralr
-
-       .size           kernel_execve,.-kernel_execve
diff --git a/arch/frv/kernel/kernel_thread.S b/arch/frv/kernel/kernel_thread.S
deleted file mode 100644 (file)
index f0e5294..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/* kernel_thread.S: kernel thread creation
- *
- * 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.
- */
-
-#include <linux/linkage.h>
-#include <linux/kern_levels.h>
-#include <asm/unistd.h>
-
-#define CLONE_VM       0x00000100      /* set if VM shared between processes */
-
-       .section .rodata
-kernel_thread_emsg:
-       .asciz  KERN_ERR "failed to create kernel thread: error=%d\n"
-
-       .text
-       .balign         4
-
-###############################################################################
-#
-# Create a kernel thread
-#
-# int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-#
-###############################################################################
-       .globl          kernel_thread
-       .type           kernel_thread,@function
-kernel_thread:
-       or.p            gr8,gr0,gr4
-       or              gr9,gr0,gr5
-
-       # start by forking the current process, but with shared VM
-       setlos.p        #__NR_clone,gr7         ; syscall number
-       ori             gr10,#CLONE_VM,gr8      ; first syscall arg     [clone_flags]
-       sethi.p         #0xe4e4,gr9             ; second syscall arg    [newsp]
-       setlo           #0xe4e4,gr9
-       setlos.p        #0,gr10                 ; third syscall arg     [parent_tidptr]
-       setlos          #0,gr11                 ; fourth syscall arg    [child_tidptr]
-       tira            gr0,#0
-       setlos.p        #4095,gr7
-       andcc           gr8,gr8,gr0,icc0
-       addcc.p         gr8,gr7,gr0,icc1
-       bnelr           icc0,#2
-       bc              icc1,#0,kernel_thread_error
-
-       # now invoke the work function
-       or              gr5,gr0,gr8
-       calll           @(gr4,gr0)
-
-       # and finally exit the thread
-       setlos          #__NR_exit,gr7          ; syscall number
-       tira            gr0,#0
-
-kernel_thread_error:
-       subi            sp,#8,sp
-       movsg           lr,gr4
-       sti             gr8,@(sp,#0)
-       sti.p           gr4,@(sp,#4)
-
-       or              gr8,gr0,gr9
-       sethi.p         %hi(kernel_thread_emsg),gr8
-       setlo           %lo(kernel_thread_emsg),gr8
-
-       call            printk
-
-       ldi             @(sp,#4),gr4
-       ldi             @(sp,#0),gr8
-       subi            sp,#8,sp
-       jmpl            @(gr4,gr0)
-
-       .size           kernel_thread,.-kernel_thread
index 2eb7fa5bf9d8d48386ea7583dd1731dd92eff7a8..655d90d20bb0cad25df015e7bdc9dee6dbf4e37b 100644 (file)
@@ -38,6 +38,7 @@
 #include "local.h"
 
 asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
 
 #include <asm/pgalloc.h>
 
@@ -172,32 +173,13 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
  * set up the kernel stack and exception frames for a new process
  */
 int copy_thread(unsigned long clone_flags,
-               unsigned long usp, unsigned long topstk,
+               unsigned long usp, unsigned long arg,
                struct task_struct *p, struct pt_regs *regs)
 {
-       struct pt_regs *childregs0, *childregs, *regs0;
+       struct pt_regs *childregs;
 
-       regs0 = __kernel_frame0_ptr;
-       childregs0 = (struct pt_regs *)
+       childregs = (struct pt_regs *)
                (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE);
-       childregs = childregs0;
-
-       /* set up the userspace frame (the only place that the USP is stored) */
-       *childregs0 = *regs0;
-
-       childregs0->gr8         = 0;
-       childregs0->sp          = usp;
-       childregs0->next_frame  = NULL;
-
-       /* set up the return kernel frame if called from kernel_thread() */
-       if (regs != regs0) {
-               childregs--;
-               *childregs = *regs;
-               childregs->sp = (unsigned long) childregs0;
-               childregs->next_frame = childregs0;
-               childregs->gr15 = (unsigned long) task_thread_info(p);
-               childregs->gr29 = (unsigned long) p;
-       }
 
        p->set_child_tid = p->clear_child_tid = NULL;
 
@@ -206,8 +188,25 @@ int copy_thread(unsigned long clone_flags,
        p->thread.sp     = (unsigned long) childregs;
        p->thread.fp     = 0;
        p->thread.lr     = 0;
-       p->thread.pc     = (unsigned long) ret_from_fork;
-       p->thread.frame0 = childregs0;
+       p->thread.frame0 = childregs;
+
+       if (unlikely(!regs)) {
+               memset(childregs, 0, sizeof(struct pt_regs));
+               childregs->gr9 = usp; /* function */
+               childregs->gr8 = arg;
+               chilregs->psr = PSR_S;
+               p->thread.pc = (unsigned long) ret_from_kernel_thread;
+               save_user_regs(p->thread.user);
+               return 0;
+       }
+
+       /* set up the userspace frame (the only place that the USP is stored) */
+       *childregs = *regs;
+
+       childregs->sp           = usp;
+       childregs->next_frame   = NULL;
+
+       p->thread.pc = (unsigned long) ret_from_fork;
 
        /* the new TLS pointer is passed in as arg #5 to sys_clone() */
        if (clone_flags & CLONE_SETTLS)
@@ -218,25 +217,6 @@ int copy_thread(unsigned long clone_flags,
        return 0;
 } /* end copy_thread() */
 
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char __user *name,
-                         const char __user *const __user *argv,
-                         const char __user *const __user *envp)
-{
-       int error;
-       char * filename;
-
-       filename = getname(name);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               return error;
-       error = do_execve(filename, argv, envp, __frame);
-       putname(filename);
-       return error;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
        struct pt_regs *regs0;
index 864c2f0d497bfa62800e4168cac94215bff4d128..535810a3217a25bf64e3f5d53059f8a5ff1a7ea4 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/personality.h>
-#include <linux/freezer.h>
 #include <linux/tracehook.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
@@ -298,10 +297,6 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
        __frame->lr   = (unsigned long) &frame->retcode;
        __frame->gr8  = sig;
 
-       /* the tracer may want to single-step inside the handler */
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
 #if DEBUG_SIG
        printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
               sig, current->comm, current->pid, frame, __frame->pc,
@@ -400,10 +395,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        __frame->gr8 = sig;
        __frame->gr9 = (unsigned long) &frame->info;
 
-       /* the tracer may want to single-step inside the handler */
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
 #if DEBUG_SIG
        printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
               sig, current->comm, current->pid, frame, __frame->pc,
index 0e152a93c1259a551ffa65b327ae5f9b013be3dd..fccd81eddff1f6de89b07cc13c362809364c9507 100644 (file)
@@ -1,3 +1,4 @@
 include include/asm-generic/Kbuild.asm
 
-generic-y      += clkdev.h
+generic-y += clkdev.h
+generic-y += exec.h
diff --git a/arch/h8300/include/asm/exec.h b/arch/h8300/include/asm/exec.h
deleted file mode 100644 (file)
index c01c45c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_EXEC_H
-#define _H8300_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* _H8300_EXEC_H */
index 9c126e0c09aa0717f4c976586440ad18d01a7232..ec2f7777c65a6c631f68fbc87733992c7b421b6e 100644 (file)
@@ -85,8 +85,6 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_TRACE      0       /* syscall trace active */
 #define TIF_SIGPENDING         1       /* signal pending */
 #define TIF_NEED_RESCHED       2       /* rescheduling necessary */
-#define TIF_POLLING_NRFLAG     3       /* true if poll_idle() is polling
-                                          TIF_NEED_RESCHED */
 #define TIF_MEMDIE             4       /* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK    5       /* restore signal mask in do_signal() */
 #define TIF_NOTIFY_RESUME      6       /* callback before returning to user */
@@ -95,11 +93,10 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
-#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
 
-#define _TIF_WORK_MASK         0x0000FFFE      /* work to do on interrupt/exception return */
+#define _TIF_WORK_MASK         (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
+                                _TIF_NOTIFY_RESUME)
 
 #endif /* __KERNEL__ */
 
index f153ed1a4c080bf73fb4be51389fec566910825d..e8dc1393a13a9c646f382b02d6111e085442012b 100644 (file)
@@ -217,14 +217,14 @@ asmlinkage int sys_execve(const char *name,
                          int dummy, ...)
 {
        int error;
-       char * filename;
+       struct filename *filename;
        struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4);
 
        filename = getname(name);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                return error;
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
        return error;
 }
index 5adaadaf92183c42703b9995e32e622dc926d958..0e81b96c642f9cb4736070e9fdcbd453da0f0564 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/personality.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
-#include <linux/freezer.h>
 #include <linux/tracehook.h>
 
 #include <asm/setup.h>
index 4f936a7ee8470b9ada6c1fe9096f77f97506a540..e4a0aad69cbbb0164bbe3cbbb007aade36c31df7 100644 (file)
@@ -120,10 +120,8 @@ register struct thread_info *__current_thread_info asm(QUOTED_THREADINFO_REG);
 #define TIF_SIGPENDING          2       /* signal pending */
 #define TIF_NEED_RESCHED        3       /* rescheduling necessary */
 #define TIF_SINGLESTEP          4       /* restore ss @ return to usr mode */
-#define TIF_IRET                5       /* return with iret */
 #define TIF_RESTORE_SIGMASK     6       /* restore sig mask in do_signal() */
 /* true if poll_idle() is polling TIF_NEED_RESCHED */
-#define TIF_POLLING_NRFLAG      16
 #define TIF_MEMDIE              17      /* OOM killer killed process */
 
 #define _TIF_SYSCALL_TRACE      (1 << TIF_SYSCALL_TRACE)
@@ -131,9 +129,6 @@ register struct thread_info *__current_thread_info asm(QUOTED_THREADINFO_REG);
 #define _TIF_SIGPENDING         (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED       (1 << TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP         (1 << TIF_SINGLESTEP)
-#define _TIF_IRET               (1 << TIF_IRET)
-#define _TIF_RESTORE_SIGMASK    (1 << TIF_RESTORE_SIGMASK)
-#define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
 
 /* work to do on interrupt/exception return - All but TIF_SYSCALL_TRACE */
 #define _TIF_WORK_MASK          (0x0000FFFF & ~_TIF_SYSCALL_TRACE)
index 304b0808d07213f0853ee256d781a114f561a947..1ea16bec7b91385ca9bb9de3563d44e0958546af 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <linux/linkage.h>
 #include <linux/syscalls.h>
-#include <linux/freezer.h>
 #include <linux/tracehook.h>
 #include <asm/registers.h>
 #include <asm/thread_info.h>
index 620dd18197a0597144ffece20adc98f655d521dd..25a9bfe3445d941f3386e05dd8ae5c0c2ece0f95 100644 (file)
@@ -40,7 +40,7 @@ asmlinkage int sys_execve(char __user *ufilename,
                          const char __user *const __user *envp)
 {
        struct pt_regs *pregs = current_thread_info()->regs;
-       char *filename;
+       struct filename *filename;
        int retval;
 
        filename = getname(ufilename);
@@ -48,7 +48,7 @@ asmlinkage int sys_execve(char __user *ufilename,
        if (IS_ERR(filename))
                return retval;
 
-       retval = do_execve(filename, argv, envp, pregs);
+       retval = do_execve(filename->name, argv, envp, pregs);
        putname(filename);
 
        return retval;
@@ -87,4 +87,3 @@ int kernel_execve(const char *filename,
 
        return retval;
 }
-EXPORT_SYMBOL(kernel_execve);
index 3c720ef6c32de0f8d57b2439ae5f76a2346cc02e..4c10e607c908cb59a444c8f7f185eeab323bfa1d 100644 (file)
@@ -39,7 +39,7 @@ config IA64
        select ARCH_TASK_STRUCT_ALLOCATOR
        select ARCH_THREAD_INFO_ALLOCATOR
        select ARCH_CLOCKSOURCE_DATA
-       select GENERIC_TIME_VSYSCALL
+       select GENERIC_TIME_VSYSCALL_OLD
        default y
        help
          The Itanium Processor Family is Intel's 64-bit successor to
index 58f3d14a6cd4029b18531bcd1d0224d8337f7d3e..4a159da23633dbf359c9886513958ce49e842ce7 100644 (file)
@@ -1,16 +1,3 @@
-include include/asm-generic/Kbuild.asm
 
-header-y += break.h
-header-y += cmpxchg.h
-header-y += fpu.h
-header-y += gcc_intrin.h
-header-y += ia64regs.h
-header-y += intel_intrin.h
-header-y += intrinsics.h
-header-y += perfmon.h
-header-y += perfmon_default_smpl.h
-header-y += ptrace_offsets.h
-header-y += rse.h
-header-y += ucontext.h
-header-y += ustack.h
 generic-y += clkdev.h
+generic-y += exec.h
diff --git a/arch/ia64/include/asm/exec.h b/arch/ia64/include/asm/exec.h
deleted file mode 100644 (file)
index b262424..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * 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 21ddee54adaea574fbe75395704bbf795bfdcc35..f9495b1757a81d949a200a9938a2e3e94422f424 100644 (file)
-#ifndef _ASM_IA64_GCC_INTRIN_H
-#define _ASM_IA64_GCC_INTRIN_H
 /*
  *
  * Copyright (C) 2002,2003 Jun Nakajima <jun.nakajima@intel.com>
  * Copyright (C) 2002,2003 Suresh Siddha <suresh.b.siddha@intel.com>
  */
+#ifndef _ASM_IA64_GCC_INTRIN_H
+#define _ASM_IA64_GCC_INTRIN_H
 
-#include <linux/types.h>
-#include <linux/compiler.h>
-
-/* define this macro to get some asm stmts included in 'c' files */
-#define ASM_SUPPORTED
-
-/* Optimization barrier */
-/* The "volatile" is due to gcc bugs */
-#define ia64_barrier() asm volatile ("":::"memory")
-
-#define ia64_stop()    asm volatile (";;"::)
-
-#define ia64_invala_gr(regnum) asm volatile ("invala.e r%0" :: "i"(regnum))
-
-#define ia64_invala_fr(regnum) asm volatile ("invala.e f%0" :: "i"(regnum))
-
-#define ia64_flushrs() asm volatile ("flushrs;;":::"memory")
-
-#define ia64_loadrs() asm volatile ("loadrs;;":::"memory")
-
-extern void ia64_bad_param_for_setreg (void);
-extern void ia64_bad_param_for_getreg (void);
+#include <uapi/asm/gcc_intrin.h>
 
-#ifdef __KERNEL__
 register unsigned long ia64_r13 asm ("r13") __used;
-#endif
-
-#define ia64_native_setreg(regnum, val)                                                \
-({                                                                             \
-       switch (regnum) {                                                       \
-           case _IA64_REG_PSR_L:                                               \
-                   asm volatile ("mov psr.l=%0" :: "r"(val) : "memory");       \
-                   break;                                                      \
-           case _IA64_REG_AR_KR0 ... _IA64_REG_AR_EC:                          \
-                   asm volatile ("mov ar%0=%1" ::                              \
-                                         "i" (regnum - _IA64_REG_AR_KR0),      \
-                                         "r"(val): "memory");                  \
-                   break;                                                      \
-           case _IA64_REG_CR_DCR ... _IA64_REG_CR_LRR1:                        \
-                   asm volatile ("mov cr%0=%1" ::                              \
-                                         "i" (regnum - _IA64_REG_CR_DCR),      \
-                                         "r"(val): "memory" );                 \
-                   break;                                                      \
-           case _IA64_REG_SP:                                                  \
-                   asm volatile ("mov r12=%0" ::                               \
-                                         "r"(val): "memory");                  \
-                   break;                                                      \
-           case _IA64_REG_GP:                                                  \
-                   asm volatile ("mov gp=%0" :: "r"(val) : "memory");          \
-               break;                                                          \
-           default:                                                            \
-                   ia64_bad_param_for_setreg();                                \
-                   break;                                                      \
-       }                                                                       \
-})
-
-#define ia64_native_getreg(regnum)                                             \
-({                                                                             \
-       __u64 ia64_intri_res;                                                   \
-                                                                               \
-       switch (regnum) {                                                       \
-       case _IA64_REG_GP:                                                      \
-               asm volatile ("mov %0=gp" : "=r"(ia64_intri_res));              \
-               break;                                                          \
-       case _IA64_REG_IP:                                                      \
-               asm volatile ("mov %0=ip" : "=r"(ia64_intri_res));              \
-               break;                                                          \
-       case _IA64_REG_PSR:                                                     \
-               asm volatile ("mov %0=psr" : "=r"(ia64_intri_res));             \
-               break;                                                          \
-       case _IA64_REG_TP:      /* for current() */                             \
-               ia64_intri_res = ia64_r13;                                      \
-               break;                                                          \
-       case _IA64_REG_AR_KR0 ... _IA64_REG_AR_EC:                              \
-               asm volatile ("mov %0=ar%1" : "=r" (ia64_intri_res)             \
-                                     : "i"(regnum - _IA64_REG_AR_KR0));        \
-               break;                                                          \
-       case _IA64_REG_CR_DCR ... _IA64_REG_CR_LRR1:                            \
-               asm volatile ("mov %0=cr%1" : "=r" (ia64_intri_res)             \
-                                     : "i" (regnum - _IA64_REG_CR_DCR));       \
-               break;                                                          \
-       case _IA64_REG_SP:                                                      \
-               asm volatile ("mov %0=sp" : "=r" (ia64_intri_res));             \
-               break;                                                          \
-       default:                                                                \
-               ia64_bad_param_for_getreg();                                    \
-               break;                                                          \
-       }                                                                       \
-       ia64_intri_res;                                                         \
-})
-
-#define ia64_hint_pause 0
-
-#define ia64_hint(mode)                                                \
-({                                                             \
-       switch (mode) {                                         \
-       case ia64_hint_pause:                                   \
-               asm volatile ("hint @pause" ::: "memory");      \
-               break;                                          \
-       }                                                       \
-})
-
-
-/* Integer values for mux1 instruction */
-#define ia64_mux1_brcst 0
-#define ia64_mux1_mix   8
-#define ia64_mux1_shuf  9
-#define ia64_mux1_alt  10
-#define ia64_mux1_rev  11
-
-#define ia64_mux1(x, mode)                                                     \
-({                                                                             \
-       __u64 ia64_intri_res;                                                   \
-                                                                               \
-       switch (mode) {                                                         \
-       case ia64_mux1_brcst:                                                   \
-               asm ("mux1 %0=%1,@brcst" : "=r" (ia64_intri_res) : "r" (x));    \
-               break;                                                          \
-       case ia64_mux1_mix:                                                     \
-               asm ("mux1 %0=%1,@mix" : "=r" (ia64_intri_res) : "r" (x));      \
-               break;                                                          \
-       case ia64_mux1_shuf:                                                    \
-               asm ("mux1 %0=%1,@shuf" : "=r" (ia64_intri_res) : "r" (x));     \
-               break;                                                          \
-       case ia64_mux1_alt:                                                     \
-               asm ("mux1 %0=%1,@alt" : "=r" (ia64_intri_res) : "r" (x));      \
-               break;                                                          \
-       case ia64_mux1_rev:                                                     \
-               asm ("mux1 %0=%1,@rev" : "=r" (ia64_intri_res) : "r" (x));      \
-               break;                                                          \
-       }                                                                       \
-       ia64_intri_res;                                                         \
-})
-
-#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-# define ia64_popcnt(x)                __builtin_popcountl(x)
-#else
-# define ia64_popcnt(x)                                                \
-  ({                                                           \
-       __u64 ia64_intri_res;                                   \
-       asm ("popcnt %0=%1" : "=r" (ia64_intri_res) : "r" (x)); \
-                                                               \
-       ia64_intri_res;                                         \
-  })
-#endif
-
-#define ia64_getf_exp(x)                                       \
-({                                                             \
-       long ia64_intri_res;                                    \
-                                                               \
-       asm ("getf.exp %0=%1" : "=r"(ia64_intri_res) : "f"(x)); \
-                                                               \
-       ia64_intri_res;                                         \
-})
-
-#define ia64_shrp(a, b, count)                                                         \
-({                                                                                     \
-       __u64 ia64_intri_res;                                                           \
-       asm ("shrp %0=%1,%2,%3" : "=r"(ia64_intri_res) : "r"(a), "r"(b), "i"(count));   \
-       ia64_intri_res;                                                                 \
-})
-
-#define ia64_ldfs(regnum, x)                                   \
-({                                                             \
-       register double __f__ asm ("f"#regnum);                 \
-       asm volatile ("ldfs %0=[%1]" :"=f"(__f__): "r"(x));     \
-})
-
-#define ia64_ldfd(regnum, x)                                   \
-({                                                             \
-       register double __f__ asm ("f"#regnum);                 \
-       asm volatile ("ldfd %0=[%1]" :"=f"(__f__): "r"(x));     \
-})
-
-#define ia64_ldfe(regnum, x)                                   \
-({                                                             \
-       register double __f__ asm ("f"#regnum);                 \
-       asm volatile ("ldfe %0=[%1]" :"=f"(__f__): "r"(x));     \
-})
-
-#define ia64_ldf8(regnum, x)                                   \
-({                                                             \
-       register double __f__ asm ("f"#regnum);                 \
-       asm volatile ("ldf8 %0=[%1]" :"=f"(__f__): "r"(x));     \
-})
-
-#define ia64_ldf_fill(regnum, x)                               \
-({                                                             \
-       register double __f__ asm ("f"#regnum);                 \
-       asm volatile ("ldf.fill %0=[%1]" :"=f"(__f__): "r"(x)); \
-})
-
-#define ia64_st4_rel_nta(m, val)                                       \
-({                                                                     \
-       asm volatile ("st4.rel.nta [%0] = %1\n\t" :: "r"(m), "r"(val)); \
-})
-
-#define ia64_stfs(x, regnum)                                           \
-({                                                                     \
-       register double __f__ asm ("f"#regnum);                         \
-       asm volatile ("stfs [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \
-})
-
-#define ia64_stfd(x, regnum)                                           \
-({                                                                     \
-       register double __f__ asm ("f"#regnum);                         \
-       asm volatile ("stfd [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \
-})
-
-#define ia64_stfe(x, regnum)                                           \
-({                                                                     \
-       register double __f__ asm ("f"#regnum);                         \
-       asm volatile ("stfe [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \
-})
-
-#define ia64_stf8(x, regnum)                                           \
-({                                                                     \
-       register double __f__ asm ("f"#regnum);                         \
-       asm volatile ("stf8 [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \
-})
-
-#define ia64_stf_spill(x, regnum)                                              \
-({                                                                             \
-       register double __f__ asm ("f"#regnum);                                 \
-       asm volatile ("stf.spill [%0]=%1" :: "r"(x), "f"(__f__) : "memory");    \
-})
-
-#define ia64_fetchadd4_acq(p, inc)                                             \
-({                                                                             \
-                                                                               \
-       __u64 ia64_intri_res;                                                   \
-       asm volatile ("fetchadd4.acq %0=[%1],%2"                                \
-                               : "=r"(ia64_intri_res) : "r"(p), "i" (inc)      \
-                               : "memory");                                    \
-                                                                               \
-       ia64_intri_res;                                                         \
-})
-
-#define ia64_fetchadd4_rel(p, inc)                                             \
-({                                                                             \
-       __u64 ia64_intri_res;                                                   \
-       asm volatile ("fetchadd4.rel %0=[%1],%2"                                \
-                               : "=r"(ia64_intri_res) : "r"(p), "i" (inc)      \
-                               : "memory");                                    \
-                                                                               \
-       ia64_intri_res;                                                         \
-})
-
-#define ia64_fetchadd8_acq(p, inc)                                             \
-({                                                                             \
-                                                                               \
-       __u64 ia64_intri_res;                                                   \
-       asm volatile ("fetchadd8.acq %0=[%1],%2"                                \
-                               : "=r"(ia64_intri_res) : "r"(p), "i" (inc)      \
-                               : "memory");                                    \
-                                                                               \
-       ia64_intri_res;                                                         \
-})
-
-#define ia64_fetchadd8_rel(p, inc)                                             \
-({                                                                             \
-       __u64 ia64_intri_res;                                                   \
-       asm volatile ("fetchadd8.rel %0=[%1],%2"                                \
-                               : "=r"(ia64_intri_res) : "r"(p), "i" (inc)      \
-                               : "memory");                                    \
-                                                                               \
-       ia64_intri_res;                                                         \
-})
-
-#define ia64_xchg1(ptr,x)                                                      \
-({                                                                             \
-       __u64 ia64_intri_res;                                                   \
-       asm volatile ("xchg1 %0=[%1],%2"                                        \
-                     : "=r" (ia64_intri_res) : "r" (ptr), "r" (x) : "memory"); \
-       ia64_intri_res;                                                         \
-})
-
-#define ia64_xchg2(ptr,x)                                              \
-({                                                                     \
-       __u64 ia64_intri_res;                                           \
-       asm volatile ("xchg2 %0=[%1],%2" : "=r" (ia64_intri_res)        \
-                     : "r" (ptr), "r" (x) : "memory");                 \
-       ia64_intri_res;                                                 \
-})
-
-#define ia64_xchg4(ptr,x)                                              \
-({                                                                     \
-       __u64 ia64_intri_res;                                           \
-       asm volatile ("xchg4 %0=[%1],%2" : "=r" (ia64_intri_res)        \
-                     : "r" (ptr), "r" (x) : "memory");                 \
-       ia64_intri_res;                                                 \
-})
-
-#define ia64_xchg8(ptr,x)                                              \
-({                                                                     \
-       __u64 ia64_intri_res;                                           \
-       asm volatile ("xchg8 %0=[%1],%2" : "=r" (ia64_intri_res)        \
-                     : "r" (ptr), "r" (x) : "memory");                 \
-       ia64_intri_res;                                                 \
-})
-
-#define ia64_cmpxchg1_acq(ptr, new, old)                                               \
-({                                                                                     \
-       __u64 ia64_intri_res;                                                           \
-       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
-       asm volatile ("cmpxchg1.acq %0=[%1],%2,ar.ccv":                                 \
-                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
-       ia64_intri_res;                                                                 \
-})
-
-#define ia64_cmpxchg1_rel(ptr, new, old)                                               \
-({                                                                                     \
-       __u64 ia64_intri_res;                                                           \
-       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
-       asm volatile ("cmpxchg1.rel %0=[%1],%2,ar.ccv":                                 \
-                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
-       ia64_intri_res;                                                                 \
-})
-
-#define ia64_cmpxchg2_acq(ptr, new, old)                                               \
-({                                                                                     \
-       __u64 ia64_intri_res;                                                           \
-       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
-       asm volatile ("cmpxchg2.acq %0=[%1],%2,ar.ccv":                                 \
-                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
-       ia64_intri_res;                                                                 \
-})
-
-#define ia64_cmpxchg2_rel(ptr, new, old)                                               \
-({                                                                                     \
-       __u64 ia64_intri_res;                                                           \
-       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
-                                                                                       \
-       asm volatile ("cmpxchg2.rel %0=[%1],%2,ar.ccv":                                 \
-                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
-       ia64_intri_res;                                                                 \
-})
-
-#define ia64_cmpxchg4_acq(ptr, new, old)                                               \
-({                                                                                     \
-       __u64 ia64_intri_res;                                                           \
-       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
-       asm volatile ("cmpxchg4.acq %0=[%1],%2,ar.ccv":                                 \
-                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
-       ia64_intri_res;                                                                 \
-})
-
-#define ia64_cmpxchg4_rel(ptr, new, old)                                               \
-({                                                                                     \
-       __u64 ia64_intri_res;                                                           \
-       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
-       asm volatile ("cmpxchg4.rel %0=[%1],%2,ar.ccv":                                 \
-                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
-       ia64_intri_res;                                                                 \
-})
-
-#define ia64_cmpxchg8_acq(ptr, new, old)                                               \
-({                                                                                     \
-       __u64 ia64_intri_res;                                                           \
-       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
-       asm volatile ("cmpxchg8.acq %0=[%1],%2,ar.ccv":                                 \
-                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
-       ia64_intri_res;                                                                 \
-})
-
-#define ia64_cmpxchg8_rel(ptr, new, old)                                               \
-({                                                                                     \
-       __u64 ia64_intri_res;                                                           \
-       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
-                                                                                       \
-       asm volatile ("cmpxchg8.rel %0=[%1],%2,ar.ccv":                                 \
-                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
-       ia64_intri_res;                                                                 \
-})
-
-#define ia64_mf()      asm volatile ("mf" ::: "memory")
-#define ia64_mfa()     asm volatile ("mf.a" ::: "memory")
-
-#define ia64_invala() asm volatile ("invala" ::: "memory")
-
-#define ia64_native_thash(addr)                                                        \
-({                                                                             \
-       unsigned long ia64_intri_res;                                           \
-       asm volatile ("thash %0=%1" : "=r"(ia64_intri_res) : "r" (addr));       \
-       ia64_intri_res;                                                         \
-})
-
-#define ia64_srlz_i()  asm volatile (";; srlz.i ;;" ::: "memory")
-#define ia64_srlz_d()  asm volatile (";; srlz.d" ::: "memory");
-
-#ifdef HAVE_SERIALIZE_DIRECTIVE
-# define ia64_dv_serialize_data()              asm volatile (".serialize.data");
-# define ia64_dv_serialize_instruction()       asm volatile (".serialize.instruction");
-#else
-# define ia64_dv_serialize_data()
-# define ia64_dv_serialize_instruction()
-#endif
-
-#define ia64_nop(x)    asm volatile ("nop %0"::"i"(x));
-
-#define ia64_itci(addr)        asm volatile ("itc.i %0;;" :: "r"(addr) : "memory")
-
-#define ia64_itcd(addr)        asm volatile ("itc.d %0;;" :: "r"(addr) : "memory")
-
-
-#define ia64_itri(trnum, addr) asm volatile ("itr.i itr[%0]=%1"                                \
-                                            :: "r"(trnum), "r"(addr) : "memory")
-
-#define ia64_itrd(trnum, addr) asm volatile ("itr.d dtr[%0]=%1"                                \
-                                            :: "r"(trnum), "r"(addr) : "memory")
-
-#define ia64_tpa(addr)                                                         \
-({                                                                             \
-       unsigned long ia64_pa;                                                  \
-       asm volatile ("tpa %0 = %1" : "=r"(ia64_pa) : "r"(addr) : "memory");    \
-       ia64_pa;                                                                \
-})
-
-#define __ia64_set_dbr(index, val)                                             \
-       asm volatile ("mov dbr[%0]=%1" :: "r"(index), "r"(val) : "memory")
-
-#define ia64_set_ibr(index, val)                                               \
-       asm volatile ("mov ibr[%0]=%1" :: "r"(index), "r"(val) : "memory")
-
-#define ia64_set_pkr(index, val)                                               \
-       asm volatile ("mov pkr[%0]=%1" :: "r"(index), "r"(val) : "memory")
-
-#define ia64_set_pmc(index, val)                                               \
-       asm volatile ("mov pmc[%0]=%1" :: "r"(index), "r"(val) : "memory")
-
-#define ia64_set_pmd(index, val)                                               \
-       asm volatile ("mov pmd[%0]=%1" :: "r"(index), "r"(val) : "memory")
-
-#define ia64_native_set_rr(index, val)                                                 \
-       asm volatile ("mov rr[%0]=%1" :: "r"(index), "r"(val) : "memory");
-
-#define ia64_native_get_cpuid(index)                                                   \
-({                                                                                     \
-       unsigned long ia64_intri_res;                                                   \
-       asm volatile ("mov %0=cpuid[%r1]" : "=r"(ia64_intri_res) : "rO"(index));        \
-       ia64_intri_res;                                                                 \
-})
-
-#define __ia64_get_dbr(index)                                                  \
-({                                                                             \
-       unsigned long ia64_intri_res;                                           \
-       asm volatile ("mov %0=dbr[%1]" : "=r"(ia64_intri_res) : "r"(index));    \
-       ia64_intri_res;                                                         \
-})
-
-#define ia64_get_ibr(index)                                                    \
-({                                                                             \
-       unsigned long ia64_intri_res;                                           \
-       asm volatile ("mov %0=ibr[%1]" : "=r"(ia64_intri_res) : "r"(index));    \
-       ia64_intri_res;                                                         \
-})
-
-#define ia64_get_pkr(index)                                                    \
-({                                                                             \
-       unsigned long ia64_intri_res;                                           \
-       asm volatile ("mov %0=pkr[%1]" : "=r"(ia64_intri_res) : "r"(index));    \
-       ia64_intri_res;                                                         \
-})
-
-#define ia64_get_pmc(index)                                                    \
-({                                                                             \
-       unsigned long ia64_intri_res;                                           \
-       asm volatile ("mov %0=pmc[%1]" : "=r"(ia64_intri_res) : "r"(index));    \
-       ia64_intri_res;                                                         \
-})
-
-
-#define ia64_native_get_pmd(index)                                             \
-({                                                                             \
-       unsigned long ia64_intri_res;                                           \
-       asm volatile ("mov %0=pmd[%1]" : "=r"(ia64_intri_res) : "r"(index));    \
-       ia64_intri_res;                                                         \
-})
-
-#define ia64_native_get_rr(index)                                              \
-({                                                                             \
-       unsigned long ia64_intri_res;                                           \
-       asm volatile ("mov %0=rr[%1]" : "=r"(ia64_intri_res) : "r" (index));    \
-       ia64_intri_res;                                                         \
-})
-
-#define ia64_native_fc(addr)   asm volatile ("fc %0" :: "r"(addr) : "memory")
-
-
-#define ia64_sync_i()  asm volatile (";; sync.i" ::: "memory")
-
-#define ia64_native_ssm(mask)  asm volatile ("ssm %0":: "i"((mask)) : "memory")
-#define ia64_native_rsm(mask)  asm volatile ("rsm %0":: "i"((mask)) : "memory")
-#define ia64_sum(mask) asm volatile ("sum %0":: "i"((mask)) : "memory")
-#define ia64_rum(mask) asm volatile ("rum %0":: "i"((mask)) : "memory")
-
-#define ia64_ptce(addr)        asm volatile ("ptc.e %0" :: "r"(addr))
-
-#define ia64_native_ptcga(addr, size)                                          \
-do {                                                                           \
-       asm volatile ("ptc.ga %0,%1" :: "r"(addr), "r"(size) : "memory");       \
-       ia64_dv_serialize_data();                                               \
-} while (0)
-
-#define ia64_ptcl(addr, size)                                                  \
-do {                                                                           \
-       asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(size) : "memory");        \
-       ia64_dv_serialize_data();                                               \
-} while (0)
-
-#define ia64_ptri(addr, size)                                          \
-       asm volatile ("ptr.i %0,%1" :: "r"(addr), "r"(size) : "memory")
-
-#define ia64_ptrd(addr, size)                                          \
-       asm volatile ("ptr.d %0,%1" :: "r"(addr), "r"(size) : "memory")
-
-#define ia64_ttag(addr)                                                        \
-({                                                                       \
-       __u64 ia64_intri_res;                                              \
-       asm volatile ("ttag %0=%1" : "=r"(ia64_intri_res) : "r" (addr));   \
-       ia64_intri_res;                                                  \
-})
-
-
-/* Values for lfhint in ia64_lfetch and ia64_lfetch_fault */
-
-#define ia64_lfhint_none   0
-#define ia64_lfhint_nt1    1
-#define ia64_lfhint_nt2    2
-#define ia64_lfhint_nta    3
-
-#define ia64_lfetch(lfhint, y)                                 \
-({                                                             \
-        switch (lfhint) {                                      \
-        case ia64_lfhint_none:                                 \
-                asm volatile ("lfetch [%0]" : : "r"(y));       \
-                break;                                         \
-        case ia64_lfhint_nt1:                                  \
-                asm volatile ("lfetch.nt1 [%0]" : : "r"(y));   \
-                break;                                         \
-        case ia64_lfhint_nt2:                                  \
-                asm volatile ("lfetch.nt2 [%0]" : : "r"(y));   \
-                break;                                         \
-        case ia64_lfhint_nta:                                  \
-                asm volatile ("lfetch.nta [%0]" : : "r"(y));   \
-                break;                                         \
-        }                                                      \
-})
-
-#define ia64_lfetch_excl(lfhint, y)                                    \
-({                                                                     \
-        switch (lfhint) {                                              \
-        case ia64_lfhint_none:                                         \
-                asm volatile ("lfetch.excl [%0]" :: "r"(y));           \
-                break;                                                 \
-        case ia64_lfhint_nt1:                                          \
-                asm volatile ("lfetch.excl.nt1 [%0]" :: "r"(y));       \
-                break;                                                 \
-        case ia64_lfhint_nt2:                                          \
-                asm volatile ("lfetch.excl.nt2 [%0]" :: "r"(y));       \
-                break;                                                 \
-        case ia64_lfhint_nta:                                          \
-                asm volatile ("lfetch.excl.nta [%0]" :: "r"(y));       \
-                break;                                                 \
-        }                                                              \
-})
-
-#define ia64_lfetch_fault(lfhint, y)                                   \
-({                                                                     \
-        switch (lfhint) {                                              \
-        case ia64_lfhint_none:                                         \
-                asm volatile ("lfetch.fault [%0]" : : "r"(y));         \
-                break;                                                 \
-        case ia64_lfhint_nt1:                                          \
-                asm volatile ("lfetch.fault.nt1 [%0]" : : "r"(y));     \
-                break;                                                 \
-        case ia64_lfhint_nt2:                                          \
-                asm volatile ("lfetch.fault.nt2 [%0]" : : "r"(y));     \
-                break;                                                 \
-        case ia64_lfhint_nta:                                          \
-                asm volatile ("lfetch.fault.nta [%0]" : : "r"(y));     \
-                break;                                                 \
-        }                                                              \
-})
-
-#define ia64_lfetch_fault_excl(lfhint, y)                              \
-({                                                                     \
-        switch (lfhint) {                                              \
-        case ia64_lfhint_none:                                         \
-                asm volatile ("lfetch.fault.excl [%0]" :: "r"(y));     \
-                break;                                                 \
-        case ia64_lfhint_nt1:                                          \
-                asm volatile ("lfetch.fault.excl.nt1 [%0]" :: "r"(y)); \
-                break;                                                 \
-        case ia64_lfhint_nt2:                                          \
-                asm volatile ("lfetch.fault.excl.nt2 [%0]" :: "r"(y)); \
-                break;                                                 \
-        case ia64_lfhint_nta:                                          \
-                asm volatile ("lfetch.fault.excl.nta [%0]" :: "r"(y)); \
-                break;                                                 \
-        }                                                              \
-})
-
-#define ia64_native_intrin_local_irq_restore(x)                        \
-do {                                                           \
-       asm volatile (";;   cmp.ne p6,p7=%0,r0;;"               \
-                     "(p6) ssm psr.i;"                         \
-                     "(p7) rsm psr.i;;"                        \
-                     "(p6) srlz.d"                             \
-                     :: "r"((x)) : "p6", "p7", "memory");      \
-} while (0)
-
 #endif /* _ASM_IA64_GCC_INTRIN_H */
index d129e367e76448036c4dad8c347cc6a33977f710..20477ea111ba2f2e71271e48b826fb22fc5ef041 100644 (file)
@@ -1,99 +1,16 @@
-#ifndef _ASM_IA64_INTRINSICS_H
-#define _ASM_IA64_INTRINSICS_H
-
 /*
  * Compiler-dependent intrinsics.
  *
  * Copyright (C) 2002-2003 Hewlett-Packard Co
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
+#ifndef _ASM_IA64_INTRINSICS_H
+#define _ASM_IA64_INTRINSICS_H
 
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-/* include compiler specific intrinsics */
-#include <asm/ia64regs.h>
-#ifdef __INTEL_COMPILER
-# include <asm/intel_intrin.h>
-#else
-# include <asm/gcc_intrin.h>
-#endif
-#include <asm/cmpxchg.h>
-
-#define ia64_native_get_psr_i()        (ia64_native_getreg(_IA64_REG_PSR) & IA64_PSR_I)
-
-#define ia64_native_set_rr0_to_rr4(val0, val1, val2, val3, val4)       \
-do {                                                                   \
-       ia64_native_set_rr(0x0000000000000000UL, (val0));               \
-       ia64_native_set_rr(0x2000000000000000UL, (val1));               \
-       ia64_native_set_rr(0x4000000000000000UL, (val2));               \
-       ia64_native_set_rr(0x6000000000000000UL, (val3));               \
-       ia64_native_set_rr(0x8000000000000000UL, (val4));               \
-} while (0)
-
-/*
- * Force an unresolved reference if someone tries to use
- * ia64_fetch_and_add() with a bad value.
- */
-extern unsigned long __bad_size_for_ia64_fetch_and_add (void);
-extern unsigned long __bad_increment_for_ia64_fetch_and_add (void);
-
-#define IA64_FETCHADD(tmp,v,n,sz,sem)                                          \
-({                                                                             \
-       switch (sz) {                                                           \
-             case 4:                                                           \
-               tmp = ia64_fetchadd4_##sem((unsigned int *) v, n);              \
-               break;                                                          \
-                                                                               \
-             case 8:                                                           \
-               tmp = ia64_fetchadd8_##sem((unsigned long *) v, n);             \
-               break;                                                          \
-                                                                               \
-             default:                                                          \
-               __bad_size_for_ia64_fetch_and_add();                            \
-       }                                                                       \
-})
-
-#define ia64_fetchadd(i,v,sem)                                                         \
-({                                                                                     \
-       __u64 _tmp;                                                                     \
-       volatile __typeof__(*(v)) *_v = (v);                                            \
-       /* Can't use a switch () here: gcc isn't always smart enough for that... */     \
-       if ((i) == -16)                                                                 \
-               IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v)), sem);                        \
-       else if ((i) == -8)                                                             \
-               IA64_FETCHADD(_tmp, _v, -8, sizeof(*(v)), sem);                         \
-       else if ((i) == -4)                                                             \
-               IA64_FETCHADD(_tmp, _v, -4, sizeof(*(v)), sem);                         \
-       else if ((i) == -1)                                                             \
-               IA64_FETCHADD(_tmp, _v, -1, sizeof(*(v)), sem);                         \
-       else if ((i) == 1)                                                              \
-               IA64_FETCHADD(_tmp, _v, 1, sizeof(*(v)), sem);                          \
-       else if ((i) == 4)                                                              \
-               IA64_FETCHADD(_tmp, _v, 4, sizeof(*(v)), sem);                          \
-       else if ((i) == 8)                                                              \
-               IA64_FETCHADD(_tmp, _v, 8, sizeof(*(v)), sem);                          \
-       else if ((i) == 16)                                                             \
-               IA64_FETCHADD(_tmp, _v, 16, sizeof(*(v)), sem);                         \
-       else                                                                            \
-               _tmp = __bad_increment_for_ia64_fetch_and_add();                        \
-       (__typeof__(*(v))) (_tmp);      /* return old value */                          \
-})
-
-#define ia64_fetch_and_add(i,v)        (ia64_fetchadd(i, v, rel) + (i)) /* return new value */
-
-#endif
-
-#ifdef __KERNEL__
 #include <asm/paravirt_privop.h>
-#endif
+#include <uapi/asm/intrinsics.h>
 
 #ifndef __ASSEMBLY__
-
-#define IA64_INTRINSIC_API(name)       ia64_native_ ## name
-#define IA64_INTRINSIC_MACRO(name)     ia64_native_ ## name
-
-#if defined(__KERNEL__)
 #if defined(CONFIG_PARAVIRT)
 # undef IA64_INTRINSIC_API
 # undef IA64_INTRINSIC_MACRO
@@ -104,36 +21,5 @@ extern unsigned long __bad_increment_for_ia64_fetch_and_add (void);
 # endif
 #define IA64_INTRINSIC_MACRO(name)     paravirt_ ## name
 #endif
-#endif
-
-/************************************************/
-/* Instructions paravirtualized for correctness */
-/************************************************/
-/* fc, thash, get_cpuid, get_pmd, get_eflags, set_eflags */
-/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag"
- * is not currently used (though it may be in a long-format VHPT system!)
- */
-#define ia64_fc                                IA64_INTRINSIC_API(fc)
-#define ia64_thash                     IA64_INTRINSIC_API(thash)
-#define ia64_get_cpuid                 IA64_INTRINSIC_API(get_cpuid)
-#define ia64_get_pmd                   IA64_INTRINSIC_API(get_pmd)
-
-
-/************************************************/
-/* Instructions paravirtualized for performance */
-/************************************************/
-#define ia64_ssm                       IA64_INTRINSIC_MACRO(ssm)
-#define ia64_rsm                       IA64_INTRINSIC_MACRO(rsm)
-#define ia64_getreg                    IA64_INTRINSIC_MACRO(getreg)
-#define ia64_setreg                    IA64_INTRINSIC_API(setreg)
-#define ia64_set_rr                    IA64_INTRINSIC_API(set_rr)
-#define ia64_get_rr                    IA64_INTRINSIC_API(get_rr)
-#define ia64_ptcga                     IA64_INTRINSIC_API(ptcga)
-#define ia64_get_psr_i                 IA64_INTRINSIC_API(get_psr_i)
-#define ia64_intrin_local_irq_restore  \
-       IA64_INTRINSIC_API(intrin_local_irq_restore)
-#define ia64_set_rr0_to_rr4            IA64_INTRINSIC_API(set_rr0_to_rr4)
-
 #endif /* !__ASSEMBLY__ */
-
 #endif /* _ASM_IA64_INTRINSICS_H */
index 2019cb99335e2d5da84546cd977d2a46f92d4340..47c00f910434f2791c279e5866987286d4d8aefa 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef __IA64_KVM_PARA_H
-#define __IA64_KVM_PARA_H
-
 /*
  * Copyright (C) 2007 Xiantao Zhang <xiantao.zhang@intel.com>
  *
  * Place - Suite 330, Boston, MA 02111-1307 USA.
  *
  */
+#ifndef __IA64_KVM_PARA_H
+#define __IA64_KVM_PARA_H
+
+#include <uapi/asm/kvm_para.h>
 
-#ifdef __KERNEL__
 
 static inline unsigned int kvm_arch_para_features(void)
 {
@@ -32,5 +32,3 @@ static inline bool kvm_check_and_clear_guest_paused(void)
 }
 
 #endif
-
-#endif
index 4459028e5aa814276233f8e3d38e4e6695ec2a70..fdd5f5229f78dacf048ff09d6d817aca42c23db0 100644 (file)
@@ -1,23 +1,17 @@
-#ifndef _ASM_IA64_MMAN_H
-#define _ASM_IA64_MMAN_H
-
 /*
  * Based on <asm-i386/mman.h>.
  *
  * Modified 1998-2000, 2002
  *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
+#ifndef _ASM_IA64_MMAN_H
+#define _ASM_IA64_MMAN_H
 
-#include <asm-generic/mman.h>
-
-#define MAP_GROWSUP    0x0200          /* register stack-like segment */
+#include <uapi/asm/mman.h>
 
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 #define arch_mmap_check        ia64_mmap_check
 int ia64_mmap_check(unsigned long addr, unsigned long len,
                unsigned long flags);
 #endif
-#endif
-
 #endif /* _ASM_IA64_MMAN_H */
index 0964c32c1358591270323341d4a65928ab4494c7..1295913d6a8211cab60659ed889bc6f1c07dcf56 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef _ASM_IA64_PARAM_H
-#define _ASM_IA64_PARAM_H
-
 /*
  * Fundamental kernel parameters.
  *
@@ -9,25 +6,12 @@
  * Modified 1998, 1999, 2002-2003
  *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
+#ifndef _ASM_IA64_PARAM_H
+#define _ASM_IA64_PARAM_H
 
-#define EXEC_PAGESIZE  65536
-
-#ifndef NOGROUP
-# define NOGROUP       (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64      /* max length of hostname */
+#include <uapi/asm/param.h>
 
-#ifdef __KERNEL__
 # define HZ            CONFIG_HZ
 # define USER_HZ       HZ
 # define CLOCKS_PER_SEC        HZ      /* frequency at which times() counts */
-#else
-   /*
-    * Technically, this is wrong, but some old apps still refer to it.  The proper way to
-    * get the HZ value is via sysconf(_SC_CLK_TCK).
-    */
-# define HZ 1024
-#endif
-
 #endif /* _ASM_IA64_PARAM_H */
index d551183fee90dde6f1a8bfa91c5ec3b9abf71653..15476dd3a8b07f28b5ba5131434f82f411511958 100644 (file)
  * Copyright (C) 2001-2003 Hewlett-Packard Co
  *               Stephane Eranian <eranian@hpl.hp.com>
  */
-
 #ifndef _ASM_IA64_PERFMON_H
 #define _ASM_IA64_PERFMON_H
 
-/*
- * perfmon commands supported on all CPU models
- */
-#define PFM_WRITE_PMCS         0x01
-#define PFM_WRITE_PMDS         0x02
-#define PFM_READ_PMDS          0x03
-#define PFM_STOP               0x04
-#define PFM_START              0x05
-#define PFM_ENABLE             0x06 /* obsolete */
-#define PFM_DISABLE            0x07 /* obsolete */
-#define PFM_CREATE_CONTEXT     0x08
-#define PFM_DESTROY_CONTEXT    0x09 /* obsolete use close() */
-#define PFM_RESTART            0x0a
-#define PFM_PROTECT_CONTEXT    0x0b /* obsolete */
-#define PFM_GET_FEATURES       0x0c
-#define PFM_DEBUG              0x0d
-#define PFM_UNPROTECT_CONTEXT  0x0e /* obsolete */
-#define PFM_GET_PMC_RESET_VAL  0x0f
-#define PFM_LOAD_CONTEXT       0x10
-#define PFM_UNLOAD_CONTEXT     0x11
-
-/*
- * PMU model specific commands (may not be supported on all PMU models)
- */
-#define PFM_WRITE_IBRS         0x20
-#define PFM_WRITE_DBRS         0x21
-
-/*
- * context flags
- */
-#define PFM_FL_NOTIFY_BLOCK             0x01   /* block task on user level notifications */
-#define PFM_FL_SYSTEM_WIDE      0x02   /* create a system wide context */
-#define PFM_FL_OVFL_NO_MSG      0x80   /* do not post overflow/end messages for notification */
-
-/*
- * event set flags
- */
-#define PFM_SETFL_EXCL_IDLE      0x01   /* exclude idle task (syswide only) XXX: DO NOT USE YET */
-
-/*
- * PMC flags
- */
-#define PFM_REGFL_OVFL_NOTIFY  0x1     /* send notification on overflow */
-#define PFM_REGFL_RANDOM       0x2     /* randomize sampling interval   */
-
-/*
- * PMD/PMC/IBR/DBR return flags (ignored on input)
- *
- * Those flags are used on output and must be checked in case EAGAIN is returned
- * by any of the calls using a pfarg_reg_t or pfarg_dbreg_t structure.
- */
-#define PFM_REG_RETFL_NOTAVAIL (1UL<<31) /* set if register is implemented but not available */
-#define PFM_REG_RETFL_EINVAL   (1UL<<30) /* set if register entry is invalid */
-#define PFM_REG_RETFL_MASK     (PFM_REG_RETFL_NOTAVAIL|PFM_REG_RETFL_EINVAL)
-
-#define PFM_REG_HAS_ERROR(flag)        (((flag) & PFM_REG_RETFL_MASK) != 0)
-
-typedef unsigned char pfm_uuid_t[16];  /* custom sampling buffer identifier type */
-
-/*
- * Request structure used to define a context
- */
-typedef struct {
-       pfm_uuid_t     ctx_smpl_buf_id;  /* which buffer format to use (if needed) */
-       unsigned long  ctx_flags;        /* noblock/block */
-       unsigned short ctx_nextra_sets;  /* number of extra event sets (you always get 1) */
-       unsigned short ctx_reserved1;    /* for future use */
-       int            ctx_fd;           /* return arg: unique identification for context */
-       void           *ctx_smpl_vaddr;  /* return arg: virtual address of sampling buffer, is used */
-       unsigned long  ctx_reserved2[11];/* for future use */
-} pfarg_context_t;
-
-/*
- * Request structure used to write/read a PMC or PMD
- */
-typedef struct {
-       unsigned int    reg_num;           /* which register */
-       unsigned short  reg_set;           /* event set for this register */
-       unsigned short  reg_reserved1;     /* for future use */
-
-       unsigned long   reg_value;         /* initial pmc/pmd value */
-       unsigned long   reg_flags;         /* input: pmc/pmd flags, return: reg error */
-
-       unsigned long   reg_long_reset;    /* reset after buffer overflow notification */
-       unsigned long   reg_short_reset;   /* reset after counter overflow */
-
-       unsigned long   reg_reset_pmds[4]; /* which other counters to reset on overflow */
-       unsigned long   reg_random_seed;   /* seed value when randomization is used */
-       unsigned long   reg_random_mask;   /* bitmask used to limit random value */
-       unsigned long   reg_last_reset_val;/* return: PMD last reset value */
-
-       unsigned long   reg_smpl_pmds[4];  /* which pmds are accessed when PMC overflows */
-       unsigned long   reg_smpl_eventid;  /* opaque sampling event identifier */
-
-       unsigned long   reg_reserved2[3];   /* for future use */
-} pfarg_reg_t;
-
-typedef struct {
-       unsigned int    dbreg_num;              /* which debug register */
-       unsigned short  dbreg_set;              /* event set for this register */
-       unsigned short  dbreg_reserved1;        /* for future use */
-       unsigned long   dbreg_value;            /* value for debug register */
-       unsigned long   dbreg_flags;            /* return: dbreg error */
-       unsigned long   dbreg_reserved2[1];     /* for future use */
-} pfarg_dbreg_t;
-
-typedef struct {
-       unsigned int    ft_version;     /* perfmon: major [16-31], minor [0-15] */
-       unsigned int    ft_reserved;    /* reserved for future use */
-       unsigned long   reserved[4];    /* for future use */
-} pfarg_features_t;
-
-typedef struct {
-       pid_t           load_pid;          /* process to load the context into */
-       unsigned short  load_set;          /* first event set to load */
-       unsigned short  load_reserved1;    /* for future use */
-       unsigned long   load_reserved2[3]; /* for future use */
-} pfarg_load_t;
-
-typedef struct {
-       int             msg_type;               /* generic message header */
-       int             msg_ctx_fd;             /* generic message header */
-       unsigned long   msg_ovfl_pmds[4];       /* which PMDs overflowed */
-       unsigned short  msg_active_set;         /* active set at the time of overflow */
-       unsigned short  msg_reserved1;          /* for future use */
-       unsigned int    msg_reserved2;          /* for future use */
-       unsigned long   msg_tstamp;             /* for perf tuning/debug */
-} pfm_ovfl_msg_t;
-
-typedef struct {
-       int             msg_type;               /* generic message header */
-       int             msg_ctx_fd;             /* generic message header */
-       unsigned long   msg_tstamp;             /* for perf tuning */
-} pfm_end_msg_t;
-
-typedef struct {
-       int             msg_type;               /* type of the message */
-       int             msg_ctx_fd;             /* unique identifier for the context */
-       unsigned long   msg_tstamp;             /* for perf tuning */
-} pfm_gen_msg_t;
-
-#define PFM_MSG_OVFL   1       /* an overflow happened */
-#define PFM_MSG_END    2       /* task to which context was attached ended */
-
-typedef union {
-       pfm_ovfl_msg_t  pfm_ovfl_msg;
-       pfm_end_msg_t   pfm_end_msg;
-       pfm_gen_msg_t   pfm_gen_msg;
-} pfm_msg_t;
-
-/*
- * Define the version numbers for both perfmon as a whole and the sampling buffer format.
- */
-#define PFM_VERSION_MAJ                 2U
-#define PFM_VERSION_MIN                 0U
-#define PFM_VERSION             (((PFM_VERSION_MAJ&0xffff)<<16)|(PFM_VERSION_MIN & 0xffff))
-#define PFM_VERSION_MAJOR(x)    (((x)>>16) & 0xffff)
-#define PFM_VERSION_MINOR(x)    ((x) & 0xffff)
+#include <uapi/asm/perfmon.h>
 
 
-/*
- * miscellaneous architected definitions
- */
-#define PMU_FIRST_COUNTER      4       /* first counting monitor (PMC/PMD) */
-#define PMU_MAX_PMCS           256     /* maximum architected number of PMC registers */
-#define PMU_MAX_PMDS           256     /* maximum architected number of PMD registers */
-
-#ifdef __KERNEL__
-
 extern long perfmonctl(int fd, int cmd, void *arg, int narg);
 
 typedef struct {
@@ -274,6 +107,4 @@ typedef struct {
 extern pfm_sysctl_t pfm_sysctl;
 
 
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_IA64_PERFMON_H */
index 68c98f5b3ca625aaca9f342addd31c68c48c27af..b0e973649cb9f4cfdda26b5178291da9bcd0b2e0 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef _ASM_IA64_PTRACE_H
-#define _ASM_IA64_PTRACE_H
-
 /*
  * Copyright (C) 1998-2004 Hewlett-Packard Co
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  *  6/17/99    D. Mosberger    added second unat member to "struct switch_stack"
  *
  */
-/*
- * When a user process is blocked, its state looks as follows:
- *
- *            +----------------------+ ------- IA64_STK_OFFSET
- *                   |                      |   ^
- *            | struct pt_regs       |  |
- *           |                      |   |
- *            +----------------------+  |
- *           |                      |   |
- *                   |    memory stack      |   |
- *           | (growing downwards)  |   |
- *           //.....................//  |
- *                                      |
- *           //.....................//  |
- *           |                      |   |
- *            +----------------------+  |
- *            | struct switch_stack  |  |
- *           |                      |   |
- *           +----------------------+   |
- *           |                      |   |
- *           //.....................//  |
- *                                      |
- *           //.....................//  |
- *           |                      |   |
- *           |  register stack      |   |
- *           | (growing upwards)    |   |
- *            |                             |   |
- *           +----------------------+   |  --- IA64_RBS_OFFSET
- *            |  struct thread_info  |  |  ^
- *           +----------------------+   |  |
- *           |                      |   |  |
- *            |  struct task_struct  |  |  |
- * current -> |                             |   |  |
- *           +----------------------+ -------
- *
- * Note that ar.ec is not saved explicitly in pt_reg or switch_stack.
- * This is because ar.ec is saved as part of ar.pfs.
- */
-
-
-#include <asm/fpu.h>
+#ifndef _ASM_IA64_PTRACE_H
+#define _ASM_IA64_PTRACE_H
 
-#ifdef __KERNEL__
 #ifndef ASM_OFFSETS_C
 #include <asm/asm-offsets.h>
 #endif
+#include <uapi/asm/ptrace.h>
 
 /*
  * Base-2 logarithm of number of pages to allocate per task structure
 
 #define KERNEL_STACK_SIZE              IA64_STK_OFFSET
 
-#endif /* __KERNEL__ */
-
 #ifndef __ASSEMBLY__
 
-/*
- * This struct defines the way the registers are saved on system
- * calls.
- *
- * We don't save all floating point register because the kernel
- * is compiled to use only a very small subset, so the other are
- * untouched.
- *
- * THIS STRUCTURE MUST BE A MULTIPLE 16-BYTE IN SIZE
- * (because the memory stack pointer MUST ALWAYS be aligned this way)
- *
- */
-struct pt_regs {
-       /* The following registers are saved by SAVE_MIN: */
-       unsigned long b6;               /* scratch */
-       unsigned long b7;               /* scratch */
-
-       unsigned long ar_csd;           /* used by cmp8xchg16 (scratch) */
-       unsigned long ar_ssd;           /* reserved for future use (scratch) */
-
-       unsigned long r8;               /* scratch (return value register 0) */
-       unsigned long r9;               /* scratch (return value register 1) */
-       unsigned long r10;              /* scratch (return value register 2) */
-       unsigned long r11;              /* scratch (return value register 3) */
-
-       unsigned long cr_ipsr;          /* interrupted task's psr */
-       unsigned long cr_iip;           /* interrupted task's instruction pointer */
-       /*
-        * interrupted task's function state; if bit 63 is cleared, it
-        * contains syscall's ar.pfs.pfm:
-        */
-       unsigned long cr_ifs;
-
-       unsigned long ar_unat;          /* interrupted task's NaT register (preserved) */
-       unsigned long ar_pfs;           /* prev function state  */
-       unsigned long ar_rsc;           /* RSE configuration */
-       /* The following two are valid only if cr_ipsr.cpl > 0 || ti->flags & _TIF_MCA_INIT */
-       unsigned long ar_rnat;          /* RSE NaT */
-       unsigned long ar_bspstore;      /* RSE bspstore */
-
-       unsigned long pr;               /* 64 predicate registers (1 bit each) */
-       unsigned long b0;               /* return pointer (bp) */
-       unsigned long loadrs;           /* size of dirty partition << 16 */
-
-       unsigned long r1;               /* the gp pointer */
-       unsigned long r12;              /* interrupted task's memory stack pointer */
-       unsigned long r13;              /* thread pointer */
-
-       unsigned long ar_fpsr;          /* floating point status (preserved) */
-       unsigned long r15;              /* scratch */
-
-       /* The remaining registers are NOT saved for system calls.  */
-
-       unsigned long r14;              /* scratch */
-       unsigned long r2;               /* scratch */
-       unsigned long r3;               /* scratch */
-
-       /* The following registers are saved by SAVE_REST: */
-       unsigned long r16;              /* scratch */
-       unsigned long r17;              /* scratch */
-       unsigned long r18;              /* scratch */
-       unsigned long r19;              /* scratch */
-       unsigned long r20;              /* scratch */
-       unsigned long r21;              /* scratch */
-       unsigned long r22;              /* scratch */
-       unsigned long r23;              /* scratch */
-       unsigned long r24;              /* scratch */
-       unsigned long r25;              /* scratch */
-       unsigned long r26;              /* scratch */
-       unsigned long r27;              /* scratch */
-       unsigned long r28;              /* scratch */
-       unsigned long r29;              /* scratch */
-       unsigned long r30;              /* scratch */
-       unsigned long r31;              /* scratch */
-
-       unsigned long ar_ccv;           /* compare/exchange value (scratch) */
-
-       /*
-        * Floating point registers that the kernel considers scratch:
-        */
-       struct ia64_fpreg f6;           /* scratch */
-       struct ia64_fpreg f7;           /* scratch */
-       struct ia64_fpreg f8;           /* scratch */
-       struct ia64_fpreg f9;           /* scratch */
-       struct ia64_fpreg f10;          /* scratch */
-       struct ia64_fpreg f11;          /* scratch */
-};
-
-/*
- * This structure contains the addition registers that need to
- * preserved across a context switch.  This generally consists of
- * "preserved" registers.
- */
-struct switch_stack {
-       unsigned long caller_unat;      /* user NaT collection register (preserved) */
-       unsigned long ar_fpsr;          /* floating-point status register */
-
-       struct ia64_fpreg f2;           /* preserved */
-       struct ia64_fpreg f3;           /* preserved */
-       struct ia64_fpreg f4;           /* preserved */
-       struct ia64_fpreg f5;           /* preserved */
-
-       struct ia64_fpreg f12;          /* scratch, but untouched by kernel */
-       struct ia64_fpreg f13;          /* scratch, but untouched by kernel */
-       struct ia64_fpreg f14;          /* scratch, but untouched by kernel */
-       struct ia64_fpreg f15;          /* scratch, but untouched by kernel */
-       struct ia64_fpreg f16;          /* preserved */
-       struct ia64_fpreg f17;          /* preserved */
-       struct ia64_fpreg f18;          /* preserved */
-       struct ia64_fpreg f19;          /* preserved */
-       struct ia64_fpreg f20;          /* preserved */
-       struct ia64_fpreg f21;          /* preserved */
-       struct ia64_fpreg f22;          /* preserved */
-       struct ia64_fpreg f23;          /* preserved */
-       struct ia64_fpreg f24;          /* preserved */
-       struct ia64_fpreg f25;          /* preserved */
-       struct ia64_fpreg f26;          /* preserved */
-       struct ia64_fpreg f27;          /* preserved */
-       struct ia64_fpreg f28;          /* preserved */
-       struct ia64_fpreg f29;          /* preserved */
-       struct ia64_fpreg f30;          /* preserved */
-       struct ia64_fpreg f31;          /* preserved */
-
-       unsigned long r4;               /* preserved */
-       unsigned long r5;               /* preserved */
-       unsigned long r6;               /* preserved */
-       unsigned long r7;               /* preserved */
-
-       unsigned long b0;               /* so we can force a direct return in copy_thread */
-       unsigned long b1;
-       unsigned long b2;
-       unsigned long b3;
-       unsigned long b4;
-       unsigned long b5;
-
-       unsigned long ar_pfs;           /* previous function state */
-       unsigned long ar_lc;            /* loop counter (preserved) */
-       unsigned long ar_unat;          /* NaT bits for r4-r7 */
-       unsigned long ar_rnat;          /* RSE NaT collection register */
-       unsigned long ar_bspstore;      /* RSE dirty base (preserved) */
-       unsigned long pr;               /* 64 predicate registers (1 bit each) */
-};
-
-#ifdef __KERNEL__
-
 #include <asm/current.h>
 #include <asm/page.h>
 
@@ -331,46 +142,5 @@ static inline long regs_return_value(struct pt_regs *regs)
   #define arch_has_single_step()  (1)
   #define arch_has_block_step()   (1)
 
-#endif /* !__KERNEL__ */
-
-/* pt_all_user_regs is used for PTRACE_GETREGS PTRACE_SETREGS */
-struct pt_all_user_regs {
-       unsigned long nat;
-       unsigned long cr_iip;
-       unsigned long cfm;
-       unsigned long cr_ipsr;
-       unsigned long pr;
-
-       unsigned long gr[32];
-       unsigned long br[8];
-       unsigned long ar[128];
-       struct ia64_fpreg fr[128];
-};
-
 #endif /* !__ASSEMBLY__ */
-
-/* indices to application-registers array in pt_all_user_regs */
-#define PT_AUR_RSC     16
-#define PT_AUR_BSP     17
-#define PT_AUR_BSPSTORE        18
-#define PT_AUR_RNAT    19
-#define PT_AUR_CCV     32
-#define PT_AUR_UNAT    36
-#define PT_AUR_FPSR    40
-#define PT_AUR_PFS     64
-#define PT_AUR_LC      65
-#define PT_AUR_EC      66
-
-/*
- * The numbers chosen here are somewhat arbitrary but absolutely MUST
- * not overlap with any of the number assigned in <linux/ptrace.h>.
- */
-#define PTRACE_SINGLEBLOCK     12      /* resume execution until next branch */
-#define PTRACE_OLD_GETSIGINFO  13      /* (replaced by PTRACE_GETSIGINFO in <linux/ptrace.h>)  */
-#define PTRACE_OLD_SETSIGINFO  14      /* (replaced by PTRACE_SETSIGINFO in <linux/ptrace.h>)  */
-#define PTRACE_GETREGS         18      /* get all registers (pt_all_user_regs) in one shot */
-#define PTRACE_SETREGS         19      /* set all registers (pt_all_user_regs) in one shot */
-
-#define PTRACE_OLDSETOPTIONS   21
-
 #endif /* _ASM_IA64_PTRACE_H */
index c8fcaa2ac48f88f13bd93e1d25fd3fd5d2031c6a..6f2e2dd0f28fddc5fe73a0ea3fbaec4f7021cccd 100644 (file)
-#ifndef _ASM_IA64_SIGINFO_H
-#define _ASM_IA64_SIGINFO_H
-
 /*
  * Based on <asm-i386/siginfo.h>.
  *
  * Modified 1998-2002
  *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
+#ifndef _ASM_IA64_SIGINFO_H
+#define _ASM_IA64_SIGINFO_H
 
-#define __ARCH_SI_PREAMBLE_SIZE        (4 * sizeof(int))
-
-#define HAVE_ARCH_SIGINFO_T
-#define HAVE_ARCH_COPY_SIGINFO
-#define HAVE_ARCH_COPY_SIGINFO_TO_USER
-
-#include <asm-generic/siginfo.h>
-
-typedef struct siginfo {
-       int si_signo;
-       int si_errno;
-       int si_code;
-       int __pad0;
-
-       union {
-               int _pad[SI_PAD_SIZE];
-
-               /* kill() */
-               struct {
-                       pid_t _pid;             /* sender's pid */
-                       uid_t _uid;             /* sender's uid */
-               } _kill;
-
-               /* POSIX.1b timers */
-               struct {
-                       timer_t _tid;           /* timer id */
-                       int _overrun;           /* overrun count */
-                       char _pad[sizeof(__ARCH_SI_UID_T) - sizeof(int)];
-                       sigval_t _sigval;       /* must overlay ._rt._sigval! */
-                       int _sys_private;       /* not to be passed to user */
-               } _timer;
-
-               /* POSIX.1b signals */
-               struct {
-                       pid_t _pid;             /* sender's pid */
-                       uid_t _uid;             /* sender's uid */
-                       sigval_t _sigval;
-               } _rt;
-
-               /* SIGCHLD */
-               struct {
-                       pid_t _pid;             /* which child */
-                       uid_t _uid;             /* sender's uid */
-                       int _status;            /* exit code */
-                       clock_t _utime;
-                       clock_t _stime;
-               } _sigchld;
-
-               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
-               struct {
-                       void __user *_addr;     /* faulting insn/memory ref. */
-                       int _imm;               /* immediate value for "break" */
-                       unsigned int _flags;    /* see below */
-                       unsigned long _isr;     /* isr */
-                       short _addr_lsb;        /* lsb of faulting address */
-               } _sigfault;
-
-               /* SIGPOLL */
-               struct {
-                       long _band;     /* POLL_IN, POLL_OUT, POLL_MSG (XPG requires a "long") */
-                       int _fd;
-               } _sigpoll;
-       } _sifields;
-} siginfo_t;
-
-#define si_imm         _sifields._sigfault._imm        /* as per UNIX SysV ABI spec */
-#define si_flags       _sifields._sigfault._flags
-/*
- * si_isr is valid for SIGILL, SIGFPE, SIGSEGV, SIGBUS, and SIGTRAP provided that
- * si_code is non-zero and __ISR_VALID is set in si_flags.
- */
-#define si_isr         _sifields._sigfault._isr
-
-/*
- * Flag values for si_flags:
- */
-#define __ISR_VALID_BIT        0
-#define __ISR_VALID    (1 << __ISR_VALID_BIT)
-
-/*
- * SIGILL si_codes
- */
-#define ILL_BADIADDR   (__SI_FAULT|9)  /* unimplemented instruction address */
-#define __ILL_BREAK    (__SI_FAULT|10) /* illegal break */
-#define __ILL_BNDMOD   (__SI_FAULT|11) /* bundle-update (modification) in progress */
-#undef NSIGILL
-#define NSIGILL                11
-
-/*
- * SIGFPE si_codes
- */
-#define __FPE_DECOVF   (__SI_FAULT|9)  /* decimal overflow */
-#define __FPE_DECDIV   (__SI_FAULT|10) /* decimal division by zero */
-#define __FPE_DECERR   (__SI_FAULT|11) /* packed decimal error */
-#define __FPE_INVASC   (__SI_FAULT|12) /* invalid ASCII digit */
-#define __FPE_INVDEC   (__SI_FAULT|13) /* invalid decimal digit */
-#undef NSIGFPE
-#define NSIGFPE                13
-
-/*
- * SIGSEGV si_codes
- */
-#define __SEGV_PSTKOVF (__SI_FAULT|3)  /* paragraph stack overflow */
-#undef NSIGSEGV
-#define NSIGSEGV       3
-
-#undef NSIGTRAP
-#define NSIGTRAP       4
-
-#ifdef __KERNEL__
 #include <linux/string.h>
+#include <uapi/asm/siginfo.h>
 
 static inline void
 copy_siginfo (siginfo_t *to, siginfo_t *from)
@@ -130,6 +20,4 @@ copy_siginfo (siginfo_t *to, siginfo_t *from)
                memcpy(to, from, 4*sizeof(int) + sizeof(from->_sifields._sigchld));
 }
 
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_IA64_SIGINFO_H */
index b166248d49a46b884b425dd530b4dd5fd0d96ad9..aecda5b9eb4ece83e867bdcdceadef56dfaf7de1 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef _ASM_IA64_SIGNAL_H
-#define _ASM_IA64_SIGNAL_H
-
 /*
  * Modified 1998-2001, 2003
  *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  * Unfortunately, this file is being included by bits/signal.h in
  * glibc-2.x.  Hence the #ifdef __KERNEL__ ugliness.
  */
+#ifndef _ASM_IA64_SIGNAL_H
+#define _ASM_IA64_SIGNAL_H
 
-#define SIGHUP          1
-#define SIGINT          2
-#define SIGQUIT                 3
-#define SIGILL          4
-#define SIGTRAP                 5
-#define SIGABRT                 6
-#define SIGIOT          6
-#define SIGBUS          7
-#define SIGFPE          8
-#define SIGKILL                 9
-#define SIGUSR1                10
-#define SIGSEGV                11
-#define SIGUSR2                12
-#define SIGPIPE                13
-#define SIGALRM                14
-#define SIGTERM                15
-#define SIGSTKFLT      16
-#define SIGCHLD                17
-#define SIGCONT                18
-#define SIGSTOP                19
-#define SIGTSTP                20
-#define SIGTTIN                21
-#define SIGTTOU                22
-#define SIGURG         23
-#define SIGXCPU                24
-#define SIGXFSZ                25
-#define SIGVTALRM      26
-#define SIGPROF                27
-#define SIGWINCH       28
-#define SIGIO          29
-#define SIGPOLL                SIGIO
-/*
-#define SIGLOST                29
-*/
-#define SIGPWR         30
-#define SIGSYS         31
-/* signal 31 is no longer "unused", but the SIGUNUSED macro remains for backwards compatibility */
-#define        SIGUNUSED       31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN       32
-#define SIGRTMAX       _NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP   0x00000001
-#define SA_NOCLDWAIT   0x00000002
-#define SA_SIGINFO     0x00000004
-#define SA_ONSTACK     0x08000000
-#define SA_RESTART     0x10000000
-#define SA_NODEFER     0x40000000
-#define SA_RESETHAND   0x80000000
-
-#define SA_NOMASK      SA_NODEFER
-#define SA_ONESHOT     SA_RESETHAND
-
-#define SA_RESTORER    0x04000000
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
-/*
- * The minimum stack size needs to be fairly large because we want to
- * be sure that an app compiled for today's CPUs will continue to run
- * on all future CPU models.  The CPU model matters because the signal
- * frame needs to have space for the complete machine state, including
- * all physical stacked registers.  The number of physical stacked
- * registers is CPU model dependent, but given that the width of
- * ar.rsc.loadrs is 14 bits, we can assume that they'll never take up
- * more than 16KB of space.
- */
-#if 1
-  /*
-   * This is a stupid typo: the value was _meant_ to be 131072 (0x20000), but I typed it
-   * in wrong. ;-(  To preserve backwards compatibility, we leave the kernel at the
-   * incorrect value and fix libc only.
-   */
-# define MINSIGSTKSZ   131027  /* min. stack size for sigaltstack() */
-#else
-# define MINSIGSTKSZ   131072  /* min. stack size for sigaltstack() */
-#endif
-#define SIGSTKSZ       262144  /* default stack size for sigaltstack() */
+#include <uapi/asm/signal.h>
 
-#ifdef __KERNEL__
 
 #define _NSIG          64
 #define _NSIG_BPW      64
 #define _NSIG_WORDS    (_NSIG / _NSIG_BPW)
 
-#endif /* __KERNEL__ */
-
-#include <asm-generic/signal-defs.h>
-
 # ifndef __ASSEMBLY__
 
-#  include <linux/types.h>
-
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-typedef struct sigaltstack {
-       void __user *ss_sp;
-       int ss_flags;
-       size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
-
 /* Most things should be clean enough to redefine this at will, if care
    is taken to make libc match.  */
 
@@ -154,7 +40,5 @@ struct k_sigaction {
 
 #define ptrace_signal_deliver(regs, cookie) do { } while (0)
 
-#endif /* __KERNEL__ */
-
 # endif /* !__ASSEMBLY__ */
 #endif /* _ASM_IA64_SIGNAL_H */
index 689d218c0c285c4d0be89fa216882e8bd78a34bd..a42f870ca4f6cc7770ae25811639d066b1382ae4 100644 (file)
@@ -1,52 +1,14 @@
-#ifndef _ASM_IA64_TERMIOS_H
-#define _ASM_IA64_TERMIOS_H
-
 /*
  * Modified 1999
  *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  *
  * 99/01/28    Added N_IRDA and N_SMSBLOCK
  */
+#ifndef _ASM_IA64_TERMIOS_H
+#define _ASM_IA64_TERMIOS_H
 
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-
-struct winsize {
-       unsigned short ws_row;
-       unsigned short ws_col;
-       unsigned short ws_xpixel;
-       unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-       unsigned short c_iflag;         /* input mode flags */
-       unsigned short c_oflag;         /* output mode flags */
-       unsigned short c_cflag;         /* control mode flags */
-       unsigned short c_lflag;         /* local mode flags */
-       unsigned char c_line;           /* line discipline */
-       unsigned char c_cc[NCC];        /* control characters */
-};
-
-/* modem lines */
-#define TIOCM_LE       0x001
-#define TIOCM_DTR      0x002
-#define TIOCM_RTS      0x004
-#define TIOCM_ST       0x008
-#define TIOCM_SR       0x010
-#define TIOCM_CTS      0x020
-#define TIOCM_CAR      0x040
-#define TIOCM_RNG      0x080
-#define TIOCM_DSR      0x100
-#define TIOCM_CD       TIOCM_CAR
-#define TIOCM_RI       TIOCM_RNG
-#define TIOCM_OUT1     0x2000
-#define TIOCM_OUT2     0x4000
-#define TIOCM_LOOP     0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+#include <uapi/asm/termios.h>
 
-# ifdef __KERNEL__
 
 /*     intr=^C         quit=^\         erase=del       kill=^U
        eof=^D          vtime=\0        vmin=\1         sxtc=\0
@@ -92,6 +54,4 @@ struct termio {
 #define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
 #define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
-# endif /* __KERNEL__ */
-
 #endif /* _ASM_IA64_TERMIOS_H */
index f7ee85378311a0f2d241a458640f697b4940a2a1..ff2ae41365840a616b4a7b6211aed1b2678c6e0a 100644 (file)
@@ -106,7 +106,6 @@ struct thread_info {
 #define TIF_SYSCALL_AUDIT      3       /* syscall auditing active */
 #define TIF_SINGLESTEP         4       /* restore singlestep on return to user mode */
 #define TIF_NOTIFY_RESUME      6       /* resumption notification requested */
-#define TIF_POLLING_NRFLAG     16      /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE             17      /* is terminating due to OOM killer */
 #define TIF_MCA_INIT           18      /* this task is processing MCA or INIT */
 #define TIF_DB_DISABLED                19      /* debug trap disabled for fsyscall */
@@ -119,7 +118,6 @@ struct thread_info {
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
 #define _TIF_MCA_INIT          (1 << TIF_MCA_INIT)
 #define _TIF_DB_DISABLED       (1 << TIF_DB_DISABLED)
 #define _TIF_RESTORE_RSE       (1 << TIF_RESTORE_RSE)
index 3f5b122d9975161ea01ab1b8fa3833ac98944bd2..4c351b169da2a48532ce7e5719757c7679fdfaaf 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef _ASM_IA64_TYPES_H
-#define _ASM_IA64_TYPES_H
-
 /*
  * This file is never included by application software unless explicitly
  * requested (e.g., via linux/types.h) in which case the application is
  * Modified 1998-2000, 2002
  *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
+#ifndef _ASM_IA64_TYPES_H
+#define _ASM_IA64_TYPES_H
 
-#ifdef __KERNEL__
 #include <asm-generic/int-ll64.h>
-#else
-#include <asm-generic/int-l64.h>
-#endif
+#include <uapi/asm/types.h>
 
 #ifdef __ASSEMBLY__
-# define __IA64_UL(x)          (x)
-# define __IA64_UL_CONST(x)    x
-
 #else
-# define __IA64_UL(x)          ((unsigned long)(x))
-# define __IA64_UL_CONST(x)    x##UL
-
 /*
  * These aren't exported outside the kernel to avoid name space clashes
  */
-# ifdef __KERNEL__
 
 struct fnptr {
        unsigned long ip;
        unsigned long gp;
 };
 
-# endif /* __KERNEL__ */
 #endif /* !__ASSEMBLY__ */
-
 #endif /* _ASM_IA64_TYPES_H */
index 7a3bd252494468dcc5f4da779a62fc4500d65805..8b3ff2f5b86167eda40544dbda0099c568eaaf0e 100644 (file)
-#ifndef _ASM_IA64_UNISTD_H
-#define _ASM_IA64_UNISTD_H
-
 /*
  * IA-64 Linux syscall numbers and inline-functions.
  *
  * Copyright (C) 1998-2005 Hewlett-Packard Co
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
+#ifndef _ASM_IA64_UNISTD_H
+#define _ASM_IA64_UNISTD_H
 
-#include <asm/break.h>
-
-#define __BREAK_SYSCALL                        __IA64_BREAK_SYSCALL
-
-#define __NR_ni_syscall                        1024
-#define __NR_exit                      1025
-#define __NR_read                      1026
-#define __NR_write                     1027
-#define __NR_open                      1028
-#define __NR_close                     1029
-#define __NR_creat                     1030
-#define __NR_link                      1031
-#define __NR_unlink                    1032
-#define __NR_execve                    1033
-#define __NR_chdir                     1034
-#define __NR_fchdir                    1035
-#define __NR_utimes                    1036
-#define __NR_mknod                     1037
-#define __NR_chmod                     1038
-#define __NR_chown                     1039
-#define __NR_lseek                     1040
-#define __NR_getpid                    1041
-#define __NR_getppid                   1042
-#define __NR_mount                     1043
-#define __NR_umount                    1044
-#define __NR_setuid                    1045
-#define __NR_getuid                    1046
-#define __NR_geteuid                   1047
-#define __NR_ptrace                    1048
-#define __NR_access                    1049
-#define __NR_sync                      1050
-#define __NR_fsync                     1051
-#define __NR_fdatasync                 1052
-#define __NR_kill                      1053
-#define __NR_rename                    1054
-#define __NR_mkdir                     1055
-#define __NR_rmdir                     1056
-#define __NR_dup                       1057
-#define __NR_pipe                      1058
-#define __NR_times                     1059
-#define __NR_brk                       1060
-#define __NR_setgid                    1061
-#define __NR_getgid                    1062
-#define __NR_getegid                   1063
-#define __NR_acct                      1064
-#define __NR_ioctl                     1065
-#define __NR_fcntl                     1066
-#define __NR_umask                     1067
-#define __NR_chroot                    1068
-#define __NR_ustat                     1069
-#define __NR_dup2                      1070
-#define __NR_setreuid                  1071
-#define __NR_setregid                  1072
-#define __NR_getresuid                 1073
-#define __NR_setresuid                 1074
-#define __NR_getresgid                 1075
-#define __NR_setresgid                 1076
-#define __NR_getgroups                 1077
-#define __NR_setgroups                 1078
-#define __NR_getpgid                   1079
-#define __NR_setpgid                   1080
-#define __NR_setsid                    1081
-#define __NR_getsid                    1082
-#define __NR_sethostname               1083
-#define __NR_setrlimit                 1084
-#define __NR_getrlimit                 1085
-#define __NR_getrusage                 1086
-#define __NR_gettimeofday              1087
-#define __NR_settimeofday              1088
-#define __NR_select                    1089
-#define __NR_poll                      1090
-#define __NR_symlink                   1091
-#define __NR_readlink                  1092
-#define __NR_uselib                    1093
-#define __NR_swapon                    1094
-#define __NR_swapoff                   1095
-#define __NR_reboot                    1096
-#define __NR_truncate                  1097
-#define __NR_ftruncate                 1098
-#define __NR_fchmod                    1099
-#define __NR_fchown                    1100
-#define __NR_getpriority               1101
-#define __NR_setpriority               1102
-#define __NR_statfs                    1103
-#define __NR_fstatfs                   1104
-#define __NR_gettid                    1105
-#define __NR_semget                    1106
-#define __NR_semop                     1107
-#define __NR_semctl                    1108
-#define __NR_msgget                    1109
-#define __NR_msgsnd                    1110
-#define __NR_msgrcv                    1111
-#define __NR_msgctl                    1112
-#define __NR_shmget                    1113
-#define __NR_shmat                     1114
-#define __NR_shmdt                     1115
-#define __NR_shmctl                    1116
-/* also known as klogctl() in GNU libc: */
-#define __NR_syslog                    1117
-#define __NR_setitimer                 1118
-#define __NR_getitimer                 1119
-/* 1120 was __NR_old_stat */
-/* 1121 was __NR_old_lstat */
-/* 1122 was __NR_old_fstat */
-#define __NR_vhangup                   1123
-#define __NR_lchown                    1124
-#define __NR_remap_file_pages          1125
-#define __NR_wait4                     1126
-#define __NR_sysinfo                   1127
-#define __NR_clone                     1128
-#define __NR_setdomainname             1129
-#define __NR_uname                     1130
-#define __NR_adjtimex                  1131
-/* 1132 was __NR_create_module */
-#define __NR_init_module               1133
-#define __NR_delete_module             1134
-/* 1135 was __NR_get_kernel_syms */
-/* 1136 was __NR_query_module */
-#define __NR_quotactl                  1137
-#define __NR_bdflush                   1138
-#define __NR_sysfs                     1139
-#define __NR_personality               1140
-#define __NR_afs_syscall               1141
-#define __NR_setfsuid                  1142
-#define __NR_setfsgid                  1143
-#define __NR_getdents                  1144
-#define __NR_flock                     1145
-#define __NR_readv                     1146
-#define __NR_writev                    1147
-#define __NR_pread64                   1148
-#define __NR_pwrite64                  1149
-#define __NR__sysctl                   1150
-#define __NR_mmap                      1151
-#define __NR_munmap                    1152
-#define __NR_mlock                     1153
-#define __NR_mlockall                  1154
-#define __NR_mprotect                  1155
-#define __NR_mremap                    1156
-#define __NR_msync                     1157
-#define __NR_munlock                   1158
-#define __NR_munlockall                        1159
-#define __NR_sched_getparam            1160
-#define __NR_sched_setparam            1161
-#define __NR_sched_getscheduler                1162
-#define __NR_sched_setscheduler                1163
-#define __NR_sched_yield               1164
-#define __NR_sched_get_priority_max    1165
-#define __NR_sched_get_priority_min    1166
-#define __NR_sched_rr_get_interval     1167
-#define __NR_nanosleep                 1168
-#define __NR_nfsservctl                        1169
-#define __NR_prctl                     1170
-/* 1171 is reserved for backwards compatibility with old __NR_getpagesize */
-#define __NR_mmap2                     1172
-#define __NR_pciconfig_read            1173
-#define __NR_pciconfig_write           1174
-#define __NR_perfmonctl                        1175
-#define __NR_sigaltstack               1176
-#define __NR_rt_sigaction              1177
-#define __NR_rt_sigpending             1178
-#define __NR_rt_sigprocmask            1179
-#define __NR_rt_sigqueueinfo           1180
-#define __NR_rt_sigreturn              1181
-#define __NR_rt_sigsuspend             1182
-#define __NR_rt_sigtimedwait           1183
-#define __NR_getcwd                    1184
-#define __NR_capget                    1185
-#define __NR_capset                    1186
-#define __NR_sendfile                  1187
-#define __NR_getpmsg                   1188
-#define __NR_putpmsg                   1189
-#define __NR_socket                    1190
-#define __NR_bind                      1191
-#define __NR_connect                   1192
-#define __NR_listen                    1193
-#define __NR_accept                    1194
-#define __NR_getsockname               1195
-#define __NR_getpeername               1196
-#define __NR_socketpair                        1197
-#define __NR_send                      1198
-#define __NR_sendto                    1199
-#define __NR_recv                      1200
-#define __NR_recvfrom                  1201
-#define __NR_shutdown                  1202
-#define __NR_setsockopt                        1203
-#define __NR_getsockopt                        1204
-#define __NR_sendmsg                   1205
-#define __NR_recvmsg                   1206
-#define __NR_pivot_root                        1207
-#define __NR_mincore                   1208
-#define __NR_madvise                   1209
-#define __NR_stat                      1210
-#define __NR_lstat                     1211
-#define __NR_fstat                     1212
-#define __NR_clone2                    1213
-#define __NR_getdents64                        1214
-#define __NR_getunwind                 1215
-#define __NR_readahead                 1216
-#define __NR_setxattr                  1217
-#define __NR_lsetxattr                 1218
-#define __NR_fsetxattr                 1219
-#define __NR_getxattr                  1220
-#define __NR_lgetxattr                 1221
-#define __NR_fgetxattr                 1222
-#define __NR_listxattr                 1223
-#define __NR_llistxattr                        1224
-#define __NR_flistxattr                        1225
-#define __NR_removexattr               1226
-#define __NR_lremovexattr              1227
-#define __NR_fremovexattr              1228
-#define __NR_tkill                     1229
-#define __NR_futex                     1230
-#define __NR_sched_setaffinity         1231
-#define __NR_sched_getaffinity         1232
-#define __NR_set_tid_address           1233
-#define __NR_fadvise64                 1234
-#define __NR_tgkill                    1235
-#define __NR_exit_group                        1236
-#define __NR_lookup_dcookie            1237
-#define __NR_io_setup                  1238
-#define __NR_io_destroy                        1239
-#define __NR_io_getevents              1240
-#define __NR_io_submit                 1241
-#define __NR_io_cancel                 1242
-#define __NR_epoll_create              1243
-#define __NR_epoll_ctl                 1244
-#define __NR_epoll_wait                        1245
-#define __NR_restart_syscall           1246
-#define __NR_semtimedop                        1247
-#define __NR_timer_create              1248
-#define __NR_timer_settime             1249
-#define __NR_timer_gettime             1250
-#define __NR_timer_getoverrun          1251
-#define __NR_timer_delete              1252
-#define __NR_clock_settime             1253
-#define __NR_clock_gettime             1254
-#define __NR_clock_getres              1255
-#define __NR_clock_nanosleep           1256
-#define __NR_fstatfs64                 1257
-#define __NR_statfs64                  1258
-#define __NR_mbind                     1259
-#define __NR_get_mempolicy             1260
-#define __NR_set_mempolicy             1261
-#define __NR_mq_open                   1262
-#define __NR_mq_unlink                 1263
-#define __NR_mq_timedsend              1264
-#define __NR_mq_timedreceive           1265
-#define __NR_mq_notify                 1266
-#define __NR_mq_getsetattr             1267
-#define __NR_kexec_load                        1268
-#define __NR_vserver                   1269
-#define __NR_waitid                    1270
-#define __NR_add_key                   1271
-#define __NR_request_key               1272
-#define __NR_keyctl                    1273
-#define __NR_ioprio_set                        1274
-#define __NR_ioprio_get                        1275
-#define __NR_move_pages                        1276
-#define __NR_inotify_init              1277
-#define __NR_inotify_add_watch         1278
-#define __NR_inotify_rm_watch          1279
-#define __NR_migrate_pages             1280
-#define __NR_openat                    1281
-#define __NR_mkdirat                   1282
-#define __NR_mknodat                   1283
-#define __NR_fchownat                  1284
-#define __NR_futimesat                 1285
-#define __NR_newfstatat                        1286
-#define __NR_unlinkat                  1287
-#define __NR_renameat                  1288
-#define __NR_linkat                    1289
-#define __NR_symlinkat                 1290
-#define __NR_readlinkat                        1291
-#define __NR_fchmodat                  1292
-#define __NR_faccessat                 1293
-#define __NR_pselect6                  1294
-#define __NR_ppoll                     1295
-#define __NR_unshare                   1296
-#define __NR_splice                    1297
-#define __NR_set_robust_list           1298
-#define __NR_get_robust_list           1299
-#define __NR_sync_file_range           1300
-#define __NR_tee                       1301
-#define __NR_vmsplice                  1302
-#define __NR_fallocate                 1303
-#define __NR_getcpu                    1304
-#define __NR_epoll_pwait               1305
-#define __NR_utimensat                 1306
-#define __NR_signalfd                  1307
-#define __NR_timerfd                   1308
-#define __NR_eventfd                   1309
-#define __NR_timerfd_create            1310
-#define __NR_timerfd_settime           1311
-#define __NR_timerfd_gettime           1312
-#define __NR_signalfd4                 1313
-#define __NR_eventfd2                  1314
-#define __NR_epoll_create1             1315
-#define __NR_dup3                      1316
-#define __NR_pipe2                     1317
-#define __NR_inotify_init1             1318
-#define __NR_preadv                    1319
-#define __NR_pwritev                   1320
-#define __NR_rt_tgsigqueueinfo         1321
-#define __NR_recvmmsg                  1322
-#define __NR_fanotify_init             1323
-#define __NR_fanotify_mark             1324
-#define __NR_prlimit64                 1325
-#define __NR_name_to_handle_at         1326
-#define __NR_open_by_handle_at         1327
-#define __NR_clock_adjtime             1328
-#define __NR_syncfs                    1329
-#define __NR_setns                     1330
-#define __NR_sendmmsg                  1331
-#define __NR_process_vm_readv          1332
-#define __NR_process_vm_writev         1333
-#define __NR_accept4                   1334
+#include <uapi/asm/unistd.h>
 
-#ifdef __KERNEL__
 
 
 #define NR_syscalls                    311 /* length of syscall table */
@@ -382,5 +65,4 @@ asmlinkage long sys_rt_sigaction(int sig,
 #define cond_syscall(x) asmlinkage long x (void) __attribute__((weak,alias("sys_ni_syscall")))
 
 #endif /* !__ASSEMBLY__ */
-#endif /* __KERNEL__ */
 #endif /* _ASM_IA64_UNISTD_H */
index 504167c35b8be550d06d72f44c281ec11d434d64..b275401b96d344bccdce2dc192a15baa2639fa92 100644 (file)
@@ -1,20 +1,11 @@
 #ifndef _ASM_IA64_USTACK_H
 #define _ASM_IA64_USTACK_H
 
-/*
- * Constants for the user stack size
- */
-
-#ifdef __KERNEL__
 #include <asm/page.h>
+#include <uapi/asm/ustack.h>
 
 /* The absolute hard limit for stack size is 1/2 of the mappable space in the region */
 #define MAX_USER_STACK_SIZE    (RGN_MAP_LIMIT/2)
 #define STACK_TOP              (0x6000000000000000UL + RGN_MAP_LIMIT)
 #define STACK_TOP_MAX          STACK_TOP
-#endif
-
-/* Make a default stack size of 2GiB */
-#define DEFAULT_USER_STACK_SIZE        (1UL << 31)
-
 #endif /* _ASM_IA64_USTACK_H */
index baebb3da1d44160fc6f6f259886656e6f494b167..30cafac937030ab7f174252949a05948a153b0ef 100644 (file)
@@ -1,3 +1,48 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += auxvec.h
+header-y += bitsperlong.h
+header-y += break.h
+header-y += byteorder.h
+header-y += cmpxchg.h
+header-y += errno.h
+header-y += fcntl.h
+header-y += fpu.h
+header-y += gcc_intrin.h
+header-y += ia64regs.h
+header-y += intel_intrin.h
+header-y += intrinsics.h
+header-y += ioctl.h
+header-y += ioctls.h
+header-y += ipcbuf.h
+header-y += kvm.h
+header-y += kvm_para.h
+header-y += mman.h
+header-y += msgbuf.h
+header-y += param.h
+header-y += perfmon.h
+header-y += perfmon_default_smpl.h
+header-y += poll.h
+header-y += posix_types.h
+header-y += ptrace.h
+header-y += ptrace_offsets.h
+header-y += resource.h
+header-y += rse.h
+header-y += sembuf.h
+header-y += setup.h
+header-y += shmbuf.h
+header-y += sigcontext.h
+header-y += siginfo.h
+header-y += signal.h
+header-y += socket.h
+header-y += sockios.h
+header-y += stat.h
+header-y += statfs.h
+header-y += swab.h
+header-y += termbits.h
+header-y += termios.h
+header-y += types.h
+header-y += ucontext.h
+header-y += unistd.h
+header-y += ustack.h
diff --git a/arch/ia64/include/uapi/asm/gcc_intrin.h b/arch/ia64/include/uapi/asm/gcc_intrin.h
new file mode 100644 (file)
index 0000000..61d0d01
--- /dev/null
@@ -0,0 +1,618 @@
+/*
+ *
+ * Copyright (C) 2002,2003 Jun Nakajima <jun.nakajima@intel.com>
+ * Copyright (C) 2002,2003 Suresh Siddha <suresh.b.siddha@intel.com>
+ */
+#ifndef _UAPI_ASM_IA64_GCC_INTRIN_H
+#define _UAPI_ASM_IA64_GCC_INTRIN_H
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+/* define this macro to get some asm stmts included in 'c' files */
+#define ASM_SUPPORTED
+
+/* Optimization barrier */
+/* The "volatile" is due to gcc bugs */
+#define ia64_barrier() asm volatile ("":::"memory")
+
+#define ia64_stop()    asm volatile (";;"::)
+
+#define ia64_invala_gr(regnum) asm volatile ("invala.e r%0" :: "i"(regnum))
+
+#define ia64_invala_fr(regnum) asm volatile ("invala.e f%0" :: "i"(regnum))
+
+#define ia64_flushrs() asm volatile ("flushrs;;":::"memory")
+
+#define ia64_loadrs() asm volatile ("loadrs;;":::"memory")
+
+extern void ia64_bad_param_for_setreg (void);
+extern void ia64_bad_param_for_getreg (void);
+
+
+#define ia64_native_setreg(regnum, val)                                                \
+({                                                                             \
+       switch (regnum) {                                                       \
+           case _IA64_REG_PSR_L:                                               \
+                   asm volatile ("mov psr.l=%0" :: "r"(val) : "memory");       \
+                   break;                                                      \
+           case _IA64_REG_AR_KR0 ... _IA64_REG_AR_EC:                          \
+                   asm volatile ("mov ar%0=%1" ::                              \
+                                         "i" (regnum - _IA64_REG_AR_KR0),      \
+                                         "r"(val): "memory");                  \
+                   break;                                                      \
+           case _IA64_REG_CR_DCR ... _IA64_REG_CR_LRR1:                        \
+                   asm volatile ("mov cr%0=%1" ::                              \
+                                         "i" (regnum - _IA64_REG_CR_DCR),      \
+                                         "r"(val): "memory" );                 \
+                   break;                                                      \
+           case _IA64_REG_SP:                                                  \
+                   asm volatile ("mov r12=%0" ::                               \
+                                         "r"(val): "memory");                  \
+                   break;                                                      \
+           case _IA64_REG_GP:                                                  \
+                   asm volatile ("mov gp=%0" :: "r"(val) : "memory");          \
+               break;                                                          \
+           default:                                                            \
+                   ia64_bad_param_for_setreg();                                \
+                   break;                                                      \
+       }                                                                       \
+})
+
+#define ia64_native_getreg(regnum)                                             \
+({                                                                             \
+       __u64 ia64_intri_res;                                                   \
+                                                                               \
+       switch (regnum) {                                                       \
+       case _IA64_REG_GP:                                                      \
+               asm volatile ("mov %0=gp" : "=r"(ia64_intri_res));              \
+               break;                                                          \
+       case _IA64_REG_IP:                                                      \
+               asm volatile ("mov %0=ip" : "=r"(ia64_intri_res));              \
+               break;                                                          \
+       case _IA64_REG_PSR:                                                     \
+               asm volatile ("mov %0=psr" : "=r"(ia64_intri_res));             \
+               break;                                                          \
+       case _IA64_REG_TP:      /* for current() */                             \
+               ia64_intri_res = ia64_r13;                                      \
+               break;                                                          \
+       case _IA64_REG_AR_KR0 ... _IA64_REG_AR_EC:                              \
+               asm volatile ("mov %0=ar%1" : "=r" (ia64_intri_res)             \
+                                     : "i"(regnum - _IA64_REG_AR_KR0));        \
+               break;                                                          \
+       case _IA64_REG_CR_DCR ... _IA64_REG_CR_LRR1:                            \
+               asm volatile ("mov %0=cr%1" : "=r" (ia64_intri_res)             \
+                                     : "i" (regnum - _IA64_REG_CR_DCR));       \
+               break;                                                          \
+       case _IA64_REG_SP:                                                      \
+               asm volatile ("mov %0=sp" : "=r" (ia64_intri_res));             \
+               break;                                                          \
+       default:                                                                \
+               ia64_bad_param_for_getreg();                                    \
+               break;                                                          \
+       }                                                                       \
+       ia64_intri_res;                                                         \
+})
+
+#define ia64_hint_pause 0
+
+#define ia64_hint(mode)                                                \
+({                                                             \
+       switch (mode) {                                         \
+       case ia64_hint_pause:                                   \
+               asm volatile ("hint @pause" ::: "memory");      \
+               break;                                          \
+       }                                                       \
+})
+
+
+/* Integer values for mux1 instruction */
+#define ia64_mux1_brcst 0
+#define ia64_mux1_mix   8
+#define ia64_mux1_shuf  9
+#define ia64_mux1_alt  10
+#define ia64_mux1_rev  11
+
+#define ia64_mux1(x, mode)                                                     \
+({                                                                             \
+       __u64 ia64_intri_res;                                                   \
+                                                                               \
+       switch (mode) {                                                         \
+       case ia64_mux1_brcst:                                                   \
+               asm ("mux1 %0=%1,@brcst" : "=r" (ia64_intri_res) : "r" (x));    \
+               break;                                                          \
+       case ia64_mux1_mix:                                                     \
+               asm ("mux1 %0=%1,@mix" : "=r" (ia64_intri_res) : "r" (x));      \
+               break;                                                          \
+       case ia64_mux1_shuf:                                                    \
+               asm ("mux1 %0=%1,@shuf" : "=r" (ia64_intri_res) : "r" (x));     \
+               break;                                                          \
+       case ia64_mux1_alt:                                                     \
+               asm ("mux1 %0=%1,@alt" : "=r" (ia64_intri_res) : "r" (x));      \
+               break;                                                          \
+       case ia64_mux1_rev:                                                     \
+               asm ("mux1 %0=%1,@rev" : "=r" (ia64_intri_res) : "r" (x));      \
+               break;                                                          \
+       }                                                                       \
+       ia64_intri_res;                                                         \
+})
+
+#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+# define ia64_popcnt(x)                __builtin_popcountl(x)
+#else
+# define ia64_popcnt(x)                                                \
+  ({                                                           \
+       __u64 ia64_intri_res;                                   \
+       asm ("popcnt %0=%1" : "=r" (ia64_intri_res) : "r" (x)); \
+                                                               \
+       ia64_intri_res;                                         \
+  })
+#endif
+
+#define ia64_getf_exp(x)                                       \
+({                                                             \
+       long ia64_intri_res;                                    \
+                                                               \
+       asm ("getf.exp %0=%1" : "=r"(ia64_intri_res) : "f"(x)); \
+                                                               \
+       ia64_intri_res;                                         \
+})
+
+#define ia64_shrp(a, b, count)                                                         \
+({                                                                                     \
+       __u64 ia64_intri_res;                                                           \
+       asm ("shrp %0=%1,%2,%3" : "=r"(ia64_intri_res) : "r"(a), "r"(b), "i"(count));   \
+       ia64_intri_res;                                                                 \
+})
+
+#define ia64_ldfs(regnum, x)                                   \
+({                                                             \
+       register double __f__ asm ("f"#regnum);                 \
+       asm volatile ("ldfs %0=[%1]" :"=f"(__f__): "r"(x));     \
+})
+
+#define ia64_ldfd(regnum, x)                                   \
+({                                                             \
+       register double __f__ asm ("f"#regnum);                 \
+       asm volatile ("ldfd %0=[%1]" :"=f"(__f__): "r"(x));     \
+})
+
+#define ia64_ldfe(regnum, x)                                   \
+({                                                             \
+       register double __f__ asm ("f"#regnum);                 \
+       asm volatile ("ldfe %0=[%1]" :"=f"(__f__): "r"(x));     \
+})
+
+#define ia64_ldf8(regnum, x)                                   \
+({                                                             \
+       register double __f__ asm ("f"#regnum);                 \
+       asm volatile ("ldf8 %0=[%1]" :"=f"(__f__): "r"(x));     \
+})
+
+#define ia64_ldf_fill(regnum, x)                               \
+({                                                             \
+       register double __f__ asm ("f"#regnum);                 \
+       asm volatile ("ldf.fill %0=[%1]" :"=f"(__f__): "r"(x)); \
+})
+
+#define ia64_st4_rel_nta(m, val)                                       \
+({                                                                     \
+       asm volatile ("st4.rel.nta [%0] = %1\n\t" :: "r"(m), "r"(val)); \
+})
+
+#define ia64_stfs(x, regnum)                                           \
+({                                                                     \
+       register double __f__ asm ("f"#regnum);                         \
+       asm volatile ("stfs [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \
+})
+
+#define ia64_stfd(x, regnum)                                           \
+({                                                                     \
+       register double __f__ asm ("f"#regnum);                         \
+       asm volatile ("stfd [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \
+})
+
+#define ia64_stfe(x, regnum)                                           \
+({                                                                     \
+       register double __f__ asm ("f"#regnum);                         \
+       asm volatile ("stfe [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \
+})
+
+#define ia64_stf8(x, regnum)                                           \
+({                                                                     \
+       register double __f__ asm ("f"#regnum);                         \
+       asm volatile ("stf8 [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \
+})
+
+#define ia64_stf_spill(x, regnum)                                              \
+({                                                                             \
+       register double __f__ asm ("f"#regnum);                                 \
+       asm volatile ("stf.spill [%0]=%1" :: "r"(x), "f"(__f__) : "memory");    \
+})
+
+#define ia64_fetchadd4_acq(p, inc)                                             \
+({                                                                             \
+                                                                               \
+       __u64 ia64_intri_res;                                                   \
+       asm volatile ("fetchadd4.acq %0=[%1],%2"                                \
+                               : "=r"(ia64_intri_res) : "r"(p), "i" (inc)      \
+                               : "memory");                                    \
+                                                                               \
+       ia64_intri_res;                                                         \
+})
+
+#define ia64_fetchadd4_rel(p, inc)                                             \
+({                                                                             \
+       __u64 ia64_intri_res;                                                   \
+       asm volatile ("fetchadd4.rel %0=[%1],%2"                                \
+                               : "=r"(ia64_intri_res) : "r"(p), "i" (inc)      \
+                               : "memory");                                    \
+                                                                               \
+       ia64_intri_res;                                                         \
+})
+
+#define ia64_fetchadd8_acq(p, inc)                                             \
+({                                                                             \
+                                                                               \
+       __u64 ia64_intri_res;                                                   \
+       asm volatile ("fetchadd8.acq %0=[%1],%2"                                \
+                               : "=r"(ia64_intri_res) : "r"(p), "i" (inc)      \
+                               : "memory");                                    \
+                                                                               \
+       ia64_intri_res;                                                         \
+})
+
+#define ia64_fetchadd8_rel(p, inc)                                             \
+({                                                                             \
+       __u64 ia64_intri_res;                                                   \
+       asm volatile ("fetchadd8.rel %0=[%1],%2"                                \
+                               : "=r"(ia64_intri_res) : "r"(p), "i" (inc)      \
+                               : "memory");                                    \
+                                                                               \
+       ia64_intri_res;                                                         \
+})
+
+#define ia64_xchg1(ptr,x)                                                      \
+({                                                                             \
+       __u64 ia64_intri_res;                                                   \
+       asm volatile ("xchg1 %0=[%1],%2"                                        \
+                     : "=r" (ia64_intri_res) : "r" (ptr), "r" (x) : "memory"); \
+       ia64_intri_res;                                                         \
+})
+
+#define ia64_xchg2(ptr,x)                                              \
+({                                                                     \
+       __u64 ia64_intri_res;                                           \
+       asm volatile ("xchg2 %0=[%1],%2" : "=r" (ia64_intri_res)        \
+                     : "r" (ptr), "r" (x) : "memory");                 \
+       ia64_intri_res;                                                 \
+})
+
+#define ia64_xchg4(ptr,x)                                              \
+({                                                                     \
+       __u64 ia64_intri_res;                                           \
+       asm volatile ("xchg4 %0=[%1],%2" : "=r" (ia64_intri_res)        \
+                     : "r" (ptr), "r" (x) : "memory");                 \
+       ia64_intri_res;                                                 \
+})
+
+#define ia64_xchg8(ptr,x)                                              \
+({                                                                     \
+       __u64 ia64_intri_res;                                           \
+       asm volatile ("xchg8 %0=[%1],%2" : "=r" (ia64_intri_res)        \
+                     : "r" (ptr), "r" (x) : "memory");                 \
+       ia64_intri_res;                                                 \
+})
+
+#define ia64_cmpxchg1_acq(ptr, new, old)                                               \
+({                                                                                     \
+       __u64 ia64_intri_res;                                                           \
+       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
+       asm volatile ("cmpxchg1.acq %0=[%1],%2,ar.ccv":                                 \
+                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
+       ia64_intri_res;                                                                 \
+})
+
+#define ia64_cmpxchg1_rel(ptr, new, old)                                               \
+({                                                                                     \
+       __u64 ia64_intri_res;                                                           \
+       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
+       asm volatile ("cmpxchg1.rel %0=[%1],%2,ar.ccv":                                 \
+                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
+       ia64_intri_res;                                                                 \
+})
+
+#define ia64_cmpxchg2_acq(ptr, new, old)                                               \
+({                                                                                     \
+       __u64 ia64_intri_res;                                                           \
+       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
+       asm volatile ("cmpxchg2.acq %0=[%1],%2,ar.ccv":                                 \
+                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
+       ia64_intri_res;                                                                 \
+})
+
+#define ia64_cmpxchg2_rel(ptr, new, old)                                               \
+({                                                                                     \
+       __u64 ia64_intri_res;                                                           \
+       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
+                                                                                       \
+       asm volatile ("cmpxchg2.rel %0=[%1],%2,ar.ccv":                                 \
+                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
+       ia64_intri_res;                                                                 \
+})
+
+#define ia64_cmpxchg4_acq(ptr, new, old)                                               \
+({                                                                                     \
+       __u64 ia64_intri_res;                                                           \
+       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
+       asm volatile ("cmpxchg4.acq %0=[%1],%2,ar.ccv":                                 \
+                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
+       ia64_intri_res;                                                                 \
+})
+
+#define ia64_cmpxchg4_rel(ptr, new, old)                                               \
+({                                                                                     \
+       __u64 ia64_intri_res;                                                           \
+       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
+       asm volatile ("cmpxchg4.rel %0=[%1],%2,ar.ccv":                                 \
+                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
+       ia64_intri_res;                                                                 \
+})
+
+#define ia64_cmpxchg8_acq(ptr, new, old)                                               \
+({                                                                                     \
+       __u64 ia64_intri_res;                                                           \
+       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
+       asm volatile ("cmpxchg8.acq %0=[%1],%2,ar.ccv":                                 \
+                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
+       ia64_intri_res;                                                                 \
+})
+
+#define ia64_cmpxchg8_rel(ptr, new, old)                                               \
+({                                                                                     \
+       __u64 ia64_intri_res;                                                           \
+       asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));                                  \
+                                                                                       \
+       asm volatile ("cmpxchg8.rel %0=[%1],%2,ar.ccv":                                 \
+                             "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");    \
+       ia64_intri_res;                                                                 \
+})
+
+#define ia64_mf()      asm volatile ("mf" ::: "memory")
+#define ia64_mfa()     asm volatile ("mf.a" ::: "memory")
+
+#define ia64_invala() asm volatile ("invala" ::: "memory")
+
+#define ia64_native_thash(addr)                                                        \
+({                                                                             \
+       unsigned long ia64_intri_res;                                           \
+       asm volatile ("thash %0=%1" : "=r"(ia64_intri_res) : "r" (addr));       \
+       ia64_intri_res;                                                         \
+})
+
+#define ia64_srlz_i()  asm volatile (";; srlz.i ;;" ::: "memory")
+#define ia64_srlz_d()  asm volatile (";; srlz.d" ::: "memory");
+
+#ifdef HAVE_SERIALIZE_DIRECTIVE
+# define ia64_dv_serialize_data()              asm volatile (".serialize.data");
+# define ia64_dv_serialize_instruction()       asm volatile (".serialize.instruction");
+#else
+# define ia64_dv_serialize_data()
+# define ia64_dv_serialize_instruction()
+#endif
+
+#define ia64_nop(x)    asm volatile ("nop %0"::"i"(x));
+
+#define ia64_itci(addr)        asm volatile ("itc.i %0;;" :: "r"(addr) : "memory")
+
+#define ia64_itcd(addr)        asm volatile ("itc.d %0;;" :: "r"(addr) : "memory")
+
+
+#define ia64_itri(trnum, addr) asm volatile ("itr.i itr[%0]=%1"                                \
+                                            :: "r"(trnum), "r"(addr) : "memory")
+
+#define ia64_itrd(trnum, addr) asm volatile ("itr.d dtr[%0]=%1"                                \
+                                            :: "r"(trnum), "r"(addr) : "memory")
+
+#define ia64_tpa(addr)                                                         \
+({                                                                             \
+       unsigned long ia64_pa;                                                  \
+       asm volatile ("tpa %0 = %1" : "=r"(ia64_pa) : "r"(addr) : "memory");    \
+       ia64_pa;                                                                \
+})
+
+#define __ia64_set_dbr(index, val)                                             \
+       asm volatile ("mov dbr[%0]=%1" :: "r"(index), "r"(val) : "memory")
+
+#define ia64_set_ibr(index, val)                                               \
+       asm volatile ("mov ibr[%0]=%1" :: "r"(index), "r"(val) : "memory")
+
+#define ia64_set_pkr(index, val)                                               \
+       asm volatile ("mov pkr[%0]=%1" :: "r"(index), "r"(val) : "memory")
+
+#define ia64_set_pmc(index, val)                                               \
+       asm volatile ("mov pmc[%0]=%1" :: "r"(index), "r"(val) : "memory")
+
+#define ia64_set_pmd(index, val)                                               \
+       asm volatile ("mov pmd[%0]=%1" :: "r"(index), "r"(val) : "memory")
+
+#define ia64_native_set_rr(index, val)                                                 \
+       asm volatile ("mov rr[%0]=%1" :: "r"(index), "r"(val) : "memory");
+
+#define ia64_native_get_cpuid(index)                                                   \
+({                                                                                     \
+       unsigned long ia64_intri_res;                                                   \
+       asm volatile ("mov %0=cpuid[%r1]" : "=r"(ia64_intri_res) : "rO"(index));        \
+       ia64_intri_res;                                                                 \
+})
+
+#define __ia64_get_dbr(index)                                                  \
+({                                                                             \
+       unsigned long ia64_intri_res;                                           \
+       asm volatile ("mov %0=dbr[%1]" : "=r"(ia64_intri_res) : "r"(index));    \
+       ia64_intri_res;                                                         \
+})
+
+#define ia64_get_ibr(index)                                                    \
+({                                                                             \
+       unsigned long ia64_intri_res;                                           \
+       asm volatile ("mov %0=ibr[%1]" : "=r"(ia64_intri_res) : "r"(index));    \
+       ia64_intri_res;                                                         \
+})
+
+#define ia64_get_pkr(index)                                                    \
+({                                                                             \
+       unsigned long ia64_intri_res;                                           \
+       asm volatile ("mov %0=pkr[%1]" : "=r"(ia64_intri_res) : "r"(index));    \
+       ia64_intri_res;                                                         \
+})
+
+#define ia64_get_pmc(index)                                                    \
+({                                                                             \
+       unsigned long ia64_intri_res;                                           \
+       asm volatile ("mov %0=pmc[%1]" : "=r"(ia64_intri_res) : "r"(index));    \
+       ia64_intri_res;                                                         \
+})
+
+
+#define ia64_native_get_pmd(index)                                             \
+({                                                                             \
+       unsigned long ia64_intri_res;                                           \
+       asm volatile ("mov %0=pmd[%1]" : "=r"(ia64_intri_res) : "r"(index));    \
+       ia64_intri_res;                                                         \
+})
+
+#define ia64_native_get_rr(index)                                              \
+({                                                                             \
+       unsigned long ia64_intri_res;                                           \
+       asm volatile ("mov %0=rr[%1]" : "=r"(ia64_intri_res) : "r" (index));    \
+       ia64_intri_res;                                                         \
+})
+
+#define ia64_native_fc(addr)   asm volatile ("fc %0" :: "r"(addr) : "memory")
+
+
+#define ia64_sync_i()  asm volatile (";; sync.i" ::: "memory")
+
+#define ia64_native_ssm(mask)  asm volatile ("ssm %0":: "i"((mask)) : "memory")
+#define ia64_native_rsm(mask)  asm volatile ("rsm %0":: "i"((mask)) : "memory")
+#define ia64_sum(mask) asm volatile ("sum %0":: "i"((mask)) : "memory")
+#define ia64_rum(mask) asm volatile ("rum %0":: "i"((mask)) : "memory")
+
+#define ia64_ptce(addr)        asm volatile ("ptc.e %0" :: "r"(addr))
+
+#define ia64_native_ptcga(addr, size)                                          \
+do {                                                                           \
+       asm volatile ("ptc.ga %0,%1" :: "r"(addr), "r"(size) : "memory");       \
+       ia64_dv_serialize_data();                                               \
+} while (0)
+
+#define ia64_ptcl(addr, size)                                                  \
+do {                                                                           \
+       asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(size) : "memory");        \
+       ia64_dv_serialize_data();                                               \
+} while (0)
+
+#define ia64_ptri(addr, size)                                          \
+       asm volatile ("ptr.i %0,%1" :: "r"(addr), "r"(size) : "memory")
+
+#define ia64_ptrd(addr, size)                                          \
+       asm volatile ("ptr.d %0,%1" :: "r"(addr), "r"(size) : "memory")
+
+#define ia64_ttag(addr)                                                        \
+({                                                                       \
+       __u64 ia64_intri_res;                                              \
+       asm volatile ("ttag %0=%1" : "=r"(ia64_intri_res) : "r" (addr));   \
+       ia64_intri_res;                                                  \
+})
+
+
+/* Values for lfhint in ia64_lfetch and ia64_lfetch_fault */
+
+#define ia64_lfhint_none   0
+#define ia64_lfhint_nt1    1
+#define ia64_lfhint_nt2    2
+#define ia64_lfhint_nta    3
+
+#define ia64_lfetch(lfhint, y)                                 \
+({                                                             \
+        switch (lfhint) {                                      \
+        case ia64_lfhint_none:                                 \
+                asm volatile ("lfetch [%0]" : : "r"(y));       \
+                break;                                         \
+        case ia64_lfhint_nt1:                                  \
+                asm volatile ("lfetch.nt1 [%0]" : : "r"(y));   \
+                break;                                         \
+        case ia64_lfhint_nt2:                                  \
+                asm volatile ("lfetch.nt2 [%0]" : : "r"(y));   \
+                break;                                         \
+        case ia64_lfhint_nta:                                  \
+                asm volatile ("lfetch.nta [%0]" : : "r"(y));   \
+                break;                                         \
+        }                                                      \
+})
+
+#define ia64_lfetch_excl(lfhint, y)                                    \
+({                                                                     \
+        switch (lfhint) {                                              \
+        case ia64_lfhint_none:                                         \
+                asm volatile ("lfetch.excl [%0]" :: "r"(y));           \
+                break;                                                 \
+        case ia64_lfhint_nt1:                                          \
+                asm volatile ("lfetch.excl.nt1 [%0]" :: "r"(y));       \
+                break;                                                 \
+        case ia64_lfhint_nt2:                                          \
+                asm volatile ("lfetch.excl.nt2 [%0]" :: "r"(y));       \
+                break;                                                 \
+        case ia64_lfhint_nta:                                          \
+                asm volatile ("lfetch.excl.nta [%0]" :: "r"(y));       \
+                break;                                                 \
+        }                                                              \
+})
+
+#define ia64_lfetch_fault(lfhint, y)                                   \
+({                                                                     \
+        switch (lfhint) {                                              \
+        case ia64_lfhint_none:                                         \
+                asm volatile ("lfetch.fault [%0]" : : "r"(y));         \
+                break;                                                 \
+        case ia64_lfhint_nt1:                                          \
+                asm volatile ("lfetch.fault.nt1 [%0]" : : "r"(y));     \
+                break;                                                 \
+        case ia64_lfhint_nt2:                                          \
+                asm volatile ("lfetch.fault.nt2 [%0]" : : "r"(y));     \
+                break;                                                 \
+        case ia64_lfhint_nta:                                          \
+                asm volatile ("lfetch.fault.nta [%0]" : : "r"(y));     \
+                break;                                                 \
+        }                                                              \
+})
+
+#define ia64_lfetch_fault_excl(lfhint, y)                              \
+({                                                                     \
+        switch (lfhint) {                                              \
+        case ia64_lfhint_none:                                         \
+                asm volatile ("lfetch.fault.excl [%0]" :: "r"(y));     \
+                break;                                                 \
+        case ia64_lfhint_nt1:                                          \
+                asm volatile ("lfetch.fault.excl.nt1 [%0]" :: "r"(y)); \
+                break;                                                 \
+        case ia64_lfhint_nt2:                                          \
+                asm volatile ("lfetch.fault.excl.nt2 [%0]" :: "r"(y)); \
+                break;                                                 \
+        case ia64_lfhint_nta:                                          \
+                asm volatile ("lfetch.fault.excl.nta [%0]" :: "r"(y)); \
+                break;                                                 \
+        }                                                              \
+})
+
+#define ia64_native_intrin_local_irq_restore(x)                        \
+do {                                                           \
+       asm volatile (";;   cmp.ne p6,p7=%0,r0;;"               \
+                     "(p6) ssm psr.i;"                         \
+                     "(p7) rsm psr.i;;"                        \
+                     "(p6) srlz.d"                             \
+                     :: "r"((x)) : "p6", "p7", "memory");      \
+} while (0)
+
+#endif /* _UAPI_ASM_IA64_GCC_INTRIN_H */
diff --git a/arch/ia64/include/uapi/asm/intrinsics.h b/arch/ia64/include/uapi/asm/intrinsics.h
new file mode 100644 (file)
index 0000000..5829978
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Compiler-dependent intrinsics.
+ *
+ * Copyright (C) 2002-2003 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#ifndef _UAPI_ASM_IA64_INTRINSICS_H
+#define _UAPI_ASM_IA64_INTRINSICS_H
+
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+/* include compiler specific intrinsics */
+#include <asm/ia64regs.h>
+#ifdef __INTEL_COMPILER
+# include <asm/intel_intrin.h>
+#else
+# include <asm/gcc_intrin.h>
+#endif
+#include <asm/cmpxchg.h>
+
+#define ia64_native_get_psr_i()        (ia64_native_getreg(_IA64_REG_PSR) & IA64_PSR_I)
+
+#define ia64_native_set_rr0_to_rr4(val0, val1, val2, val3, val4)       \
+do {                                                                   \
+       ia64_native_set_rr(0x0000000000000000UL, (val0));               \
+       ia64_native_set_rr(0x2000000000000000UL, (val1));               \
+       ia64_native_set_rr(0x4000000000000000UL, (val2));               \
+       ia64_native_set_rr(0x6000000000000000UL, (val3));               \
+       ia64_native_set_rr(0x8000000000000000UL, (val4));               \
+} while (0)
+
+/*
+ * Force an unresolved reference if someone tries to use
+ * ia64_fetch_and_add() with a bad value.
+ */
+extern unsigned long __bad_size_for_ia64_fetch_and_add (void);
+extern unsigned long __bad_increment_for_ia64_fetch_and_add (void);
+
+#define IA64_FETCHADD(tmp,v,n,sz,sem)                                          \
+({                                                                             \
+       switch (sz) {                                                           \
+             case 4:                                                           \
+               tmp = ia64_fetchadd4_##sem((unsigned int *) v, n);              \
+               break;                                                          \
+                                                                               \
+             case 8:                                                           \
+               tmp = ia64_fetchadd8_##sem((unsigned long *) v, n);             \
+               break;                                                          \
+                                                                               \
+             default:                                                          \
+               __bad_size_for_ia64_fetch_and_add();                            \
+       }                                                                       \
+})
+
+#define ia64_fetchadd(i,v,sem)                                                         \
+({                                                                                     \
+       __u64 _tmp;                                                                     \
+       volatile __typeof__(*(v)) *_v = (v);                                            \
+       /* Can't use a switch () here: gcc isn't always smart enough for that... */     \
+       if ((i) == -16)                                                                 \
+               IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v)), sem);                        \
+       else if ((i) == -8)                                                             \
+               IA64_FETCHADD(_tmp, _v, -8, sizeof(*(v)), sem);                         \
+       else if ((i) == -4)                                                             \
+               IA64_FETCHADD(_tmp, _v, -4, sizeof(*(v)), sem);                         \
+       else if ((i) == -1)                                                             \
+               IA64_FETCHADD(_tmp, _v, -1, sizeof(*(v)), sem);                         \
+       else if ((i) == 1)                                                              \
+               IA64_FETCHADD(_tmp, _v, 1, sizeof(*(v)), sem);                          \
+       else if ((i) == 4)                                                              \
+               IA64_FETCHADD(_tmp, _v, 4, sizeof(*(v)), sem);                          \
+       else if ((i) == 8)                                                              \
+               IA64_FETCHADD(_tmp, _v, 8, sizeof(*(v)), sem);                          \
+       else if ((i) == 16)                                                             \
+               IA64_FETCHADD(_tmp, _v, 16, sizeof(*(v)), sem);                         \
+       else                                                                            \
+               _tmp = __bad_increment_for_ia64_fetch_and_add();                        \
+       (__typeof__(*(v))) (_tmp);      /* return old value */                          \
+})
+
+#define ia64_fetch_and_add(i,v)        (ia64_fetchadd(i, v, rel) + (i)) /* return new value */
+
+#endif
+
+
+#ifndef __ASSEMBLY__
+
+#define IA64_INTRINSIC_API(name)       ia64_native_ ## name
+#define IA64_INTRINSIC_MACRO(name)     ia64_native_ ## name
+
+
+/************************************************/
+/* Instructions paravirtualized for correctness */
+/************************************************/
+/* fc, thash, get_cpuid, get_pmd, get_eflags, set_eflags */
+/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag"
+ * is not currently used (though it may be in a long-format VHPT system!)
+ */
+#define ia64_fc                                IA64_INTRINSIC_API(fc)
+#define ia64_thash                     IA64_INTRINSIC_API(thash)
+#define ia64_get_cpuid                 IA64_INTRINSIC_API(get_cpuid)
+#define ia64_get_pmd                   IA64_INTRINSIC_API(get_pmd)
+
+
+/************************************************/
+/* Instructions paravirtualized for performance */
+/************************************************/
+#define ia64_ssm                       IA64_INTRINSIC_MACRO(ssm)
+#define ia64_rsm                       IA64_INTRINSIC_MACRO(rsm)
+#define ia64_getreg                    IA64_INTRINSIC_MACRO(getreg)
+#define ia64_setreg                    IA64_INTRINSIC_API(setreg)
+#define ia64_set_rr                    IA64_INTRINSIC_API(set_rr)
+#define ia64_get_rr                    IA64_INTRINSIC_API(get_rr)
+#define ia64_ptcga                     IA64_INTRINSIC_API(ptcga)
+#define ia64_get_psr_i                 IA64_INTRINSIC_API(get_psr_i)
+#define ia64_intrin_local_irq_restore  \
+       IA64_INTRINSIC_API(intrin_local_irq_restore)
+#define ia64_set_rr0_to_rr4            IA64_INTRINSIC_API(set_rr0_to_rr4)
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _UAPI_ASM_IA64_INTRINSICS_H */
diff --git a/arch/ia64/include/uapi/asm/kvm_para.h b/arch/ia64/include/uapi/asm/kvm_para.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/arch/ia64/include/uapi/asm/mman.h b/arch/ia64/include/uapi/asm/mman.h
new file mode 100644 (file)
index 0000000..8740819
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Based on <asm-i386/mman.h>.
+ *
+ * Modified 1998-2000, 2002
+ *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
+ */
+#ifndef _UAPI_ASM_IA64_MMAN_H
+#define _UAPI_ASM_IA64_MMAN_H
+
+
+#include <asm-generic/mman.h>
+
+#define MAP_GROWSUP    0x0200          /* register stack-like segment */
+
+
+#endif /* _UAPI_ASM_IA64_MMAN_H */
diff --git a/arch/ia64/include/uapi/asm/param.h b/arch/ia64/include/uapi/asm/param.h
new file mode 100644 (file)
index 0000000..d7da41d
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Fundamental kernel parameters.
+ *
+ * Based on <asm-i386/param.h>.
+ *
+ * Modified 1998, 1999, 2002-2003
+ *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
+ */
+#ifndef _UAPI_ASM_IA64_PARAM_H
+#define _UAPI_ASM_IA64_PARAM_H
+
+
+#define EXEC_PAGESIZE  65536
+
+#ifndef NOGROUP
+# define NOGROUP       (-1)
+#endif
+
+#define MAXHOSTNAMELEN 64      /* max length of hostname */
+
+#ifndef __KERNEL__
+   /*
+    * Technically, this is wrong, but some old apps still refer to it.  The proper way to
+    * get the HZ value is via sysconf(_SC_CLK_TCK).
+    */
+# define HZ 1024
+#endif
+
+#endif /* _UAPI_ASM_IA64_PARAM_H */
diff --git a/arch/ia64/include/uapi/asm/perfmon.h b/arch/ia64/include/uapi/asm/perfmon.h
new file mode 100644 (file)
index 0000000..1a10a2d
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2001-2003 Hewlett-Packard Co
+ *               Stephane Eranian <eranian@hpl.hp.com>
+ */
+
+#ifndef _UAPI_ASM_IA64_PERFMON_H
+#define _UAPI_ASM_IA64_PERFMON_H
+
+/*
+ * perfmon commands supported on all CPU models
+ */
+#define PFM_WRITE_PMCS         0x01
+#define PFM_WRITE_PMDS         0x02
+#define PFM_READ_PMDS          0x03
+#define PFM_STOP               0x04
+#define PFM_START              0x05
+#define PFM_ENABLE             0x06 /* obsolete */
+#define PFM_DISABLE            0x07 /* obsolete */
+#define PFM_CREATE_CONTEXT     0x08
+#define PFM_DESTROY_CONTEXT    0x09 /* obsolete use close() */
+#define PFM_RESTART            0x0a
+#define PFM_PROTECT_CONTEXT    0x0b /* obsolete */
+#define PFM_GET_FEATURES       0x0c
+#define PFM_DEBUG              0x0d
+#define PFM_UNPROTECT_CONTEXT  0x0e /* obsolete */
+#define PFM_GET_PMC_RESET_VAL  0x0f
+#define PFM_LOAD_CONTEXT       0x10
+#define PFM_UNLOAD_CONTEXT     0x11
+
+/*
+ * PMU model specific commands (may not be supported on all PMU models)
+ */
+#define PFM_WRITE_IBRS         0x20
+#define PFM_WRITE_DBRS         0x21
+
+/*
+ * context flags
+ */
+#define PFM_FL_NOTIFY_BLOCK             0x01   /* block task on user level notifications */
+#define PFM_FL_SYSTEM_WIDE      0x02   /* create a system wide context */
+#define PFM_FL_OVFL_NO_MSG      0x80   /* do not post overflow/end messages for notification */
+
+/*
+ * event set flags
+ */
+#define PFM_SETFL_EXCL_IDLE      0x01   /* exclude idle task (syswide only) XXX: DO NOT USE YET */
+
+/*
+ * PMC flags
+ */
+#define PFM_REGFL_OVFL_NOTIFY  0x1     /* send notification on overflow */
+#define PFM_REGFL_RANDOM       0x2     /* randomize sampling interval   */
+
+/*
+ * PMD/PMC/IBR/DBR return flags (ignored on input)
+ *
+ * Those flags are used on output and must be checked in case EAGAIN is returned
+ * by any of the calls using a pfarg_reg_t or pfarg_dbreg_t structure.
+ */
+#define PFM_REG_RETFL_NOTAVAIL (1UL<<31) /* set if register is implemented but not available */
+#define PFM_REG_RETFL_EINVAL   (1UL<<30) /* set if register entry is invalid */
+#define PFM_REG_RETFL_MASK     (PFM_REG_RETFL_NOTAVAIL|PFM_REG_RETFL_EINVAL)
+
+#define PFM_REG_HAS_ERROR(flag)        (((flag) & PFM_REG_RETFL_MASK) != 0)
+
+typedef unsigned char pfm_uuid_t[16];  /* custom sampling buffer identifier type */
+
+/*
+ * Request structure used to define a context
+ */
+typedef struct {
+       pfm_uuid_t     ctx_smpl_buf_id;  /* which buffer format to use (if needed) */
+       unsigned long  ctx_flags;        /* noblock/block */
+       unsigned short ctx_nextra_sets;  /* number of extra event sets (you always get 1) */
+       unsigned short ctx_reserved1;    /* for future use */
+       int            ctx_fd;           /* return arg: unique identification for context */
+       void           *ctx_smpl_vaddr;  /* return arg: virtual address of sampling buffer, is used */
+       unsigned long  ctx_reserved2[11];/* for future use */
+} pfarg_context_t;
+
+/*
+ * Request structure used to write/read a PMC or PMD
+ */
+typedef struct {
+       unsigned int    reg_num;           /* which register */
+       unsigned short  reg_set;           /* event set for this register */
+       unsigned short  reg_reserved1;     /* for future use */
+
+       unsigned long   reg_value;         /* initial pmc/pmd value */
+       unsigned long   reg_flags;         /* input: pmc/pmd flags, return: reg error */
+
+       unsigned long   reg_long_reset;    /* reset after buffer overflow notification */
+       unsigned long   reg_short_reset;   /* reset after counter overflow */
+
+       unsigned long   reg_reset_pmds[4]; /* which other counters to reset on overflow */
+       unsigned long   reg_random_seed;   /* seed value when randomization is used */
+       unsigned long   reg_random_mask;   /* bitmask used to limit random value */
+       unsigned long   reg_last_reset_val;/* return: PMD last reset value */
+
+       unsigned long   reg_smpl_pmds[4];  /* which pmds are accessed when PMC overflows */
+       unsigned long   reg_smpl_eventid;  /* opaque sampling event identifier */
+
+       unsigned long   reg_reserved2[3];   /* for future use */
+} pfarg_reg_t;
+
+typedef struct {
+       unsigned int    dbreg_num;              /* which debug register */
+       unsigned short  dbreg_set;              /* event set for this register */
+       unsigned short  dbreg_reserved1;        /* for future use */
+       unsigned long   dbreg_value;            /* value for debug register */
+       unsigned long   dbreg_flags;            /* return: dbreg error */
+       unsigned long   dbreg_reserved2[1];     /* for future use */
+} pfarg_dbreg_t;
+
+typedef struct {
+       unsigned int    ft_version;     /* perfmon: major [16-31], minor [0-15] */
+       unsigned int    ft_reserved;    /* reserved for future use */
+       unsigned long   reserved[4];    /* for future use */
+} pfarg_features_t;
+
+typedef struct {
+       pid_t           load_pid;          /* process to load the context into */
+       unsigned short  load_set;          /* first event set to load */
+       unsigned short  load_reserved1;    /* for future use */
+       unsigned long   load_reserved2[3]; /* for future use */
+} pfarg_load_t;
+
+typedef struct {
+       int             msg_type;               /* generic message header */
+       int             msg_ctx_fd;             /* generic message header */
+       unsigned long   msg_ovfl_pmds[4];       /* which PMDs overflowed */
+       unsigned short  msg_active_set;         /* active set at the time of overflow */
+       unsigned short  msg_reserved1;          /* for future use */
+       unsigned int    msg_reserved2;          /* for future use */
+       unsigned long   msg_tstamp;             /* for perf tuning/debug */
+} pfm_ovfl_msg_t;
+
+typedef struct {
+       int             msg_type;               /* generic message header */
+       int             msg_ctx_fd;             /* generic message header */
+       unsigned long   msg_tstamp;             /* for perf tuning */
+} pfm_end_msg_t;
+
+typedef struct {
+       int             msg_type;               /* type of the message */
+       int             msg_ctx_fd;             /* unique identifier for the context */
+       unsigned long   msg_tstamp;             /* for perf tuning */
+} pfm_gen_msg_t;
+
+#define PFM_MSG_OVFL   1       /* an overflow happened */
+#define PFM_MSG_END    2       /* task to which context was attached ended */
+
+typedef union {
+       pfm_ovfl_msg_t  pfm_ovfl_msg;
+       pfm_end_msg_t   pfm_end_msg;
+       pfm_gen_msg_t   pfm_gen_msg;
+} pfm_msg_t;
+
+/*
+ * Define the version numbers for both perfmon as a whole and the sampling buffer format.
+ */
+#define PFM_VERSION_MAJ                 2U
+#define PFM_VERSION_MIN                 0U
+#define PFM_VERSION             (((PFM_VERSION_MAJ&0xffff)<<16)|(PFM_VERSION_MIN & 0xffff))
+#define PFM_VERSION_MAJOR(x)    (((x)>>16) & 0xffff)
+#define PFM_VERSION_MINOR(x)    ((x) & 0xffff)
+
+
+/*
+ * miscellaneous architected definitions
+ */
+#define PMU_FIRST_COUNTER      4       /* first counting monitor (PMC/PMD) */
+#define PMU_MAX_PMCS           256     /* maximum architected number of PMC registers */
+#define PMU_MAX_PMDS           256     /* maximum architected number of PMD registers */
+
+
+#endif /* _UAPI_ASM_IA64_PERFMON_H */
diff --git a/arch/ia64/include/uapi/asm/ptrace.h b/arch/ia64/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..0a02f63
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 1998-2004 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@hpl.hp.com>
+ *     Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 2003 Intel Co
+ *     Suresh Siddha <suresh.b.siddha@intel.com>
+ *     Fenghua Yu <fenghua.yu@intel.com>
+ *     Arun Sharma <arun.sharma@intel.com>
+ *
+ * 12/07/98    S. Eranian      added pt_regs & switch_stack
+ * 12/21/98    D. Mosberger    updated to match latest code
+ *  6/17/99    D. Mosberger    added second unat member to "struct switch_stack"
+ *
+ */
+#ifndef _UAPI_ASM_IA64_PTRACE_H
+#define _UAPI_ASM_IA64_PTRACE_H
+
+/*
+ * When a user process is blocked, its state looks as follows:
+ *
+ *            +----------------------+ ------- IA64_STK_OFFSET
+ *                   |                      |   ^
+ *            | struct pt_regs       |  |
+ *           |                      |   |
+ *            +----------------------+  |
+ *           |                      |   |
+ *                   |    memory stack      |   |
+ *           | (growing downwards)  |   |
+ *           //.....................//  |
+ *                                      |
+ *           //.....................//  |
+ *           |                      |   |
+ *            +----------------------+  |
+ *            | struct switch_stack  |  |
+ *           |                      |   |
+ *           +----------------------+   |
+ *           |                      |   |
+ *           //.....................//  |
+ *                                      |
+ *           //.....................//  |
+ *           |                      |   |
+ *           |  register stack      |   |
+ *           | (growing upwards)    |   |
+ *            |                             |   |
+ *           +----------------------+   |  --- IA64_RBS_OFFSET
+ *            |  struct thread_info  |  |  ^
+ *           +----------------------+   |  |
+ *           |                      |   |  |
+ *            |  struct task_struct  |  |  |
+ * current -> |                             |   |  |
+ *           +----------------------+ -------
+ *
+ * Note that ar.ec is not saved explicitly in pt_reg or switch_stack.
+ * This is because ar.ec is saved as part of ar.pfs.
+ */
+
+
+#include <asm/fpu.h>
+
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This struct defines the way the registers are saved on system
+ * calls.
+ *
+ * We don't save all floating point register because the kernel
+ * is compiled to use only a very small subset, so the other are
+ * untouched.
+ *
+ * THIS STRUCTURE MUST BE A MULTIPLE 16-BYTE IN SIZE
+ * (because the memory stack pointer MUST ALWAYS be aligned this way)
+ *
+ */
+struct pt_regs {
+       /* The following registers are saved by SAVE_MIN: */
+       unsigned long b6;               /* scratch */
+       unsigned long b7;               /* scratch */
+
+       unsigned long ar_csd;           /* used by cmp8xchg16 (scratch) */
+       unsigned long ar_ssd;           /* reserved for future use (scratch) */
+
+       unsigned long r8;               /* scratch (return value register 0) */
+       unsigned long r9;               /* scratch (return value register 1) */
+       unsigned long r10;              /* scratch (return value register 2) */
+       unsigned long r11;              /* scratch (return value register 3) */
+
+       unsigned long cr_ipsr;          /* interrupted task's psr */
+       unsigned long cr_iip;           /* interrupted task's instruction pointer */
+       /*
+        * interrupted task's function state; if bit 63 is cleared, it
+        * contains syscall's ar.pfs.pfm:
+        */
+       unsigned long cr_ifs;
+
+       unsigned long ar_unat;          /* interrupted task's NaT register (preserved) */
+       unsigned long ar_pfs;           /* prev function state  */
+       unsigned long ar_rsc;           /* RSE configuration */
+       /* The following two are valid only if cr_ipsr.cpl > 0 || ti->flags & _TIF_MCA_INIT */
+       unsigned long ar_rnat;          /* RSE NaT */
+       unsigned long ar_bspstore;      /* RSE bspstore */
+
+       unsigned long pr;               /* 64 predicate registers (1 bit each) */
+       unsigned long b0;               /* return pointer (bp) */
+       unsigned long loadrs;           /* size of dirty partition << 16 */
+
+       unsigned long r1;               /* the gp pointer */
+       unsigned long r12;              /* interrupted task's memory stack pointer */
+       unsigned long r13;              /* thread pointer */
+
+       unsigned long ar_fpsr;          /* floating point status (preserved) */
+       unsigned long r15;              /* scratch */
+
+       /* The remaining registers are NOT saved for system calls.  */
+
+       unsigned long r14;              /* scratch */
+       unsigned long r2;               /* scratch */
+       unsigned long r3;               /* scratch */
+
+       /* The following registers are saved by SAVE_REST: */
+       unsigned long r16;              /* scratch */
+       unsigned long r17;              /* scratch */
+       unsigned long r18;              /* scratch */
+       unsigned long r19;              /* scratch */
+       unsigned long r20;              /* scratch */
+       unsigned long r21;              /* scratch */
+       unsigned long r22;              /* scratch */
+       unsigned long r23;              /* scratch */
+       unsigned long r24;              /* scratch */
+       unsigned long r25;              /* scratch */
+       unsigned long r26;              /* scratch */
+       unsigned long r27;              /* scratch */
+       unsigned long r28;              /* scratch */
+       unsigned long r29;              /* scratch */
+       unsigned long r30;              /* scratch */
+       unsigned long r31;              /* scratch */
+
+       unsigned long ar_ccv;           /* compare/exchange value (scratch) */
+
+       /*
+        * Floating point registers that the kernel considers scratch:
+        */
+       struct ia64_fpreg f6;           /* scratch */
+       struct ia64_fpreg f7;           /* scratch */
+       struct ia64_fpreg f8;           /* scratch */
+       struct ia64_fpreg f9;           /* scratch */
+       struct ia64_fpreg f10;          /* scratch */
+       struct ia64_fpreg f11;          /* scratch */
+};
+
+/*
+ * This structure contains the addition registers that need to
+ * preserved across a context switch.  This generally consists of
+ * "preserved" registers.
+ */
+struct switch_stack {
+       unsigned long caller_unat;      /* user NaT collection register (preserved) */
+       unsigned long ar_fpsr;          /* floating-point status register */
+
+       struct ia64_fpreg f2;           /* preserved */
+       struct ia64_fpreg f3;           /* preserved */
+       struct ia64_fpreg f4;           /* preserved */
+       struct ia64_fpreg f5;           /* preserved */
+
+       struct ia64_fpreg f12;          /* scratch, but untouched by kernel */
+       struct ia64_fpreg f13;          /* scratch, but untouched by kernel */
+       struct ia64_fpreg f14;          /* scratch, but untouched by kernel */
+       struct ia64_fpreg f15;          /* scratch, but untouched by kernel */
+       struct ia64_fpreg f16;          /* preserved */
+       struct ia64_fpreg f17;          /* preserved */
+       struct ia64_fpreg f18;          /* preserved */
+       struct ia64_fpreg f19;          /* preserved */
+       struct ia64_fpreg f20;          /* preserved */
+       struct ia64_fpreg f21;          /* preserved */
+       struct ia64_fpreg f22;          /* preserved */
+       struct ia64_fpreg f23;          /* preserved */
+       struct ia64_fpreg f24;          /* preserved */
+       struct ia64_fpreg f25;          /* preserved */
+       struct ia64_fpreg f26;          /* preserved */
+       struct ia64_fpreg f27;          /* preserved */
+       struct ia64_fpreg f28;          /* preserved */
+       struct ia64_fpreg f29;          /* preserved */
+       struct ia64_fpreg f30;          /* preserved */
+       struct ia64_fpreg f31;          /* preserved */
+
+       unsigned long r4;               /* preserved */
+       unsigned long r5;               /* preserved */
+       unsigned long r6;               /* preserved */
+       unsigned long r7;               /* preserved */
+
+       unsigned long b0;               /* so we can force a direct return in copy_thread */
+       unsigned long b1;
+       unsigned long b2;
+       unsigned long b3;
+       unsigned long b4;
+       unsigned long b5;
+
+       unsigned long ar_pfs;           /* previous function state */
+       unsigned long ar_lc;            /* loop counter (preserved) */
+       unsigned long ar_unat;          /* NaT bits for r4-r7 */
+       unsigned long ar_rnat;          /* RSE NaT collection register */
+       unsigned long ar_bspstore;      /* RSE dirty base (preserved) */
+       unsigned long pr;               /* 64 predicate registers (1 bit each) */
+};
+
+
+/* pt_all_user_regs is used for PTRACE_GETREGS PTRACE_SETREGS */
+struct pt_all_user_regs {
+       unsigned long nat;
+       unsigned long cr_iip;
+       unsigned long cfm;
+       unsigned long cr_ipsr;
+       unsigned long pr;
+
+       unsigned long gr[32];
+       unsigned long br[8];
+       unsigned long ar[128];
+       struct ia64_fpreg fr[128];
+};
+
+#endif /* !__ASSEMBLY__ */
+
+/* indices to application-registers array in pt_all_user_regs */
+#define PT_AUR_RSC     16
+#define PT_AUR_BSP     17
+#define PT_AUR_BSPSTORE        18
+#define PT_AUR_RNAT    19
+#define PT_AUR_CCV     32
+#define PT_AUR_UNAT    36
+#define PT_AUR_FPSR    40
+#define PT_AUR_PFS     64
+#define PT_AUR_LC      65
+#define PT_AUR_EC      66
+
+/*
+ * The numbers chosen here are somewhat arbitrary but absolutely MUST
+ * not overlap with any of the number assigned in <linux/ptrace.h>.
+ */
+#define PTRACE_SINGLEBLOCK     12      /* resume execution until next branch */
+#define PTRACE_OLD_GETSIGINFO  13      /* (replaced by PTRACE_GETSIGINFO in <linux/ptrace.h>)  */
+#define PTRACE_OLD_SETSIGINFO  14      /* (replaced by PTRACE_SETSIGINFO in <linux/ptrace.h>)  */
+#define PTRACE_GETREGS         18      /* get all registers (pt_all_user_regs) in one shot */
+#define PTRACE_SETREGS         19      /* set all registers (pt_all_user_regs) in one shot */
+
+#define PTRACE_OLDSETOPTIONS   21
+
+#endif /* _UAPI_ASM_IA64_PTRACE_H */
diff --git a/arch/ia64/include/uapi/asm/siginfo.h b/arch/ia64/include/uapi/asm/siginfo.h
new file mode 100644 (file)
index 0000000..4ea6225
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Based on <asm-i386/siginfo.h>.
+ *
+ * Modified 1998-2002
+ *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
+ */
+#ifndef _UAPI_ASM_IA64_SIGINFO_H
+#define _UAPI_ASM_IA64_SIGINFO_H
+
+
+#define __ARCH_SI_PREAMBLE_SIZE        (4 * sizeof(int))
+
+#define HAVE_ARCH_SIGINFO_T
+#define HAVE_ARCH_COPY_SIGINFO
+#define HAVE_ARCH_COPY_SIGINFO_TO_USER
+
+#include <asm-generic/siginfo.h>
+
+typedef struct siginfo {
+       int si_signo;
+       int si_errno;
+       int si_code;
+       int __pad0;
+
+       union {
+               int _pad[SI_PAD_SIZE];
+
+               /* kill() */
+               struct {
+                       pid_t _pid;             /* sender's pid */
+                       uid_t _uid;             /* sender's uid */
+               } _kill;
+
+               /* POSIX.1b timers */
+               struct {
+                       timer_t _tid;           /* timer id */
+                       int _overrun;           /* overrun count */
+                       char _pad[sizeof(__ARCH_SI_UID_T) - sizeof(int)];
+                       sigval_t _sigval;       /* must overlay ._rt._sigval! */
+                       int _sys_private;       /* not to be passed to user */
+               } _timer;
+
+               /* POSIX.1b signals */
+               struct {
+                       pid_t _pid;             /* sender's pid */
+                       uid_t _uid;             /* sender's uid */
+                       sigval_t _sigval;
+               } _rt;
+
+               /* SIGCHLD */
+               struct {
+                       pid_t _pid;             /* which child */
+                       uid_t _uid;             /* sender's uid */
+                       int _status;            /* exit code */
+                       clock_t _utime;
+                       clock_t _stime;
+               } _sigchld;
+
+               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+               struct {
+                       void __user *_addr;     /* faulting insn/memory ref. */
+                       int _imm;               /* immediate value for "break" */
+                       unsigned int _flags;    /* see below */
+                       unsigned long _isr;     /* isr */
+                       short _addr_lsb;        /* lsb of faulting address */
+               } _sigfault;
+
+               /* SIGPOLL */
+               struct {
+                       long _band;     /* POLL_IN, POLL_OUT, POLL_MSG (XPG requires a "long") */
+                       int _fd;
+               } _sigpoll;
+       } _sifields;
+} siginfo_t;
+
+#define si_imm         _sifields._sigfault._imm        /* as per UNIX SysV ABI spec */
+#define si_flags       _sifields._sigfault._flags
+/*
+ * si_isr is valid for SIGILL, SIGFPE, SIGSEGV, SIGBUS, and SIGTRAP provided that
+ * si_code is non-zero and __ISR_VALID is set in si_flags.
+ */
+#define si_isr         _sifields._sigfault._isr
+
+/*
+ * Flag values for si_flags:
+ */
+#define __ISR_VALID_BIT        0
+#define __ISR_VALID    (1 << __ISR_VALID_BIT)
+
+/*
+ * SIGILL si_codes
+ */
+#define ILL_BADIADDR   (__SI_FAULT|9)  /* unimplemented instruction address */
+#define __ILL_BREAK    (__SI_FAULT|10) /* illegal break */
+#define __ILL_BNDMOD   (__SI_FAULT|11) /* bundle-update (modification) in progress */
+#undef NSIGILL
+#define NSIGILL                11
+
+/*
+ * SIGFPE si_codes
+ */
+#define __FPE_DECOVF   (__SI_FAULT|9)  /* decimal overflow */
+#define __FPE_DECDIV   (__SI_FAULT|10) /* decimal division by zero */
+#define __FPE_DECERR   (__SI_FAULT|11) /* packed decimal error */
+#define __FPE_INVASC   (__SI_FAULT|12) /* invalid ASCII digit */
+#define __FPE_INVDEC   (__SI_FAULT|13) /* invalid decimal digit */
+#undef NSIGFPE
+#define NSIGFPE                13
+
+/*
+ * SIGSEGV si_codes
+ */
+#define __SEGV_PSTKOVF (__SI_FAULT|3)  /* paragraph stack overflow */
+#undef NSIGSEGV
+#define NSIGSEGV       3
+
+#undef NSIGTRAP
+#define NSIGTRAP       4
+
+
+#endif /* _UAPI_ASM_IA64_SIGINFO_H */
diff --git a/arch/ia64/include/uapi/asm/signal.h b/arch/ia64/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..e531c42
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Modified 1998-2001, 2003
+ *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
+ *
+ * Unfortunately, this file is being included by bits/signal.h in
+ * glibc-2.x.  Hence the #ifdef __KERNEL__ ugliness.
+ */
+#ifndef _UAPI_ASM_IA64_SIGNAL_H
+#define _UAPI_ASM_IA64_SIGNAL_H
+
+
+#define SIGHUP          1
+#define SIGINT          2
+#define SIGQUIT                 3
+#define SIGILL          4
+#define SIGTRAP                 5
+#define SIGABRT                 6
+#define SIGIOT          6
+#define SIGBUS          7
+#define SIGFPE          8
+#define SIGKILL                 9
+#define SIGUSR1                10
+#define SIGSEGV                11
+#define SIGUSR2                12
+#define SIGPIPE                13
+#define SIGALRM                14
+#define SIGTERM                15
+#define SIGSTKFLT      16
+#define SIGCHLD                17
+#define SIGCONT                18
+#define SIGSTOP                19
+#define SIGTSTP                20
+#define SIGTTIN                21
+#define SIGTTOU                22
+#define SIGURG         23
+#define SIGXCPU                24
+#define SIGXFSZ                25
+#define SIGVTALRM      26
+#define SIGPROF                27
+#define SIGWINCH       28
+#define SIGIO          29
+#define SIGPOLL                SIGIO
+/*
+#define SIGLOST                29
+*/
+#define SIGPWR         30
+#define SIGSYS         31
+/* signal 31 is no longer "unused", but the SIGUNUSED macro remains for backwards compatibility */
+#define        SIGUNUSED       31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN       32
+#define SIGRTMAX       _NSIG
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP   0x00000001
+#define SA_NOCLDWAIT   0x00000002
+#define SA_SIGINFO     0x00000004
+#define SA_ONSTACK     0x08000000
+#define SA_RESTART     0x10000000
+#define SA_NODEFER     0x40000000
+#define SA_RESETHAND   0x80000000
+
+#define SA_NOMASK      SA_NODEFER
+#define SA_ONESHOT     SA_RESETHAND
+
+#define SA_RESTORER    0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK     1
+#define SS_DISABLE     2
+
+/*
+ * The minimum stack size needs to be fairly large because we want to
+ * be sure that an app compiled for today's CPUs will continue to run
+ * on all future CPU models.  The CPU model matters because the signal
+ * frame needs to have space for the complete machine state, including
+ * all physical stacked registers.  The number of physical stacked
+ * registers is CPU model dependent, but given that the width of
+ * ar.rsc.loadrs is 14 bits, we can assume that they'll never take up
+ * more than 16KB of space.
+ */
+#if 1
+  /*
+   * This is a stupid typo: the value was _meant_ to be 131072 (0x20000), but I typed it
+   * in wrong. ;-(  To preserve backwards compatibility, we leave the kernel at the
+   * incorrect value and fix libc only.
+   */
+# define MINSIGSTKSZ   131027  /* min. stack size for sigaltstack() */
+#else
+# define MINSIGSTKSZ   131072  /* min. stack size for sigaltstack() */
+#endif
+#define SIGSTKSZ       262144  /* default stack size for sigaltstack() */
+
+
+#include <asm-generic/signal-defs.h>
+
+# ifndef __ASSEMBLY__
+
+#  include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+typedef struct sigaltstack {
+       void __user *ss_sp;
+       int ss_flags;
+       size_t ss_size;
+} stack_t;
+
+
+# endif /* !__ASSEMBLY__ */
+#endif /* _UAPI_ASM_IA64_SIGNAL_H */
diff --git a/arch/ia64/include/uapi/asm/termios.h b/arch/ia64/include/uapi/asm/termios.h
new file mode 100644 (file)
index 0000000..d59b48c
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Modified 1999
+ *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
+ *
+ * 99/01/28    Added N_IRDA and N_SMSBLOCK
+ */
+#ifndef _UAPI_ASM_IA64_TERMIOS_H
+#define _UAPI_ASM_IA64_TERMIOS_H
+
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+       unsigned short ws_row;
+       unsigned short ws_col;
+       unsigned short ws_xpixel;
+       unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+       unsigned short c_iflag;         /* input mode flags */
+       unsigned short c_oflag;         /* output mode flags */
+       unsigned short c_cflag;         /* control mode flags */
+       unsigned short c_lflag;         /* local mode flags */
+       unsigned char c_line;           /* line discipline */
+       unsigned char c_cc[NCC];        /* control characters */
+};
+
+/* modem lines */
+#define TIOCM_LE       0x001
+#define TIOCM_DTR      0x002
+#define TIOCM_RTS      0x004
+#define TIOCM_ST       0x008
+#define TIOCM_SR       0x010
+#define TIOCM_CTS      0x020
+#define TIOCM_CAR      0x040
+#define TIOCM_RNG      0x080
+#define TIOCM_DSR      0x100
+#define TIOCM_CD       TIOCM_CAR
+#define TIOCM_RI       TIOCM_RNG
+#define TIOCM_OUT1     0x2000
+#define TIOCM_OUT2     0x4000
+#define TIOCM_LOOP     0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+
+#endif /* _UAPI_ASM_IA64_TERMIOS_H */
diff --git a/arch/ia64/include/uapi/asm/types.h b/arch/ia64/include/uapi/asm/types.h
new file mode 100644 (file)
index 0000000..321193b
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * This file is never included by application software unless explicitly
+ * requested (e.g., via linux/types.h) in which case the application is
+ * Linux specific so (user-) name space pollution is not a major issue.
+ * However, for interoperability, libraries still need to be careful to
+ * avoid naming clashes.
+ *
+ * Based on <asm-alpha/types.h>.
+ *
+ * Modified 1998-2000, 2002
+ *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
+ */
+#ifndef _UAPI_ASM_IA64_TYPES_H
+#define _UAPI_ASM_IA64_TYPES_H
+
+
+#ifndef __KERNEL__
+#include <asm-generic/int-l64.h>
+#endif
+
+#ifdef __ASSEMBLY__
+# define __IA64_UL(x)          (x)
+# define __IA64_UL_CONST(x)    x
+
+#else
+# define __IA64_UL(x)          ((unsigned long)(x))
+# define __IA64_UL_CONST(x)    x##UL
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _UAPI_ASM_IA64_TYPES_H */
diff --git a/arch/ia64/include/uapi/asm/unistd.h b/arch/ia64/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..b706aa5
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * IA-64 Linux syscall numbers and inline-functions.
+ *
+ * Copyright (C) 1998-2005 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#ifndef _UAPI_ASM_IA64_UNISTD_H
+#define _UAPI_ASM_IA64_UNISTD_H
+
+
+#include <asm/break.h>
+
+#define __BREAK_SYSCALL                        __IA64_BREAK_SYSCALL
+
+#define __NR_ni_syscall                        1024
+#define __NR_exit                      1025
+#define __NR_read                      1026
+#define __NR_write                     1027
+#define __NR_open                      1028
+#define __NR_close                     1029
+#define __NR_creat                     1030
+#define __NR_link                      1031
+#define __NR_unlink                    1032
+#define __NR_execve                    1033
+#define __NR_chdir                     1034
+#define __NR_fchdir                    1035
+#define __NR_utimes                    1036
+#define __NR_mknod                     1037
+#define __NR_chmod                     1038
+#define __NR_chown                     1039
+#define __NR_lseek                     1040
+#define __NR_getpid                    1041
+#define __NR_getppid                   1042
+#define __NR_mount                     1043
+#define __NR_umount                    1044
+#define __NR_setuid                    1045
+#define __NR_getuid                    1046
+#define __NR_geteuid                   1047
+#define __NR_ptrace                    1048
+#define __NR_access                    1049
+#define __NR_sync                      1050
+#define __NR_fsync                     1051
+#define __NR_fdatasync                 1052
+#define __NR_kill                      1053
+#define __NR_rename                    1054
+#define __NR_mkdir                     1055
+#define __NR_rmdir                     1056
+#define __NR_dup                       1057
+#define __NR_pipe                      1058
+#define __NR_times                     1059
+#define __NR_brk                       1060
+#define __NR_setgid                    1061
+#define __NR_getgid                    1062
+#define __NR_getegid                   1063
+#define __NR_acct                      1064
+#define __NR_ioctl                     1065
+#define __NR_fcntl                     1066
+#define __NR_umask                     1067
+#define __NR_chroot                    1068
+#define __NR_ustat                     1069
+#define __NR_dup2                      1070
+#define __NR_setreuid                  1071
+#define __NR_setregid                  1072
+#define __NR_getresuid                 1073
+#define __NR_setresuid                 1074
+#define __NR_getresgid                 1075
+#define __NR_setresgid                 1076
+#define __NR_getgroups                 1077
+#define __NR_setgroups                 1078
+#define __NR_getpgid                   1079
+#define __NR_setpgid                   1080
+#define __NR_setsid                    1081
+#define __NR_getsid                    1082
+#define __NR_sethostname               1083
+#define __NR_setrlimit                 1084
+#define __NR_getrlimit                 1085
+#define __NR_getrusage                 1086
+#define __NR_gettimeofday              1087
+#define __NR_settimeofday              1088
+#define __NR_select                    1089
+#define __NR_poll                      1090
+#define __NR_symlink                   1091
+#define __NR_readlink                  1092
+#define __NR_uselib                    1093
+#define __NR_swapon                    1094
+#define __NR_swapoff                   1095
+#define __NR_reboot                    1096
+#define __NR_truncate                  1097
+#define __NR_ftruncate                 1098
+#define __NR_fchmod                    1099
+#define __NR_fchown                    1100
+#define __NR_getpriority               1101
+#define __NR_setpriority               1102
+#define __NR_statfs                    1103
+#define __NR_fstatfs                   1104
+#define __NR_gettid                    1105
+#define __NR_semget                    1106
+#define __NR_semop                     1107
+#define __NR_semctl                    1108
+#define __NR_msgget                    1109
+#define __NR_msgsnd                    1110
+#define __NR_msgrcv                    1111
+#define __NR_msgctl                    1112
+#define __NR_shmget                    1113
+#define __NR_shmat                     1114
+#define __NR_shmdt                     1115
+#define __NR_shmctl                    1116
+/* also known as klogctl() in GNU libc: */
+#define __NR_syslog                    1117
+#define __NR_setitimer                 1118
+#define __NR_getitimer                 1119
+/* 1120 was __NR_old_stat */
+/* 1121 was __NR_old_lstat */
+/* 1122 was __NR_old_fstat */
+#define __NR_vhangup                   1123
+#define __NR_lchown                    1124
+#define __NR_remap_file_pages          1125
+#define __NR_wait4                     1126
+#define __NR_sysinfo                   1127
+#define __NR_clone                     1128
+#define __NR_setdomainname             1129
+#define __NR_uname                     1130
+#define __NR_adjtimex                  1131
+/* 1132 was __NR_create_module */
+#define __NR_init_module               1133
+#define __NR_delete_module             1134
+/* 1135 was __NR_get_kernel_syms */
+/* 1136 was __NR_query_module */
+#define __NR_quotactl                  1137
+#define __NR_bdflush                   1138
+#define __NR_sysfs                     1139
+#define __NR_personality               1140
+#define __NR_afs_syscall               1141
+#define __NR_setfsuid                  1142
+#define __NR_setfsgid                  1143
+#define __NR_getdents                  1144
+#define __NR_flock                     1145
+#define __NR_readv                     1146
+#define __NR_writev                    1147
+#define __NR_pread64                   1148
+#define __NR_pwrite64                  1149
+#define __NR__sysctl                   1150
+#define __NR_mmap                      1151
+#define __NR_munmap                    1152
+#define __NR_mlock                     1153
+#define __NR_mlockall                  1154
+#define __NR_mprotect                  1155
+#define __NR_mremap                    1156
+#define __NR_msync                     1157
+#define __NR_munlock                   1158
+#define __NR_munlockall                        1159
+#define __NR_sched_getparam            1160
+#define __NR_sched_setparam            1161
+#define __NR_sched_getscheduler                1162
+#define __NR_sched_setscheduler                1163
+#define __NR_sched_yield               1164
+#define __NR_sched_get_priority_max    1165
+#define __NR_sched_get_priority_min    1166
+#define __NR_sched_rr_get_interval     1167
+#define __NR_nanosleep                 1168
+#define __NR_nfsservctl                        1169
+#define __NR_prctl                     1170
+/* 1171 is reserved for backwards compatibility with old __NR_getpagesize */
+#define __NR_mmap2                     1172
+#define __NR_pciconfig_read            1173
+#define __NR_pciconfig_write           1174
+#define __NR_perfmonctl                        1175
+#define __NR_sigaltstack               1176
+#define __NR_rt_sigaction              1177
+#define __NR_rt_sigpending             1178
+#define __NR_rt_sigprocmask            1179
+#define __NR_rt_sigqueueinfo           1180
+#define __NR_rt_sigreturn              1181
+#define __NR_rt_sigsuspend             1182
+#define __NR_rt_sigtimedwait           1183
+#define __NR_getcwd                    1184
+#define __NR_capget                    1185
+#define __NR_capset                    1186
+#define __NR_sendfile                  1187
+#define __NR_getpmsg                   1188
+#define __NR_putpmsg                   1189
+#define __NR_socket                    1190
+#define __NR_bind                      1191
+#define __NR_connect                   1192
+#define __NR_listen                    1193
+#define __NR_accept                    1194
+#define __NR_getsockname               1195
+#define __NR_getpeername               1196
+#define __NR_socketpair                        1197
+#define __NR_send                      1198
+#define __NR_sendto                    1199
+#define __NR_recv                      1200
+#define __NR_recvfrom                  1201
+#define __NR_shutdown                  1202
+#define __NR_setsockopt                        1203
+#define __NR_getsockopt                        1204
+#define __NR_sendmsg                   1205
+#define __NR_recvmsg                   1206
+#define __NR_pivot_root                        1207
+#define __NR_mincore                   1208
+#define __NR_madvise                   1209
+#define __NR_stat                      1210
+#define __NR_lstat                     1211
+#define __NR_fstat                     1212
+#define __NR_clone2                    1213
+#define __NR_getdents64                        1214
+#define __NR_getunwind                 1215
+#define __NR_readahead                 1216
+#define __NR_setxattr                  1217
+#define __NR_lsetxattr                 1218
+#define __NR_fsetxattr                 1219
+#define __NR_getxattr                  1220
+#define __NR_lgetxattr                 1221
+#define __NR_fgetxattr                 1222
+#define __NR_listxattr                 1223
+#define __NR_llistxattr                        1224
+#define __NR_flistxattr                        1225
+#define __NR_removexattr               1226
+#define __NR_lremovexattr              1227
+#define __NR_fremovexattr              1228
+#define __NR_tkill                     1229
+#define __NR_futex                     1230
+#define __NR_sched_setaffinity         1231
+#define __NR_sched_getaffinity         1232
+#define __NR_set_tid_address           1233
+#define __NR_fadvise64                 1234
+#define __NR_tgkill                    1235
+#define __NR_exit_group                        1236
+#define __NR_lookup_dcookie            1237
+#define __NR_io_setup                  1238
+#define __NR_io_destroy                        1239
+#define __NR_io_getevents              1240
+#define __NR_io_submit                 1241
+#define __NR_io_cancel                 1242
+#define __NR_epoll_create              1243
+#define __NR_epoll_ctl                 1244
+#define __NR_epoll_wait                        1245
+#define __NR_restart_syscall           1246
+#define __NR_semtimedop                        1247
+#define __NR_timer_create              1248
+#define __NR_timer_settime             1249
+#define __NR_timer_gettime             1250
+#define __NR_timer_getoverrun          1251
+#define __NR_timer_delete              1252
+#define __NR_clock_settime             1253
+#define __NR_clock_gettime             1254
+#define __NR_clock_getres              1255
+#define __NR_clock_nanosleep           1256
+#define __NR_fstatfs64                 1257
+#define __NR_statfs64                  1258
+#define __NR_mbind                     1259
+#define __NR_get_mempolicy             1260
+#define __NR_set_mempolicy             1261
+#define __NR_mq_open                   1262
+#define __NR_mq_unlink                 1263
+#define __NR_mq_timedsend              1264
+#define __NR_mq_timedreceive           1265
+#define __NR_mq_notify                 1266
+#define __NR_mq_getsetattr             1267
+#define __NR_kexec_load                        1268
+#define __NR_vserver                   1269
+#define __NR_waitid                    1270
+#define __NR_add_key                   1271
+#define __NR_request_key               1272
+#define __NR_keyctl                    1273
+#define __NR_ioprio_set                        1274
+#define __NR_ioprio_get                        1275
+#define __NR_move_pages                        1276
+#define __NR_inotify_init              1277
+#define __NR_inotify_add_watch         1278
+#define __NR_inotify_rm_watch          1279
+#define __NR_migrate_pages             1280
+#define __NR_openat                    1281
+#define __NR_mkdirat                   1282
+#define __NR_mknodat                   1283
+#define __NR_fchownat                  1284
+#define __NR_futimesat                 1285
+#define __NR_newfstatat                        1286
+#define __NR_unlinkat                  1287
+#define __NR_renameat                  1288
+#define __NR_linkat                    1289
+#define __NR_symlinkat                 1290
+#define __NR_readlinkat                        1291
+#define __NR_fchmodat                  1292
+#define __NR_faccessat                 1293
+#define __NR_pselect6                  1294
+#define __NR_ppoll                     1295
+#define __NR_unshare                   1296
+#define __NR_splice                    1297
+#define __NR_set_robust_list           1298
+#define __NR_get_robust_list           1299
+#define __NR_sync_file_range           1300
+#define __NR_tee                       1301
+#define __NR_vmsplice                  1302
+#define __NR_fallocate                 1303
+#define __NR_getcpu                    1304
+#define __NR_epoll_pwait               1305
+#define __NR_utimensat                 1306
+#define __NR_signalfd                  1307
+#define __NR_timerfd                   1308
+#define __NR_eventfd                   1309
+#define __NR_timerfd_create            1310
+#define __NR_timerfd_settime           1311
+#define __NR_timerfd_gettime           1312
+#define __NR_signalfd4                 1313
+#define __NR_eventfd2                  1314
+#define __NR_epoll_create1             1315
+#define __NR_dup3                      1316
+#define __NR_pipe2                     1317
+#define __NR_inotify_init1             1318
+#define __NR_preadv                    1319
+#define __NR_pwritev                   1320
+#define __NR_rt_tgsigqueueinfo         1321
+#define __NR_recvmmsg                  1322
+#define __NR_fanotify_init             1323
+#define __NR_fanotify_mark             1324
+#define __NR_prlimit64                 1325
+#define __NR_name_to_handle_at         1326
+#define __NR_open_by_handle_at         1327
+#define __NR_clock_adjtime             1328
+#define __NR_syncfs                    1329
+#define __NR_setns                     1330
+#define __NR_sendmmsg                  1331
+#define __NR_process_vm_readv          1332
+#define __NR_process_vm_writev         1333
+#define __NR_accept4                   1334
+
+#endif /* _UAPI_ASM_IA64_UNISTD_H */
diff --git a/arch/ia64/include/uapi/asm/ustack.h b/arch/ia64/include/uapi/asm/ustack.h
new file mode 100644 (file)
index 0000000..1dfebc6
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _UAPI_ASM_IA64_USTACK_H
+#define _UAPI_ASM_IA64_USTACK_H
+
+/*
+ * Constants for the user stack size
+ */
+
+
+/* Make a default stack size of 2GiB */
+#define DEFAULT_USER_STACK_SIZE        (1UL << 31)
+
+#endif /* _UAPI_ASM_IA64_USTACK_H */
index ee31fe9b310e3d93de0e46ab29486e920b51763a..35e106f2ed13e81a8509d9db0d0285cba10a0e8f 100644 (file)
@@ -614,14 +614,14 @@ sys_execve (const char __user *filename,
            const char __user *const __user *envp,
            struct pt_regs *regs)
 {
-       char *fname;
+       struct filename *fname;
        int error;
 
        fname = getname(filename);
        error = PTR_ERR(fname);
        if (IS_ERR(fname))
                goto out;
-       error = do_execve(fname, argv, envp, regs);
+       error = do_execve(fname->name, argv, envp, regs);
        putname(fname);
 out:
        return error;
index 37dd79511cbeb548c67b4f255ff0b1fcb2c69196..680b73786be85077fe2a2424e3ecfd00ebe6ea43 100644 (file)
@@ -437,14 +437,6 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
        long restart = in_syscall;
        long errno = scr->pt.r8;
 
-       /*
-        * In the ia64_leave_kernel code path, we want the common case to go fast, which
-        * is why we may in certain cases get here from kernel mode. Just return without
-        * doing anything if so.
-        */
-       if (!user_mode(&scr->pt))
-               return;
-
        /*
         * This only loops in the rare cases of handle_signal() failing, in which case we
         * need to push through a forced SIGSEGV.
index 80ff9acc5edfeb674e889a4f263553877a07f4b4..f6388216080d72fbd4547beb6e229a0e02cf7eff 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/efi.h>
 #include <linux/timex.h>
-#include <linux/clocksource.h>
+#include <linux/timekeeper_internal.h>
 #include <linux/platform_device.h>
 
 #include <asm/machvec.h>
@@ -454,7 +454,7 @@ void update_vsyscall_tz(void)
 {
 }
 
-void update_vsyscall(struct timespec *wall, struct timespec *wtm,
+void update_vsyscall_old(struct timespec *wall, struct timespec *wtm,
                        struct clocksource *c, u32 mult)
 {
        write_seqcount_begin(&fsyscall_gtod_data.seq);
index 0e152a93c1259a551ffa65b327ae5f9b013be3dd..fccd81eddff1f6de89b07cc13c362809364c9507 100644 (file)
@@ -1,3 +1,4 @@
 include include/asm-generic/Kbuild.asm
 
-generic-y      += clkdev.h
+generic-y += clkdev.h
+generic-y += exec.h
diff --git a/arch/m32r/include/asm/exec.h b/arch/m32r/include/asm/exec.h
deleted file mode 100644 (file)
index c805dbd..0000000
+++ /dev/null
@@ -1,14 +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) 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 c083f6073ef4f3d1720f466fb08f62a64bbe0881..c074f4c2e858e6cc76b16476a9fc24aea2566793 100644 (file)
@@ -119,25 +119,20 @@ static inline unsigned int get_thread_fault_code(void)
 #define TIF_SIGPENDING         1       /* signal pending */
 #define TIF_NEED_RESCHED       2       /* rescheduling necessary */
 #define TIF_SINGLESTEP         3       /* restore singlestep on return to user mode */
-#define TIF_IRET               4       /* return with iret */
 #define TIF_NOTIFY_RESUME      5       /* callback before returning to user */
 #define TIF_RESTORE_SIGMASK    8       /* restore signal mask in do_signal() */
 #define TIF_USEDFPU            16      /* FPU was used by this task this quantum (SMP) */
-#define TIF_POLLING_NRFLAG     17      /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE             18      /* is terminating due to OOM killer */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP                (1<<TIF_SINGLESTEP)
-#define _TIF_IRET              (1<<TIF_IRET)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
-#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU           (1<<TIF_USEDFPU)
-#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 
-#define _TIF_WORK_MASK         0x0000FFFE      /* work to do on interrupt/exception return */
-#define _TIF_ALLWORK_MASK      0x0000FFFF      /* work to do on any return to u-space */
+#define _TIF_WORK_MASK         (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME)
+#define _TIF_ALLWORK_MASK      (_TIF_WORK_MASK | _TIF_SYSCALL_TRACE)
 
 /*
  * Thread-synchronous status.
index 384e63f3a4c4e96ea2ea3cf54c76058c54edf88b..e7366276ef30067ad22f9fd4b9db3252d69f8b66 100644 (file)
@@ -296,14 +296,14 @@ asmlinkage int sys_execve(const char __user *ufilename,
                          unsigned long r6, struct pt_regs regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(ufilename);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename, uargv, uenvp, &regs);
+       error = do_execve(filename->name, uargv, uenvp, &regs);
        putname(filename);
 out:
        return error;
index d0f60b97bbc5d82b1855e73145ce0b809124200f..6e3c26a1607cdb6b505e4b25cab682a08ed04605 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <linux/personality.h>
-#include <linux/freezer.h>
 #include <linux/tracehook.h>
 #include <asm/cacheflush.h>
 #include <asm/ucontext.h>
@@ -366,6 +365,4 @@ void do_notify_resume(struct pt_regs *regs, __u32 thread_info_flags)
                clear_thread_flag(TIF_NOTIFY_RESUME);
                tracehook_notify_resume(regs);
        }
-
-       clear_thread_flag(TIF_IRET);
 }
index dae1e7e16a374d3e100c2f86115181ea2b0006ca..76fd6e2f71da1d4c7138f06dfca8a76633eb4336 100644 (file)
@@ -15,6 +15,7 @@ config M68K
        select FPU if MMU
        select ARCH_WANT_IPC_PARSE_VERSION
        select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE
+       select GENERIC_KERNEL_THREAD
 
 config RWSEM_GENERIC_SPINLOCK
        bool
index bfe675f0faee5a1b6bda67ecf9bc4ac006f63f87..ecb540810ab3ace200ae66368d700d97b4abf0d2 100644 (file)
@@ -7,6 +7,7 @@ generic-y += cputime.h
 generic-y += device.h
 generic-y += emergency-restart.h
 generic-y += errno.h
+generic-y += exec.h
 generic-y += futex.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
diff --git a/arch/m68k/include/asm/exec.h b/arch/m68k/include/asm/exec.h
deleted file mode 100644 (file)
index 0499adf..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _M68K_EXEC_H
-#define _M68K_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* _M68K_EXEC_H */
index f17c42aff7ffb9aa592aebf2e118d99309d8e699..ae700f49e51da86b8b86b8ce9ee41b0a1908d6b1 100644 (file)
@@ -100,6 +100,16 @@ struct thread_struct {
        .fs     = __KERNEL_DS,                                          \
 }
 
+/*
+ * ColdFire stack format sbould be 0x4 for an aligned usp (will always be
+ * true on thread creation). We need to set this explicitly.
+ */
+#ifdef CONFIG_COLDFIRE
+#define setframeformat(_regs)  do { (_regs)->format = 0x4; } while(0)
+#else
+#define setframeformat(_regs)  do { } while (0)
+#endif
+
 #ifdef CONFIG_MMU
 /*
  * Do necessary setup to start up a newly executed thread.
@@ -109,6 +119,7 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
 {
        regs->pc = pc;
        regs->sr &= ~0x2000;
+       setframeformat(regs);
        wrusp(usp);
 }
 
@@ -116,21 +127,11 @@ extern int handle_kernel_fault(struct pt_regs *regs);
 
 #else
 
-/*
- * Coldfire stacks need to be re-aligned on trap exit, conventional
- * 68k can handle this case cleanly.
- */
-#ifdef CONFIG_COLDFIRE
-#define reformat(_regs)                do { (_regs)->format = 0x4; } while(0)
-#else
-#define reformat(_regs)                do { } while (0)
-#endif
-
 #define start_thread(_regs, _pc, _usp)                  \
 do {                                                    \
        (_regs)->pc = (_pc);                            \
        ((struct switch_stack *)(_regs))[-1].a6 = 0;    \
-       reformat(_regs);                                \
+       setframeformat(_regs);                          \
        if (current->mm)                                \
                (_regs)->d5 = current->mm->start_data;  \
        (_regs)->sr &= ~0x2000;                         \
@@ -153,8 +154,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 /*
  * Free current thread data structures etc..
  */
index 65322b17b6cfb96664763a74796871d1c321413b..5e08b597f012192e8a5f8cd4cc4d0a20690b485d 100644 (file)
@@ -85,6 +85,8 @@ struct switch_stack {
 #define user_mode(regs) (!((regs)->sr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
 #define profile_pc(regs) instruction_pointer(regs)
+#define current_pt_regs() \
+       (struct pt_regs *)((char *)current_thread_info() + THREAD_SIZE) - 1
 
 #define arch_has_single_step() (1)
 
index 045cfd6a9e31b72edd428160deedd47b6078a51a..c702ad71679195f501f540b7ed5b32108f920813 100644 (file)
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
index 165ee9f9d5c9db716290009980fc6d1e865bf446..946cb0187751caf241a0f2f4e1b5b9ebe3c535a0 100644 (file)
@@ -111,6 +111,22 @@ ENTRY(ret_from_fork)
        addql   #4,%sp
        jra     ret_from_exception
 
+ENTRY(ret_from_kernel_thread)
+       | a3 contains the kernel thread payload, d7 - its argument
+       movel   %d1,%sp@-
+       jsr     schedule_tail
+       GET_CURRENT(%d0)
+       movel   %d7,(%sp)
+       jsr     %a3@
+       addql   #4,%sp
+       movel   %d0,(%sp)
+       jra     sys_exit
+
+ENTRY(ret_from_kernel_execve)
+       movel   4(%sp), %sp
+       GET_CURRENT(%d0)
+       jra     ret_from_exception
+
 #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU)
 
 #ifdef TRAP_DBG_INTERRUPT
index ac2892e49c7c9107734044925caad596e56988bc..c51bb172e14d774a4dcbea235fc22618de198aba 100644 (file)
@@ -35,6 +35,7 @@
 
 
 asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
 
 
 /*
@@ -123,51 +124,6 @@ void show_regs(struct pt_regs * regs)
                printk("USP: %08lx\n", rdusp());
 }
 
-/*
- * Create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-       int pid;
-       mm_segment_t fs;
-
-       fs = get_fs();
-       set_fs (KERNEL_DS);
-
-       {
-       register long retval __asm__ ("d0");
-       register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED;
-
-       retval = __NR_clone;
-       __asm__ __volatile__
-         ("clrl %%d2\n\t"
-          "trap #0\n\t"                /* Linux/m68k system call */
-          "tstl %0\n\t"                /* child or parent */
-          "jne 1f\n\t"                 /* parent - jump */
-#ifdef CONFIG_MMU
-          "lea %%sp@(%c7),%6\n\t"      /* reload current */
-          "movel %6@,%6\n\t"
-#endif
-          "movel %3,%%sp@-\n\t"        /* push argument */
-          "jsr %4@\n\t"                /* call fn */
-          "movel %0,%%d1\n\t"          /* pass exit value */
-          "movel %2,%%d0\n\t"          /* exit */
-          "trap #0\n"
-          "1:"
-          : "+d" (retval)
-          : "i" (__NR_clone), "i" (__NR_exit),
-            "r" (arg), "a" (fn), "d" (clone_arg), "r" (current),
-            "i" (-THREAD_SIZE)
-          : "d2");
-
-       pid = retval;
-       }
-
-       set_fs (fs);
-       return pid;
-}
-EXPORT_SYMBOL(kernel_thread);
-
 void flush_thread(void)
 {
        current->thread.fs = __USER_DS;
@@ -219,30 +175,18 @@ asmlinkage int m68k_clone(struct pt_regs *regs)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-                unsigned long unused,
+                unsigned long arg,
                 struct task_struct * p, struct pt_regs * regs)
 {
        struct pt_regs * childregs;
-       struct switch_stack * childstack, *stack;
-       unsigned long *retp;
+       struct switch_stack *childstack;
 
        childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
-
-       *childregs = *regs;
-       childregs->d0 = 0;
-
-       retp = ((unsigned long *) regs);
-       stack = ((struct switch_stack *) retp) - 1;
-
        childstack = ((struct switch_stack *) childregs) - 1;
-       *childstack = *stack;
-       childstack->retpc = (unsigned long)ret_from_fork;
 
        p->thread.usp = usp;
        p->thread.ksp = (unsigned long)childstack;
-
-       if (clone_flags & CLONE_SETTLS)
-               task_thread_info(p)->tp_value = regs->d5;
+       p->thread.esp0 = (unsigned long)childregs;
 
        /*
         * Must save the current SFC/DFC value, NOT the value when
@@ -250,6 +194,26 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
         */
        p->thread.fs = get_fs().seg;
 
+       if (unlikely(!regs)) {
+               /* kernel thread */
+               memset(childstack, 0,
+                       sizeof(struct switch_stack) + sizeof(struct pt_regs));
+               childregs->sr = PS_S;
+               childstack->a3 = usp; /* function */
+               childstack->d7 = arg;
+               childstack->retpc = (unsigned long)ret_from_kernel_thread;
+               p->thread.usp = 0;
+               return 0;
+       }
+       *childregs = *regs;
+       childregs->d0 = 0;
+
+       *childstack = ((struct switch_stack *) regs)[-1];
+       childstack->retpc = (unsigned long)ret_from_fork;
+
+       if (clone_flags & CLONE_SETTLS)
+               task_thread_info(p)->tp_value = regs->d5;
+
 #ifdef CONFIG_FPU
        if (!FPU_IS_EMU) {
                /* Copy the current fpu state */
@@ -337,26 +301,6 @@ int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
 EXPORT_SYMBOL(dump_fpu);
 #endif /* CONFIG_FPU */
 
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char __user *name,
-                         const char __user *const __user *argv,
-                         const char __user *const __user *envp)
-{
-       int error;
-       char * filename;
-       struct pt_regs *regs = (struct pt_regs *) &name;
-
-       filename = getname(name);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               return error;
-       error = do_execve(filename, argv, envp, regs);
-       putname(filename);
-       return error;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long fp, pc;
index 9a5932ec368946bf808c5faf527cbf39731b5540..3a480b3df0d6cfee0fa7a6e2da99f710d776d587 100644 (file)
@@ -549,23 +549,6 @@ asmlinkage int sys_getpagesize(void)
        return PAGE_SIZE;
 }
 
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename,
-                 const char *const argv[],
-                 const char *const envp[])
-{
-       register long __res asm ("%d0") = __NR_execve;
-       register long __a asm ("%d1") = (long)(filename);
-       register long __b asm ("%d2") = (long)(argv);
-       register long __c asm ("%d3") = (long)(envp);
-       asm volatile ("trap  #0" : "+d" (__res)
-                       : "d" (__a), "d" (__b), "d" (__c));
-       return __res;
-}
-
 asmlinkage unsigned long sys_get_thread_area(void)
 {
        return current_thread_info()->tp_value;
index 48510f6cec8f23f924c9bdc1781540282bcb0a7b..8653072d7e9f061479c5b11c5de056337cfdac7a 100644 (file)
@@ -2,3 +2,4 @@ include include/asm-generic/Kbuild.asm
 
 header-y  += elf.h
 generic-y += clkdev.h
+generic-y += exec.h
diff --git a/arch/microblaze/include/asm/exec.h b/arch/microblaze/include/asm/exec.h
deleted file mode 100644 (file)
index e750de1..0000000
+++ /dev/null
@@ -1,14 +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_EXEC_H
-#define _ASM_MICROBLAZE_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* _ASM_MICROBLAZE_EXEC_H */
index 6c610234ffab96c8d849dfc8dac498bfaf1c9919..008f30433d22f606f6b6d15f2d644fa5d88c1dd2 100644 (file)
@@ -121,7 +121,6 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_NEED_RESCHED       3 /* rescheduling necessary */
 /* restore singlestep on return to user mode */
 #define TIF_SINGLESTEP         4
-#define TIF_IRET               5 /* return with iret */
 #define TIF_MEMDIE             6       /* is terminating due to OOM killer */
 #define TIF_SYSCALL_AUDIT      9       /* syscall auditing active */
 #define TIF_SECCOMP            10      /* secure computing */
@@ -134,7 +133,6 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP                (1 << TIF_SINGLESTEP)
-#define _TIF_IRET              (1 << TIF_IRET)
 #define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1 << TIF_SECCOMP)
@@ -184,6 +182,7 @@ static inline bool test_and_clear_restore_sigmask(void)
        ti->status &= ~TS_RESTORE_SIGMASK;
        return true;
 }
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
 #endif
 
 #endif /* __KERNEL__ */
index c1220dbf87cd2726520d9713a6024c1a2fff80c5..3847e5b9c601f68e189ca21749300b6b7e416415 100644 (file)
@@ -254,10 +254,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        set_fs(USER_DS);
 
-       /* the tracer may want to single-step inside the handler */
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
 #ifdef DEBUG_SIG
        printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n",
                current->comm, current->pid, frame, regs->pc);
@@ -315,7 +311,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
        if (ret)
                return;
 
-       signal_delivered(sig, info, ka, regs, 0);
+       signal_delivered(sig, info, ka, regs,
+                       test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
index e5b154f24f85e059229544cde92714fa7e8caa54..404c0f24bd41a7acaf5496e86120b15f9e715cd8 100644 (file)
@@ -54,13 +54,13 @@ asmlinkage long microblaze_execve(const char __user *filenamei,
                                  struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(filenamei);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
 out:
        return error;
index 55902d9cd0f2c4eaf1d2a839954e054ab5b30ec6..b85b121397c8413e385809b6e3b32ac2228ad96e 100644 (file)
@@ -119,7 +119,6 @@ CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_BLOCK2MTD=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_PLATFORM=y
 CONFIG_ATA=y
 # CONFIG_ATA_VERBOSE_ERROR is not set
index 564ab81d6cdc338b5f7033248d7d2e02c8fd3f00..163e81db880dc5d6b46a07eca5be4e179d21b266 100644 (file)
@@ -31,6 +31,7 @@ extern struct platform_device jz4740_pcm_device;
 extern struct platform_device jz4740_codec_device;
 extern struct platform_device jz4740_adc_device;
 extern struct platform_device jz4740_wdt_device;
+extern struct platform_device jz4740_pwm_device;
 
 void jz4740_serial_device_register(void);
 
index 9baa03ce748ca173ad4c1c61a77817231c1a15c0..a7759fb1f73d576bcd6388588096aea764620143 100644 (file)
 #ifndef __ASM_MACH_JZ4740_TIMER
 #define __ASM_MACH_JZ4740_TIMER
 
+#define JZ_REG_TIMER_STOP              0x0C
+#define JZ_REG_TIMER_STOP_SET          0x1C
+#define JZ_REG_TIMER_STOP_CLEAR                0x2C
+#define JZ_REG_TIMER_ENABLE            0x00
+#define JZ_REG_TIMER_ENABLE_SET                0x04
+#define JZ_REG_TIMER_ENABLE_CLEAR      0x08
+#define JZ_REG_TIMER_FLAG              0x10
+#define JZ_REG_TIMER_FLAG_SET          0x14
+#define JZ_REG_TIMER_FLAG_CLEAR                0x18
+#define JZ_REG_TIMER_MASK              0x20
+#define JZ_REG_TIMER_MASK_SET          0x24
+#define JZ_REG_TIMER_MASK_CLEAR                0x28
+
+#define JZ_REG_TIMER_DFR(x) (((x) * 0x10) + 0x30)
+#define JZ_REG_TIMER_DHR(x) (((x) * 0x10) + 0x34)
+#define JZ_REG_TIMER_CNT(x) (((x) * 0x10) + 0x38)
+#define JZ_REG_TIMER_CTRL(x) (((x) * 0x10) + 0x3C)
+
+#define JZ_TIMER_IRQ_HALF(x) BIT((x) + 0x10)
+#define JZ_TIMER_IRQ_FULL(x) BIT(x)
+
+#define JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN     BIT(9)
+#define JZ_TIMER_CTRL_PWM_ACTIVE_LOW           BIT(8)
+#define JZ_TIMER_CTRL_PWM_ENABLE               BIT(7)
+#define JZ_TIMER_CTRL_PRESCALE_MASK            0x1c
+#define JZ_TIMER_CTRL_PRESCALE_OFFSET          0x3
+#define JZ_TIMER_CTRL_PRESCALE_1               (0 << 3)
+#define JZ_TIMER_CTRL_PRESCALE_4               (1 << 3)
+#define JZ_TIMER_CTRL_PRESCALE_16              (2 << 3)
+#define JZ_TIMER_CTRL_PRESCALE_64              (3 << 3)
+#define JZ_TIMER_CTRL_PRESCALE_256             (4 << 3)
+#define JZ_TIMER_CTRL_PRESCALE_1024            (5 << 3)
+
+#define JZ_TIMER_CTRL_PRESCALER(x) ((x) << JZ_TIMER_CTRL_PRESCALE_OFFSET)
+
+#define JZ_TIMER_CTRL_SRC_EXT          BIT(2)
+#define JZ_TIMER_CTRL_SRC_RTC          BIT(1)
+#define JZ_TIMER_CTRL_SRC_PCLK         BIT(0)
+
+extern void __iomem *jz4740_timer_base;
+void __init jz4740_timer_init(void);
+
 void jz4740_timer_enable_watchdog(void);
 void jz4740_timer_disable_watchdog(void);
 
+static inline void jz4740_timer_stop(unsigned int timer)
+{
+       writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_SET);
+}
+
+static inline void jz4740_timer_start(unsigned int timer)
+{
+       writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR);
+}
+
+static inline bool jz4740_timer_is_enabled(unsigned int timer)
+{
+       return readb(jz4740_timer_base + JZ_REG_TIMER_ENABLE) & BIT(timer);
+}
+
+static inline void jz4740_timer_enable(unsigned int timer)
+{
+       writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_SET);
+}
+
+static inline void jz4740_timer_disable(unsigned int timer)
+{
+       writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_CLEAR);
+}
+
+static inline void jz4740_timer_set_period(unsigned int timer, uint16_t period)
+{
+       writew(period, jz4740_timer_base + JZ_REG_TIMER_DFR(timer));
+}
+
+static inline void jz4740_timer_set_duty(unsigned int timer, uint16_t duty)
+{
+       writew(duty, jz4740_timer_base + JZ_REG_TIMER_DHR(timer));
+}
+
+static inline void jz4740_timer_set_count(unsigned int timer, uint16_t count)
+{
+       writew(count, jz4740_timer_base + JZ_REG_TIMER_CNT(timer));
+}
+
+static inline uint16_t jz4740_timer_get_count(unsigned int timer)
+{
+       return readw(jz4740_timer_base + JZ_REG_TIMER_CNT(timer));
+}
+
+static inline void jz4740_timer_ack_full(unsigned int timer)
+{
+       writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR);
+}
+
+static inline void jz4740_timer_irq_full_enable(unsigned int timer)
+{
+       writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR);
+       writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_CLEAR);
+}
+
+static inline void jz4740_timer_irq_full_disable(unsigned int timer)
+{
+       writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_SET);
+}
+
+static inline void jz4740_timer_set_ctrl(unsigned int timer, uint16_t ctrl)
+{
+       writew(ctrl, jz4740_timer_base + JZ_REG_TIMER_CTRL(timer));
+}
+
+static inline uint16_t jz4740_timer_get_ctrl(unsigned int timer)
+{
+       return readw(jz4740_timer_base + JZ_REG_TIMER_CTRL(timer));
+}
+
 #endif
index 946e010f20182b11622aa0b9bbc2d53927eab36e..8debe9e917549097d09f5083489714605066a1cc 100644 (file)
@@ -103,7 +103,6 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define TIF_NOTIFY_RESUME      5       /* callback before returning to user */
 #define TIF_RESTORE_SIGMASK    9       /* restore signal mask in do_signal() */
 #define TIF_USEDFPU            16      /* FPU was used by this task this quantum (SMP) */
-#define TIF_POLLING_NRFLAG     17      /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE             18      /* is terminating due to OOM killer */
 #define TIF_FIXADE             20      /* Fix address errors in software */
 #define TIF_LOGADE             21      /* Log address errors to syslog */
@@ -125,9 +124,7 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define _TIF_SYSCALL_AUDIT     (1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1<<TIF_SECCOMP)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
-#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU           (1<<TIF_USEDFPU)
-#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_FIXADE            (1<<TIF_FIXADE)
 #define _TIF_LOGADE            (1<<TIF_LOGADE)
 #define _TIF_32BIT_REGS                (1<<TIF_32BIT_REGS)
index 3e7141f0746c4617bbea24459ef5b13ec41afa87..4689030538839b796cd76567b495bef494a8c0e7 100644 (file)
@@ -7,6 +7,3 @@ config JZ4740_QI_LB60
        bool "Qi Hardware Ben NanoNote"
 
 endchoice
-
-config HAVE_PWM
-       bool
index e44abea9c209ef1c2e035373333e671a876b0093..63bad0e491d0892b6acb2ea68817f272145b669a 100644 (file)
@@ -5,7 +5,7 @@
 # Object file lists.
 
 obj-y += prom.o irq.o time.o reset.o setup.o dma.o \
-       gpio.o clock.o platform.o timer.o pwm.o serial.o
+       gpio.o clock.o platform.o timer.o serial.o
 
 obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
 
index 9a3d9de4d04ef219faee3f832027c1416e92e61c..43d964d3628803102f4384bf734de428cb3049a4 100644 (file)
@@ -437,6 +437,7 @@ static struct platform_device *jz_platform_devices[] __initdata = {
        &jz4740_codec_device,
        &jz4740_rtc_device,
        &jz4740_adc_device,
+       &jz4740_pwm_device,
        &qi_lb60_gpio_keys,
        &qi_lb60_pwm_beeper,
        &qi_lb60_charger_device,
index e342ed4cbd4378c84749ae7e77406a131cec7c1c..6d14dcdbd9083639ebb7a73f3ab0edc00aada7c8 100644 (file)
@@ -323,3 +323,9 @@ struct platform_device jz4740_wdt_device = {
        .num_resources = ARRAY_SIZE(jz4740_wdt_resources),
        .resource      = jz4740_wdt_resources,
 };
+
+/* PWM */
+struct platform_device jz4740_pwm_device = {
+       .name = "jz4740-pwm",
+       .id   = -1,
+};
diff --git a/arch/mips/jz4740/pwm.c b/arch/mips/jz4740/pwm.c
deleted file mode 100644 (file)
index a26a6fa..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *  JZ4740 platform PWM support
- *
- *  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.
- *
- *  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/clk.h>
-#include <linux/err.h>
-#include <linux/pwm.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-jz4740/gpio.h>
-#include "timer.h"
-
-static struct clk *jz4740_pwm_clk;
-
-DEFINE_MUTEX(jz4740_pwm_mutex);
-
-struct pwm_device {
-       unsigned int id;
-       unsigned int gpio;
-       bool used;
-};
-
-static struct pwm_device jz4740_pwm_list[] = {
-       { 2, JZ_GPIO_PWM2, false },
-       { 3, JZ_GPIO_PWM3, false },
-       { 4, JZ_GPIO_PWM4, false },
-       { 5, JZ_GPIO_PWM5, false },
-       { 6, JZ_GPIO_PWM6, false },
-       { 7, JZ_GPIO_PWM7, false },
-};
-
-struct pwm_device *pwm_request(int id, const char *label)
-{
-       int ret = 0;
-       struct pwm_device *pwm;
-
-       if (id < 2 || id > 7 || !jz4740_pwm_clk)
-               return ERR_PTR(-ENODEV);
-
-       mutex_lock(&jz4740_pwm_mutex);
-
-       pwm = &jz4740_pwm_list[id - 2];
-       if (pwm->used)
-               ret = -EBUSY;
-       else
-               pwm->used = true;
-
-       mutex_unlock(&jz4740_pwm_mutex);
-
-       if (ret)
-               return ERR_PTR(ret);
-
-       ret = gpio_request(pwm->gpio, label);
-
-       if (ret) {
-               printk(KERN_ERR "Failed to request pwm gpio: %d\n", ret);
-               pwm->used = false;
-               return ERR_PTR(ret);
-       }
-
-       jz_gpio_set_function(pwm->gpio, JZ_GPIO_FUNC_PWM);
-
-       jz4740_timer_start(id);
-
-       return pwm;
-}
-
-void pwm_free(struct pwm_device *pwm)
-{
-       pwm_disable(pwm);
-       jz4740_timer_set_ctrl(pwm->id, 0);
-
-       jz_gpio_set_function(pwm->gpio, JZ_GPIO_FUNC_NONE);
-       gpio_free(pwm->gpio);
-
-       jz4740_timer_stop(pwm->id);
-
-       pwm->used = false;
-}
-
-int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
-{
-       unsigned long long tmp;
-       unsigned long period, duty;
-       unsigned int prescaler = 0;
-       unsigned int id = pwm->id;
-       uint16_t ctrl;
-       bool is_enabled;
-
-       if (duty_ns < 0 || duty_ns > period_ns)
-               return -EINVAL;
-
-       tmp = (unsigned long long)clk_get_rate(jz4740_pwm_clk) * period_ns;
-       do_div(tmp, 1000000000);
-       period = tmp;
-
-       while (period > 0xffff && prescaler < 6) {
-               period >>= 2;
-               ++prescaler;
-       }
-
-       if (prescaler == 6)
-               return -EINVAL;
-
-       tmp = (unsigned long long)period * duty_ns;
-       do_div(tmp, period_ns);
-       duty = period - tmp;
-
-       if (duty >= period)
-               duty = period - 1;
-
-       is_enabled = jz4740_timer_is_enabled(id);
-       if (is_enabled)
-               pwm_disable(pwm);
-
-       jz4740_timer_set_count(id, 0);
-       jz4740_timer_set_duty(id, duty);
-       jz4740_timer_set_period(id, period);
-
-       ctrl = JZ_TIMER_CTRL_PRESCALER(prescaler) | JZ_TIMER_CTRL_SRC_EXT |
-               JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN;
-
-       jz4740_timer_set_ctrl(id, ctrl);
-
-       if (is_enabled)
-               pwm_enable(pwm);
-
-       return 0;
-}
-
-int pwm_enable(struct pwm_device *pwm)
-{
-       uint32_t ctrl = jz4740_timer_get_ctrl(pwm->id);
-
-       ctrl |= JZ_TIMER_CTRL_PWM_ENABLE;
-       jz4740_timer_set_ctrl(pwm->id, ctrl);
-       jz4740_timer_enable(pwm->id);
-
-       return 0;
-}
-
-void pwm_disable(struct pwm_device *pwm)
-{
-       uint32_t ctrl = jz4740_timer_get_ctrl(pwm->id);
-
-       ctrl &= ~JZ_TIMER_CTRL_PWM_ENABLE;
-       jz4740_timer_disable(pwm->id);
-       jz4740_timer_set_ctrl(pwm->id, ctrl);
-}
-
-static int __init jz4740_pwm_init(void)
-{
-       int ret = 0;
-
-       jz4740_pwm_clk = clk_get(NULL, "ext");
-
-       if (IS_ERR(jz4740_pwm_clk)) {
-               ret = PTR_ERR(jz4740_pwm_clk);
-               jz4740_pwm_clk = NULL;
-       }
-
-       return ret;
-}
-subsys_initcall(jz4740_pwm_init);
index f83c2dd07a2732ab61972d353546bdbad137b307..39bb4bbf43e7073e9327a634f221f5c1942b2855 100644 (file)
 #include <linux/clockchips.h>
 
 #include <asm/mach-jz4740/irq.h>
+#include <asm/mach-jz4740/timer.h>
 #include <asm/time.h>
 
 #include "clock.h"
-#include "timer.h"
 
 #define TIMER_CLOCKEVENT 0
 #define TIMER_CLOCKSOURCE 1
index 654d5c3900b66282a06c0a0a6a02383a957c3a72..22f11d73a17d85833da49c9692efa162a0564c4a 100644 (file)
 #include <linux/kernel.h>
 #include <linux/module.h>
 
-#include "timer.h"
-
 #include <asm/mach-jz4740/base.h>
+#include <asm/mach-jz4740/timer.h>
 
 void __iomem *jz4740_timer_base;
+EXPORT_SYMBOL_GPL(jz4740_timer_base);
 
 void jz4740_timer_enable_watchdog(void)
 {
diff --git a/arch/mips/jz4740/timer.h b/arch/mips/jz4740/timer.h
deleted file mode 100644 (file)
index fca3994..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *  JZ4740 platform timer support
- *
- *  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.
- *
- *  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 __MIPS_JZ4740_TIMER_H__
-#define __MIPS_JZ4740_TIMER_H__
-
-#include <linux/module.h>
-#include <linux/io.h>
-
-#define JZ_REG_TIMER_STOP              0x0C
-#define JZ_REG_TIMER_STOP_SET          0x1C
-#define JZ_REG_TIMER_STOP_CLEAR                0x2C
-#define JZ_REG_TIMER_ENABLE            0x00
-#define JZ_REG_TIMER_ENABLE_SET                0x04
-#define JZ_REG_TIMER_ENABLE_CLEAR      0x08
-#define JZ_REG_TIMER_FLAG              0x10
-#define JZ_REG_TIMER_FLAG_SET          0x14
-#define JZ_REG_TIMER_FLAG_CLEAR                0x18
-#define JZ_REG_TIMER_MASK              0x20
-#define JZ_REG_TIMER_MASK_SET          0x24
-#define JZ_REG_TIMER_MASK_CLEAR                0x28
-
-#define JZ_REG_TIMER_DFR(x) (((x) * 0x10) + 0x30)
-#define JZ_REG_TIMER_DHR(x) (((x) * 0x10) + 0x34)
-#define JZ_REG_TIMER_CNT(x) (((x) * 0x10) + 0x38)
-#define JZ_REG_TIMER_CTRL(x) (((x) * 0x10) + 0x3C)
-
-#define JZ_TIMER_IRQ_HALF(x) BIT((x) + 0x10)
-#define JZ_TIMER_IRQ_FULL(x) BIT(x)
-
-#define JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN     BIT(9)
-#define JZ_TIMER_CTRL_PWM_ACTIVE_LOW           BIT(8)
-#define JZ_TIMER_CTRL_PWM_ENABLE               BIT(7)
-#define JZ_TIMER_CTRL_PRESCALE_MASK            0x1c
-#define JZ_TIMER_CTRL_PRESCALE_OFFSET          0x3
-#define JZ_TIMER_CTRL_PRESCALE_1               (0 << 3)
-#define JZ_TIMER_CTRL_PRESCALE_4               (1 << 3)
-#define JZ_TIMER_CTRL_PRESCALE_16              (2 << 3)
-#define JZ_TIMER_CTRL_PRESCALE_64              (3 << 3)
-#define JZ_TIMER_CTRL_PRESCALE_256             (4 << 3)
-#define JZ_TIMER_CTRL_PRESCALE_1024            (5 << 3)
-
-#define JZ_TIMER_CTRL_PRESCALER(x) ((x) << JZ_TIMER_CTRL_PRESCALE_OFFSET)
-
-#define JZ_TIMER_CTRL_SRC_EXT          BIT(2)
-#define JZ_TIMER_CTRL_SRC_RTC          BIT(1)
-#define JZ_TIMER_CTRL_SRC_PCLK         BIT(0)
-
-extern void __iomem *jz4740_timer_base;
-void __init jz4740_timer_init(void);
-
-static inline void jz4740_timer_stop(unsigned int timer)
-{
-       writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_SET);
-}
-
-static inline void jz4740_timer_start(unsigned int timer)
-{
-       writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR);
-}
-
-static inline bool jz4740_timer_is_enabled(unsigned int timer)
-{
-       return readb(jz4740_timer_base + JZ_REG_TIMER_ENABLE) & BIT(timer);
-}
-
-static inline void jz4740_timer_enable(unsigned int timer)
-{
-       writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_SET);
-}
-
-static inline void jz4740_timer_disable(unsigned int timer)
-{
-       writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_CLEAR);
-}
-
-
-static inline void jz4740_timer_set_period(unsigned int timer, uint16_t period)
-{
-       writew(period, jz4740_timer_base + JZ_REG_TIMER_DFR(timer));
-}
-
-static inline void jz4740_timer_set_duty(unsigned int timer, uint16_t duty)
-{
-       writew(duty, jz4740_timer_base + JZ_REG_TIMER_DHR(timer));
-}
-
-static inline void jz4740_timer_set_count(unsigned int timer, uint16_t count)
-{
-       writew(count, jz4740_timer_base + JZ_REG_TIMER_CNT(timer));
-}
-
-static inline uint16_t jz4740_timer_get_count(unsigned int timer)
-{
-       return readw(jz4740_timer_base + JZ_REG_TIMER_CNT(timer));
-}
-
-static inline void jz4740_timer_ack_full(unsigned int timer)
-{
-       writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR);
-}
-
-static inline void jz4740_timer_irq_full_enable(unsigned int timer)
-{
-       writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR);
-       writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_CLEAR);
-}
-
-static inline void jz4740_timer_irq_full_disable(unsigned int timer)
-{
-       writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_SET);
-}
-
-static inline void jz4740_timer_set_ctrl(unsigned int timer, uint16_t ctrl)
-{
-       writew(ctrl, jz4740_timer_base + JZ_REG_TIMER_CTRL(timer));
-}
-
-static inline uint16_t jz4740_timer_get_ctrl(unsigned int timer)
-{
-       return readw(jz4740_timer_base + JZ_REG_TIMER_CTRL(timer));
-}
-
-#endif
index f4546e97c60db111215495f924aa567595c39581..23817a6e32b606cde0a3a714c810db342b91fd0f 100644 (file)
@@ -283,6 +283,15 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
        struct pt_regs *regs = args->regs;
        int trap = (regs->cp0_cause & 0x7c) >> 2;
 
+#ifdef CONFIG_KPROBES
+       /*
+        * Return immediately if the kprobes fault notifier has set
+        * DIE_PAGE_FAULT.
+        */
+       if (cmd == DIE_PAGE_FAULT)
+               return NOTIFY_DONE;
+#endif /* CONFIG_KPROBES */
+
        /* Userspace events, ignore. */
        if (user_mode(regs))
                return NOTIFY_DONE;
index 922a554cd10802336aa5c23ce030dcbf8432c017..3a21acedf88231403703c3ca842916f325f88a6f 100644 (file)
@@ -83,13 +83,13 @@ out:
 asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs)
 {
        int error;
-       char * filename;
+       struct filename *filename;
 
        filename = getname(compat_ptr(regs.regs[4]));
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = compat_do_execve(filename, compat_ptr(regs.regs[5]),
+       error = compat_do_execve(filename->name, compat_ptr(regs.regs[5]),
                                 compat_ptr(regs.regs[6]), &regs);
        putname(filename);
 
index b08220c82113ccd4a30a2dceac6832e2c199fabc..2bd561bc05ae2b4e7b814ac866d21faaddd046a2 100644 (file)
@@ -133,13 +133,13 @@ _sys_clone(nabi_no_regargs struct pt_regs regs)
 asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs)
 {
        int error;
-       char * filename;
+       struct filename *filename;
 
        filename = getname((const char __user *) (long)regs.regs[4]);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename,
+       error = do_execve(filename->name,
                          (const char __user *const __user *) (long)regs.regs[5],
                          (const char __user *const __user *) (long)regs.regs[6],
                          &regs);
index 5cfb086b39034417208a3efd4a708c5835c91db7..ddbdc33471a830b152ec1f5cb3dcf9912d805fda 100644 (file)
@@ -8,6 +8,7 @@ config MN10300
        select HAVE_ARCH_KGDB
        select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER
        select GENERIC_CLOCKEVENTS
+       select GENERIC_KERNEL_THREAD
 
 config AM33_2
        def_bool n
index 0d20f5526dd8e99b7ba770d677bc17480f4bdb40..fccd81eddff1f6de89b07cc13c362809364c9507 100644 (file)
@@ -1,3 +1,4 @@
 include include/asm-generic/Kbuild.asm
 
 generic-y += clkdev.h
+generic-y += exec.h
diff --git a/arch/mn10300/include/asm/exec.h b/arch/mn10300/include/asm/exec.h
deleted file mode 100644 (file)
index c74e367..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/* 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 2ee58e3eb6b355b75166bf57334c01498a66b8fd..1c3eb4fda9588a57e555bf8ead8757f8952eb7a8 100644 (file)
@@ -61,7 +61,7 @@
 ###############################################################################
 .macro RESTORE_ALL
        # peel back the stack to the calling frame
-       # - this permits execve() to discard extra frames due to kernel syscalls
+       # - we need that when returning from interrupts to kernel mode
        GET_THREAD_INFO a0
        mov     (TI_frame,a0),fp
        mov     fp,sp
index 247928c9f549ec239e1e5556a1c7157674833bba..8b80b19d0c8a4fbfe7406f12141ae6d12040fd35 100644 (file)
@@ -119,31 +119,19 @@ struct thread_struct {
 
 /*
  * do necessary setup to start up a newly executed thread
- * - need to discard the frame stacked by the kernel thread invoking the execve
- *   syscall (see RESTORE_ALL macro)
  */
 static inline void start_thread(struct pt_regs *regs,
                                unsigned long new_pc, unsigned long new_sp)
 {
-       struct thread_info *ti = current_thread_info();
-       struct pt_regs *frame0;
-
-       frame0 = thread_info_to_uregs(ti);
-       frame0->epsw = EPSW_nSL | EPSW_IE | EPSW_IM;
-       frame0->pc = new_pc;
-       frame0->sp = new_sp;
-       ti->frame = frame0;
+       regs->epsw = EPSW_nSL | EPSW_IE | EPSW_IM;
+       regs->pc = new_pc;
+       regs->sp = new_sp;
 }
 
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
-/*
- * create a kernel thread without removing it from tasklists
- */
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 /*
  * Return saved PC of a blocked thread.
  */
index 44251b974f1d96d4931e4704d9433163eb070962..08ac856c053e67f915958fdbe5f20d67c48970ae 100644 (file)
@@ -86,6 +86,7 @@ struct pt_regs {
 #define user_mode(regs)                        (((regs)->epsw & EPSW_nSL) == EPSW_nSL)
 #define instruction_pointer(regs)      ((regs)->pc)
 #define user_stack_pointer(regs)       ((regs)->sp)
+#define current_pt_regs()              current_frame()
 
 #define arch_has_single_step() (1)
 
index ac519bbd42ffe32693a02d3f88ac5dbd21d426ff..f90062b0622df11c2f049830f185adefa4a60b22 100644 (file)
@@ -160,12 +160,13 @@ void arch_release_thread_info(struct thread_info *ti);
 #define _TIF_SIGPENDING                +(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      +(1 << TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP                +(1 << TIF_SINGLESTEP)
-#define _TIF_RESTORE_SIGMASK   +(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_POLLING_NRFLAG    +(1 << TIF_POLLING_NRFLAG)
 
 #define _TIF_WORK_MASK         0x0000FFFE      /* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK      0x0000FFFF      /* work to do on any return to u-space */
 
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_THREAD_INFO_H */
index 866eb14749d7701cb4dafce5566d8aa00df18fe6..044c770adbb65bc11fe2332d645d7b1c06a29640 100644 (file)
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
index d06749173d639dd66f4ce32358ff199b88b5ae09..561029f7fa4489259297225313ffa7b6d028817a 100644 (file)
@@ -7,8 +7,8 @@ fpu-obj-y := fpu-nofpu.o fpu-nofpu-low.o
 fpu-obj-$(CONFIG_FPU) := fpu.o fpu-low.o
 
 obj-y   := process.o signal.o entry.o traps.o irq.o \
-          ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
-          switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y) \
+          ptrace.o setup.o time.o sys_mn10300.o io.o \
+          switch_to.o mn10300_ksyms.o $(fpu-obj-y) \
           csrc-mn10300.o cevt-mn10300.o
 
 obj-$(CONFIG_SMP) += smp.o smp-low.o
index 8e11f9f48999e172437a925bb9713a2c9c1236c2..0c631d34c8d7f1f73807b4f46c8114ea430a3154 100644 (file)
@@ -55,6 +55,20 @@ ENTRY(ret_from_fork)
        mov     d0,(REG_D0,fp)
        jmp     syscall_exit
 
+ENTRY(ret_from_kernel_thread)
+       call    schedule_tail[],0
+       mov     (REG_D0,fp),d0
+       mov     (REG_A0,fp),a0
+       calls   (a0)
+       jmp     sys_exit
+
+ENTRY(ret_from_kernel_execve)
+       add     -12,d0  /* pt_regs -> frame */
+       mov     d0,sp
+       GET_THREAD_INFO a2
+       clr     d0
+       jmp     syscall_exit
+
 ###############################################################################
 #
 # system call handler
@@ -94,6 +108,10 @@ restore_all:
 ###############################################################################
        ALIGN
 syscall_exit_work:
+       mov     (REG_EPSW,fp),d0
+       and     EPSW_nSL,d0
+       beq     resume_kernel           # returning to supervisor mode
+
        btst    _TIF_SYSCALL_TRACE,d2
        beq     work_pending
        LOCAL_IRQ_ENABLE                # could let syscall_trace_exit() call
index 2df440105a80f78e111f4f863261cbb7abab10ae..561785581f6c21382e9e17b5e1566a5c4ed1c20e 100644 (file)
 struct clocksource;
 struct clock_event_device;
 
-/*
- * kthread.S
- */
-extern int kernel_thread_helper(int);
-
 /*
  * entry.S
  */
 extern void ret_from_fork(struct task_struct *) __attribute__((noreturn));
+extern void ret_from_kernel_thread(struct task_struct *) __attribute__((noreturn));
 
 /*
  * smp-low.S
diff --git a/arch/mn10300/kernel/kernel_execve.S b/arch/mn10300/kernel/kernel_execve.S
deleted file mode 100644 (file)
index 86039f1..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* MN10300 In-kernel program execution
- *
- * 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.
- */
-#include <linux/linkage.h>
-#include <asm/unistd.h>
-
-###############################################################################
-#
-# Do a system call from kernel instead of calling sys_execve so we end up with
-# proper pt_regs.
-#
-# int kernel_execve(const char *filename, char *const argv[],
-#                  char *const envp[])
-#
-# On entry: D0/D1/8(SP): arguments to function
-# On return: D0: syscall return.
-#
-###############################################################################
-       .globl          kernel_execve
-       .type           kernel_execve,@function
-kernel_execve:
-       mov             a3,a1
-       mov             d0,a0
-       mov             (12,sp),a3
-       mov             +__NR_execve,d0
-       syscall         0
-       mov             a1,a3
-       rets
-
-       .size           kernel_execve,.-kernel_execve
diff --git a/arch/mn10300/kernel/kthread.S b/arch/mn10300/kernel/kthread.S
deleted file mode 100644 (file)
index b5ae467..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/* MN10300 Kernel thread trampoline function
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by Mark Salter (msalter@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.
- */
-       .text
-
-###############################################################################
-#
-# kernel_thread_helper - trampoline for kernel_thread()
-#
-# On entry:
-#   A2 = address of function to call
-#   D2 = function argument
-#
-###############################################################################
-       .globl  kernel_thread_helper
-       .type   kernel_thread_helper,@function
-kernel_thread_helper:
-       mov     do_exit,d1
-       mov     d1,(sp)
-       mov     d1,mdr
-       mov     d2,d0
-       jmp     (a2)
-
-       .size   kernel_thread_helper,.-kernel_thread_helper
index e9cceba193b6510f50acd8419a4a2498f82ff64f..d0c671b6d9ffc18f687b5d45b99697f891686583 100644 (file)
@@ -164,27 +164,6 @@ void show_regs(struct pt_regs *regs)
 {
 }
 
-/*
- * create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-
-       regs.a2 = (unsigned long) fn;
-       regs.d2 = (unsigned long) arg;
-       regs.pc = (unsigned long) kernel_thread_helper;
-       local_save_flags(regs.epsw);
-       regs.epsw |= EPSW_IE | EPSW_IM_7;
-
-       /* Ok, create the new process.. */
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0,
-                      NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 /*
  * free current thread data structures etc..
  */
@@ -230,50 +209,42 @@ int copy_thread(unsigned long clone_flags,
                struct task_struct *p, struct pt_regs *kregs)
 {
        struct thread_info *ti = task_thread_info(p);
-       struct pt_regs *c_uregs, *c_kregs, *uregs;
+       struct pt_regs *c_regs;
        unsigned long c_ksp;
 
-       uregs = current->thread.uregs;
-
        c_ksp = (unsigned long) task_stack_page(p) + THREAD_SIZE;
 
        /* allocate the userspace exception frame and set it up */
        c_ksp -= sizeof(struct pt_regs);
-       c_uregs = (struct pt_regs *) c_ksp;
+       c_regs = (struct pt_regs *) c_ksp;
+       c_ksp -= 12; /* allocate function call ABI slack */
 
-       p->thread.uregs = c_uregs;
-       *c_uregs = *uregs;
-       c_uregs->sp = c_usp;
-       c_uregs->epsw &= ~EPSW_FE; /* my FPU */
+       /* set up things up so the scheduler can start the new task */
+       p->thread.uregs = c_regs;
+       ti->frame       = c_regs;
+       p->thread.a3    = (unsigned long) c_regs;
+       p->thread.sp    = c_ksp;
+       p->thread.wchan = p->thread.pc;
+       p->thread.usp   = c_usp;
 
-       c_ksp -= 12; /* allocate function call ABI slack */
+       if (unlikely(!kregs)) {
+               memset(c_regs, 0, sizeof(struct pt_regs));
+               c_regs->a0 = c_usp; /* function */
+               c_regs->d0 = ustk_size; /* argument */
+               local_save_flags(c_regs->epsw);
+               c_regs->epsw |= EPSW_IE | EPSW_IM_7;
+               p->thread.pc    = (unsigned long) ret_from_kernel_thread;
+               return 0;
+       }
+       *c_regs = *kregs;
+       c_regs->sp = c_usp;
+       c_regs->epsw &= ~EPSW_FE; /* my FPU */
 
        /* the new TLS pointer is passed in as arg #5 to sys_clone() */
        if (clone_flags & CLONE_SETTLS)
-               c_uregs->e2 = current_frame()->d3;
-
-       /* set up the return kernel frame if called from kernel_thread() */
-       c_kregs = c_uregs;
-       if (kregs != uregs) {
-               c_ksp -= sizeof(struct pt_regs);
-               c_kregs = (struct pt_regs *) c_ksp;
-               *c_kregs = *kregs;
-               c_kregs->sp = c_usp;
-               c_kregs->next = c_uregs;
-#ifdef CONFIG_MN10300_CURRENT_IN_E2
-               c_kregs->e2 = (unsigned long) p; /* current */
-#endif
-
-               c_ksp -= 12; /* allocate function call ABI slack */
-       }
+               c_regs->e2 = current_frame()->d3;
 
-       /* set up things up so the scheduler can start the new task */
-       ti->frame       = c_kregs;
-       p->thread.a3    = (unsigned long) c_kregs;
-       p->thread.sp    = c_ksp;
        p->thread.pc    = (unsigned long) ret_from_fork;
-       p->thread.wchan = (unsigned long) ret_from_fork;
-       p->thread.usp   = c_usp;
 
        return 0;
 }
@@ -302,22 +273,6 @@ asmlinkage long sys_vfork(void)
                       current_frame(), 0, NULL, NULL);
 }
 
-asmlinkage long sys_execve(const char __user *name,
-                          const char __user *const __user *argv,
-                          const char __user *const __user *envp)
-{
-       char *filename;
-       int error;
-
-       filename = getname(name);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               return error;
-       error = do_execve(filename, argv, envp, current_frame());
-       putname(filename);
-       return error;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
        return p->thread.wchan;
index 4d584ae29ae1c1c2c53746ee3a6d1d9b78e7042a..f570b3085ef90004d2150eca7f86107ea232cf1e 100644 (file)
@@ -317,10 +317,6 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
        regs->d0 = sig;
        regs->d1 = (unsigned long) &frame->sc;
 
-       /* the tracer may want to single-step inside the handler */
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
 #if DEBUG_SIG
        printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
               sig, current->comm, current->pid, frame, regs->pc,
@@ -398,10 +394,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->d0 = sig;
        regs->d1 = (long) &frame->info;
 
-       /* the tracer may want to single-step inside the handler */
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
 #if DEBUG_SIG
        printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
               sig, current->comm, current->pid, frame, regs->pc,
@@ -475,11 +467,6 @@ static void do_signal(struct pt_regs *regs)
        siginfo_t info;
        int signr;
 
-       /* we want the common case to go fast, which is why we may in certain
-        * cases get here from kernel mode */
-       if (!user_mode(regs))
-               return;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                if (handle_signal(signr, &info, &ka, regs) == 0) {
index 07a8bc080ef2e25508cbded379a2e94b9531adad..07f3212422adf916f2dfa590f492eb7a4dc517ad 100644 (file)
@@ -121,7 +121,6 @@ register struct thread_info *current_thread_info_reg asm("r10");
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP                (1<<TIF_SINGLESTEP)
-#define _TIF_RESTORE_SIGMASK     (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 
 
@@ -129,6 +128,8 @@ register struct thread_info *current_thread_info_reg asm("r10");
 /* For OpenRISC, this is anything in the LSW other than syscall trace */
 #define _TIF_WORK_MASK (0xff & ~(_TIF_SYSCALL_TRACE|_TIF_SINGLESTEP))
 
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_THREAD_INFO_H */
index 55210f37d1a3e2a74ed1a30cc8cad3e6c600231f..c35f3ab1a8d34749d3f32648e82d826f27f350e1 100644 (file)
@@ -271,7 +271,7 @@ asmlinkage long _sys_execve(const char __user *name,
                            struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(name);
        error = PTR_ERR(filename);
@@ -279,7 +279,7 @@ asmlinkage long _sys_execve(const char __user *name,
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
 
 out:
index 6785de7bd2a0298c58f025bda474b037e3ea07f9..a0760b87fd4ec8c5c8531de43833a12fdd97bad1 100644 (file)
 int hpux_execve(struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname((const char __user *) regs->gr[26]);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename,
+       error = do_execve(filename->name,
                          (const char __user *const __user *) regs->gr[25],
                          (const char __user *const __user *) regs->gr[24],
                          regs);
index 38a1c1b8d4e8e11093b3a35db9d95ca98749ed1a..011468857e9801fe850164655bddf840d3e4f2ea 100644 (file)
@@ -71,7 +71,7 @@ ENTRY(hpux_gateway_page)
        STREG   %r26, TASK_PT_GR26(%r1)         /* 1st argument */
        STREG   %r27, TASK_PT_GR27(%r1)         /* user dp */
        STREG   %r28, TASK_PT_GR28(%r1)         /* return value 0 */
-       STREG   %r28, TASK_PT_ORIG_R28(%r1)     /* return value 0 (saved for signals) */
+       STREG   %r0, TASK_PT_ORIG_R28(%r1)     /* don't prohibit restarts */
        STREG   %r29, TASK_PT_GR29(%r1)         /* 8th argument */
        STREG   %r31, TASK_PT_GR31(%r1)         /* preserve syscall return ptr */
        
index 0587f62e5b76027291cea9dd62954d230cc38c06..458371a1565aa2fdcbaa75e27ab398d8741019a9 100644 (file)
@@ -3,3 +3,4 @@ include include/asm-generic/Kbuild.asm
 header-y += pdc.h
 generic-y += clkdev.h
 generic-y += word-at-a-time.h
+generic-y += exec.h
diff --git a/arch/parisc/include/asm/exec.h b/arch/parisc/include/asm/exec.h
deleted file mode 100644 (file)
index 6bb5af7..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __PARISC_EXEC_H
-#define __PARISC_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* __PARISC_EXEC_H */
index 22b4726dee494403c80bdf2f88c583ba32043b94..d1fb79a36f3d32f1632772d6fb366b8416c96a17 100644 (file)
@@ -68,13 +68,16 @@ struct thread_info {
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
 #define _TIF_32BIT             (1 << TIF_32BIT)
-#define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
 #define _TIF_SINGLESTEP                (1 << TIF_SINGLESTEP)
 #define _TIF_BLOCKSTEP         (1 << TIF_BLOCKSTEP)
 
 #define _TIF_USER_WORK_MASK     (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \
                                  _TIF_NEED_RESCHED)
+#define _TIF_SYSCALL_TRACE_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP |        \
+                                _TIF_BLOCKSTEP)
+
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
 
 #endif /* __KERNEL__ */
 
index 8c6b6b6561f0de7025ea5a24b6fed7cb2e6dc677..cbc37216bf90f2fa5c64b5b1956272b9db237b8f 100644 (file)
@@ -342,13 +342,13 @@ unsigned long thread_saved_pc(struct task_struct *t)
 asmlinkage int sys_execve(struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname((const char __user *) regs->gr[26]);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename,
+       error = do_execve(filename->name,
                          (const char __user *const __user *) regs->gr[25],
                          (const char __user *const __user *) regs->gr[24],
                          regs);
index 594459bde14ed3c927b7dddce88e1d9cf9863e74..53799695599872565f1ad8c387cbf0e1b91ceb3d 100644 (file)
@@ -113,6 +113,8 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
                (usp - sigframe_size);
        DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
 
+       regs->orig_r28 = 1; /* no restarts for sigreturn */
+
 #ifdef CONFIG_64BIT
        compat_frame = (struct compat_rt_sigframe __user *)frame;
        
@@ -437,7 +439,7 @@ give_sigsegv:
  * OK, we're invoking a handler.
  */    
 
-static long
+static void
 handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
                struct pt_regs *regs, int in_syscall)
 {
@@ -447,7 +449,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        
        /* Set up the stack frame */
        if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
-               return 0;
+               return;
 
        signal_delivered(sig, info, ka, regs, 
                test_thread_flag(TIF_SINGLESTEP) ||
@@ -455,13 +457,14 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 
        DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
                regs->gr[28]);
-
-       return 1;
 }
 
 static inline void
 syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
 {
+       if (regs->orig_r28)
+               return;
+       regs->orig_r28 = 1; /* no more restarts */
        /* Check the return code */
        switch (regs->gr[28]) {
        case -ERESTART_RESTARTBLOCK:
@@ -482,8 +485,6 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
                 * we have to do is fiddle the return pointer.
                 */
                regs->gr[31] -= 8; /* delayed branching */
-               /* Preserve original r28. */
-               regs->gr[28] = regs->orig_r28;
                break;
        }
 }
@@ -491,6 +492,9 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
 static inline void
 insert_restart_trampoline(struct pt_regs *regs)
 {
+       if (regs->orig_r28)
+               return;
+       regs->orig_r28 = 1; /* no more restarts */
        switch(regs->gr[28]) {
        case -ERESTART_RESTARTBLOCK: {
                /* Restart the system call - no handlers present */
@@ -525,9 +529,6 @@ insert_restart_trampoline(struct pt_regs *regs)
                flush_user_icache_range(regs->gr[30], regs->gr[30] + 4);
 
                regs->gr[31] = regs->gr[30] + 8;
-               /* Preserve original r28. */
-               regs->gr[28] = regs->orig_r28;
-
                return;
        }
        case -ERESTARTNOHAND:
@@ -539,9 +540,6 @@ insert_restart_trampoline(struct pt_regs *regs)
                 * slot of the branch external instruction.
                 */
                regs->gr[31] -= 8;
-               /* Preserve original r28. */
-               regs->gr[28] = regs->orig_r28;
-
                return;
        }
        default:
@@ -570,30 +568,17 @@ do_signal(struct pt_regs *regs, long in_syscall)
        DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
               regs, regs->sr[7], in_syscall);
 
-       /* Everyone else checks to see if they are in kernel mode at
-          this point and exits if that's the case.  I'm not sure why
-          we would be called in that case, but for some reason we
-          are. */
-
-       /* May need to force signal if handle_signal failed to deliver */
-       while (1) {
-               signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-               DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); 
+       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+       DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); 
        
-               if (signr <= 0)
-                 break;
-               
+       if (signr > 0) {
                /* Restart a system call if necessary. */
                if (in_syscall)
                        syscall_restart(regs, &ka);
 
-               /* Whee!  Actually deliver the signal.  If the
-                  delivery failed, we need to continue to iterate in
-                  this loop so we can deliver the SIGSEGV... */
-               if (handle_signal(signr, &info, &ka, regs, in_syscall))
-                       return;
+               handle_signal(signr, &info, &ka, regs, in_syscall);
+               return;
        }
-       /* end of while(1) looping forever if we can't force a signal */
 
        /* Did we come from a system call? */
        if (in_syscall)
index dc9a624623233e0e9f084e3659e65e37bf28df47..bf5b93a885d3cc6eb1b6ccd2ded74223b6cd2d32 100644 (file)
 asmlinkage int sys32_execve(struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));
        filename = getname((const char __user *) regs->gr[26]);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = compat_do_execve(filename, compat_ptr(regs->gr[25]),
+       error = compat_do_execve(filename->name, compat_ptr(regs->gr[25]),
                                 compat_ptr(regs->gr[24]), regs);
        putname(filename);
 out:
index 82a52b2fb13f296ef65726afc51b38f12e420047..86742df0b1941b4599c4cf0be76e9be48445bfef 100644 (file)
@@ -156,7 +156,7 @@ linux_gateway_entry:
        STREG   %r26, TASK_PT_GR26(%r1)         /* 1st argument */
        STREG   %r27, TASK_PT_GR27(%r1)         /* user dp */
        STREG   %r28, TASK_PT_GR28(%r1)         /* return value 0 */
-       STREG   %r28, TASK_PT_ORIG_R28(%r1)     /* return value 0 (saved for signals) */
+       STREG   %r0, TASK_PT_ORIG_R28(%r1)      /* don't prohibit restarts */
        STREG   %r29, TASK_PT_GR29(%r1)         /* return value 1 */
        STREG   %r31, TASK_PT_GR31(%r1)         /* preserve syscall return ptr */
        
@@ -180,9 +180,10 @@ linux_gateway_entry:
 
        /* Are we being ptraced? */
        mfctl   %cr30, %r1
-       LDREG   TI_TASK(%r1),%r1
-       ldw     TASK_PTRACE(%r1), %r1
-       bb,<,n  %r1,31,.Ltracesys
+       LDREG   TI_FLAGS(%r1),%r1
+       ldi     _TIF_SYSCALL_TRACE_MASK, %r19
+       and,COND(=) %r1, %r19, %r0
+       b,n     .Ltracesys
        
        /* Note!  We cannot use the syscall table that is mapped
        nearby since the gateway page is mapped execute-only. */
index df7edb887a04c85be2c53ec9c12540f2a6440b29..969f3d9ded91941cb4323052df4f465764259608 100644 (file)
@@ -137,10 +137,11 @@ config PPC
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_CMOS_UPDATE
-       select GENERIC_TIME_VSYSCALL
+       select GENERIC_TIME_VSYSCALL_OLD
        select GENERIC_CLOCKEVENTS
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
+       select GENERIC_KERNEL_THREAD
 
 config EARLY_PRINTK
        bool
index 126ef1b08a01bcc80c94e34ff2dd49b776109ecd..e4ad2e27551a096e8af773ec4fb9f231c5d64b03 100644 (file)
@@ -38,7 +38,6 @@ CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_FSL_ELBC=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
index abcf00ad939e4b8c4c340b004b800ddba87e6396..34ff5686be0833781ca864899efbb8dcbb05a658 100644 (file)
@@ -37,7 +37,6 @@ CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
index 9352e4430c3b05419fdff7ee3b3ec91cfeaeee5d..09116c6a6719df021771e8f489ab3c67ee43cf6b 100644 (file)
@@ -50,7 +50,6 @@ CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_FSL_ELBC=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
index 9dc5cd1fde1a9107614709d1082270361ac71882..8734b3855272b3583aa9ba7c723f5e6df01772b1 100644 (file)
@@ -74,9 +74,6 @@ struct task_struct;
 void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
 void release_thread(struct task_struct *);
 
-/* Create a new kernel thread. */
-extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 /* Lazy FPU handling on uni-processor */
 extern struct task_struct *last_task_used_math;
 extern struct task_struct *last_task_used_altivec;
index 55380dc16f918c8977c989e9604a90cebc019fdb..5f995681bc1d4bc83198ac29e266610d187593cc 100644 (file)
@@ -96,6 +96,8 @@ extern unsigned long ptrace_get_reg(struct task_struct *task, int regno);
 extern int ptrace_put_reg(struct task_struct *task, int regno,
                          unsigned long data);
 
+#define current_pt_regs() \
+       ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
 /*
  * We use the least-significant bit of the trap field to indicate
  * whether we have saved the full set of registers, or only a
index 4084e567d28ef0d41b4bc2834270bd80c7e1eaa4..329db4ec12ca855f2180a8edfe5f535a201d0015 100644 (file)
@@ -17,9 +17,6 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
 asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len,
                unsigned long prot, unsigned long flags,
                unsigned long fd, unsigned long pgoff);
-asmlinkage int sys_execve(unsigned long a0, unsigned long a1,
-               unsigned long a2, unsigned long a3, unsigned long a4,
-               unsigned long a5, struct pt_regs *regs);
 asmlinkage int sys_clone(unsigned long clone_flags, unsigned long usp,
                int __user *parent_tidp, void __user *child_threadptr,
                int __user *child_tidp, int p6, struct pt_regs *regs);
index 8ceea14d6fe44a20d0d807e28a4ca63477f18863..406b7b9a13412f3736c369f500a5022e4955a928 100644 (file)
@@ -182,6 +182,8 @@ static inline bool test_thread_local_flags(unsigned int flags)
 #define is_32bit_task()        (1)
 #endif
 
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
index d974bca0c33dbcfe92ce1e06e69d873dcc85e552..921dce6d84458d3ef02b7b8ea1a6590809c226ef 100644 (file)
@@ -55,6 +55,8 @@
 #define __ARCH_WANT_SYS_NEWFSTATAT
 #define __ARCH_WANT_COMPAT_SYS_SENDFILE
 #endif
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
index af37528da49fff06ef7b47fb2e9add01dd6b1caa..9499385676e784362c20eade975ae396aaff144d 100644 (file)
@@ -435,6 +435,22 @@ ret_from_fork:
        li      r3,0
        b       ret_from_syscall
 
+       .globl  ret_from_kernel_thread
+ret_from_kernel_thread:
+       REST_NVGPRS(r1)
+       bl      schedule_tail
+       mtlr    r14
+       mr      r3,r15
+       PPC440EP_ERR42
+       blrl
+       li      r3,0
+       b       do_exit         # no return
+
+       .globl  __ret_from_kernel_execve
+__ret_from_kernel_execve:
+       addi    r1,r3,-STACK_FRAME_OVERHEAD
+       b       ret_from_syscall
+
 /* Traced system call support */
 syscall_dotrace:
        SAVE_NVGPRS(r1)
index 0e931aaffca20ad2213c1fb0dd2923e409cf75c9..56e0ff0878b5534c76b8c93818f7536498ce52df 100644 (file)
@@ -370,6 +370,22 @@ _GLOBAL(ret_from_fork)
        li      r3,0
        b       syscall_exit
 
+_GLOBAL(ret_from_kernel_thread)
+       bl      .schedule_tail
+       REST_NVGPRS(r1)
+       REST_GPR(2,r1)
+       mtlr    r14
+       mr      r3,r15
+       blrl
+       li      r3,0
+       b       .do_exit        # no return
+
+_GLOBAL(__ret_from_kernel_execve)
+       addi    r1,r3,-STACK_FRAME_OVERHEAD
+       li      r10,1
+       std     r10,SOFTE(r1)
+       b       syscall_exit
+
        .section        ".toc","aw"
 DSCR_DEFAULT:
        .tc dscr_default[TC],dscr_default
index ba16874fe294c003b6d28a65f25da53f8d23097a..7ce26d45777ef1d5497ab778eff937b11204aef3 100644 (file)
@@ -54,13 +54,6 @@ _GLOBAL(add_reloc_offset)
        .align  3
 2:     PPC_LONG 1b
 
-_GLOBAL(kernel_execve)
-       li      r0,__NR_execve
-       sc
-       bnslr
-       neg     r3,r3
-       blr
-
 _GLOBAL(setjmp)
        mflr    r0
        PPC_STL r0,0(r3)
index 407e293aad2fcad29c97be4d88961af12827f357..19e096bd0e73d8b9a530159a4b9b440efc25403f 100644 (file)
@@ -663,39 +663,6 @@ _GLOBAL(abs)
        sub     r3,r3,r4
        blr
 
-/*
- * Create a kernel thread
- *   kernel_thread(fn, arg, flags)
- */
-_GLOBAL(kernel_thread)
-       stwu    r1,-16(r1)
-       stw     r30,8(r1)
-       stw     r31,12(r1)
-       mr      r30,r3          /* function */
-       mr      r31,r4          /* argument */
-       ori     r3,r5,CLONE_VM  /* flags */
-       oris    r3,r3,CLONE_UNTRACED>>16
-       li      r4,0            /* new sp (unused) */
-       li      r0,__NR_clone
-       sc
-       bns+    1f              /* did system call indicate error? */
-       neg     r3,r3           /* if so, make return code negative */
-1:     cmpwi   0,r3,0          /* parent or child? */
-       bne     2f              /* return if parent */
-       li      r0,0            /* make top-level stack frame */
-       stwu    r0,-16(r1)
-       mtlr    r30             /* fn addr in lr */
-       mr      r3,r31          /* load arg and call fn */
-       PPC440EP_ERR42
-       blrl
-       li      r0,__NR_exit    /* exit if function returns */
-       li      r3,0
-       sc
-2:     lwz     r30,8(r1)
-       lwz     r31,12(r1)
-       addi    r1,r1,16
-       blr
-
 #ifdef CONFIG_SMP
 _GLOBAL(start_secondary_resume)
        /* Reset stack */
index 565b78625a32a149ce4959fb9610a46a82a5e04a..5cfa8008693b83aaae96dd4f5d91a7e8190d234b 100644 (file)
@@ -406,40 +406,6 @@ _GLOBAL(scom970_write)
 #endif /* CONFIG_CPU_FREQ_PMAC64 || CONFIG_CPU_FREQ_MAPLE */
 
 
-/*
- * Create a kernel thread
- *   kernel_thread(fn, arg, flags)
- */
-_GLOBAL(kernel_thread)
-       std     r29,-24(r1)
-       std     r30,-16(r1)
-       stdu    r1,-STACK_FRAME_OVERHEAD(r1)
-       mr      r29,r3
-       mr      r30,r4
-       ori     r3,r5,CLONE_VM  /* flags */
-       oris    r3,r3,(CLONE_UNTRACED>>16)
-       li      r4,0            /* new sp (unused) */
-       li      r0,__NR_clone
-       sc
-       bns+    1f              /* did system call indicate error? */
-       neg     r3,r3           /* if so, make return code negative */
-1:     cmpdi   0,r3,0          /* parent or child? */
-       bne     2f              /* return if parent */
-       li      r0,0
-       stdu    r0,-STACK_FRAME_OVERHEAD(r1)
-       ld      r2,8(r29)
-       ld      r29,0(r29)
-       mtlr    r29              /* fn addr in lr */
-       mr      r3,r30          /* load arg and call fn */
-       blrl
-       li      r0,__NR_exit    /* exit after child exits */
-        li     r3,0
-       sc
-2:     addi    r1,r1,STACK_FRAME_OVERHEAD
-       ld      r29,-24(r1)
-       ld      r30,-16(r1)
-       blr
-
 /*
  * disable_kernel_fp()
  * Disable the FPU.
index 3e4031581c65482bb9348b17c9509e630b710570..19e4288d84865e7b97f1a22a6fe099037b46aeef 100644 (file)
@@ -94,7 +94,6 @@ EXPORT_SYMBOL(pci_dram_offset);
 #endif /* CONFIG_PCI */
 
 EXPORT_SYMBOL(start_thread);
-EXPORT_SYMBOL(kernel_thread);
 
 EXPORT_SYMBOL(giveup_fpu);
 #ifdef CONFIG_ALTIVEC
index d5ad666efd8b9a5fde3b93541fb774ae8459881f..ba48233500f6d47d7f2a554f5023f23060b5cff2 100644 (file)
@@ -733,30 +733,39 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-               unsigned long unused, struct task_struct *p,
+               unsigned long arg, struct task_struct *p,
                struct pt_regs *regs)
 {
        struct pt_regs *childregs, *kregs;
        extern void ret_from_fork(void);
+       extern void ret_from_kernel_thread(void);
+       void (*f)(void);
        unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
 
-       CHECK_FULL_REGS(regs);
        /* Copy registers */
        sp -= sizeof(struct pt_regs);
        childregs = (struct pt_regs *) sp;
-       *childregs = *regs;
-       if ((childregs->msr & MSR_PR) == 0) {
+       if (!regs) {
                /* for kernel thread, set `current' and stackptr in new task */
+               memset(childregs, 0, sizeof(struct pt_regs));
                childregs->gpr[1] = sp + sizeof(struct pt_regs);
-#ifdef CONFIG_PPC32
-               childregs->gpr[2] = (unsigned long) p;
-#else
+#ifdef CONFIG_PPC64
+               childregs->gpr[14] = *(unsigned long *)usp;
+               childregs->gpr[2] = ((unsigned long *)usp)[1],
                clear_tsk_thread_flag(p, TIF_32BIT);
+#else
+               childregs->gpr[14] = usp;       /* function */
+               childregs->gpr[2] = (unsigned long) p;
 #endif
+               childregs->gpr[15] = arg;
                p->thread.regs = NULL;  /* no user register state */
+               f = ret_from_kernel_thread;
        } else {
+               CHECK_FULL_REGS(regs);
+               *childregs = *regs;
                childregs->gpr[1] = usp;
                p->thread.regs = childregs;
+               childregs->gpr[3] = 0;  /* Result from fork() */
                if (clone_flags & CLONE_SETTLS) {
 #ifdef CONFIG_PPC64
                        if (!is_32bit_task())
@@ -765,8 +774,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 #endif
                                childregs->gpr[2] = childregs->gpr[6];
                }
+
+               f = ret_from_fork;
        }
-       childregs->gpr[3] = 0;  /* Result from fork() */
        sp -= STACK_FRAME_OVERHEAD;
 
        /*
@@ -805,19 +815,17 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
                p->thread.dscr = current->thread.dscr;
        }
 #endif
-
        /*
         * The PPC64 ABI makes use of a TOC to contain function 
         * pointers.  The function (ret_from_except) is actually a pointer
         * to the TOC entry.  The first entry is a pointer to the actual
         * function.
-        */
+        */
 #ifdef CONFIG_PPC64
-       kregs->nip = *((unsigned long *)ret_from_fork);
+       kregs->nip = *((unsigned long *)f);
 #else
-       kregs->nip = (unsigned long)ret_from_fork;
+       kregs->nip = (unsigned long)f;
 #endif
-
        return 0;
 }
 
@@ -1055,26 +1063,13 @@ int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
                        regs, 0, NULL, NULL);
 }
 
-int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
-              unsigned long a3, unsigned long a4, unsigned long a5,
-              struct pt_regs *regs)
+void __ret_from_kernel_execve(struct pt_regs *normal)
+__noreturn;
+
+void ret_from_kernel_execve(struct pt_regs *normal)
 {
-       int error;
-       char *filename;
-
-       filename = getname((const char __user *) a0);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       flush_fp_to_thread(current);
-       flush_altivec_to_thread(current);
-       flush_spe_to_thread(current);
-       error = do_execve(filename,
-                         (const char __user *const __user *) a1,
-                         (const char __user *const __user *) a2, regs);
-       putname(filename);
-out:
-       return error;
+       set_thread_flag(TIF_RESTOREALL);
+       __ret_from_kernel_execve(normal);
 }
 
 static inline int valid_irq_stack(unsigned long sp, struct task_struct *p,
index 8b4c049aee20e8604fa83a9a017366213d0ab6d9..804e323c139d000fbc280742d9b1a6729271110e 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/stddef.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
-#include <linux/freezer.h>
 #endif
 
 #include <asm/uaccess.h>
index abd1112da54f40b1b24a08a6a0732373ad95ef0e..9c2ed90ece8f4cdb93b75456f70376b944d52703 100644 (file)
@@ -156,28 +156,6 @@ asmlinkage long compat_sys_sendfile64_wrapper(u32 out_fd, u32 in_fd,
                            (off_t __user *)offset, count);
 }
 
-long compat_sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
-                 unsigned long a3, unsigned long a4, unsigned long a5,
-                 struct pt_regs *regs)
-{
-       int error;
-       char * filename;
-       
-       filename = getname((char __user *) a0);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       flush_fp_to_thread(current);
-       flush_altivec_to_thread(current);
-
-       error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs);
-
-       putname(filename);
-
-out:
-       return error;
-}
-
 /* Note: it is necessary to treat option as an unsigned int, 
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
index c9986fd400d89947966d4e94746f8d8c9913b7a2..ce4cb772dc7833f502e8521fe57ed6eb646c46d5 100644 (file)
@@ -73,7 +73,7 @@
 /* powerpc clocksource/clockevent code */
 
 #include <linux/clockchips.h>
-#include <linux/clocksource.h>
+#include <linux/timekeeper_internal.h>
 
 static cycle_t rtc_read(struct clocksource *);
 static struct clocksource clocksource_rtc = {
@@ -727,7 +727,7 @@ static cycle_t timebase_read(struct clocksource *cs)
        return (cycle_t)get_tb();
 }
 
-void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
+void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
                        struct clocksource *clock, u32 mult)
 {
        u64 new_tb_to_xs, new_stamp_xsec;
index 51faaac8abe6c401636326deebd59f4d12457b28..185bedd926df7258bef7070d97c68f577bf91298 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
+#include <linux/kthread.h>
 #include <asm/eeh_event.h>
 #include <asm/ppc-pci.h>
 
@@ -59,8 +60,6 @@ static int eeh_event_handler(void * dummy)
        struct eeh_event *event;
        struct eeh_pe *pe;
 
-       set_task_comm(current, "eehd");
-
        spin_lock_irqsave(&eeh_eventlist_lock, flags);
        event = NULL;
 
@@ -108,7 +107,7 @@ static int eeh_event_handler(void * dummy)
  */
 static void eeh_thread_launcher(struct work_struct *dummy)
 {
-       if (kernel_thread(eeh_event_handler, NULL, CLONE_KERNEL) < 0)
+       if (IS_ERR(kthread_run(eeh_event_handler, NULL, "eehd")))
                printk(KERN_ERR "Failed to start EEH daemon\n");
 }
 
index dc0a035e63bb5c549adbfa58660b15ef16abec90..ecdb0a6b317172f396a858d382c4a0946745943e 100644 (file)
@@ -77,8 +77,9 @@ static int pseries_remove_memblock(unsigned long base, unsigned int memblock_siz
 {
        unsigned long start, start_pfn;
        struct zone *zone;
-       int i, ret;
-       int sections_to_remove;
+       int ret;
+       unsigned long section;
+       unsigned long sections_to_remove;
 
        start_pfn = base >> PAGE_SHIFT;
 
@@ -99,9 +100,9 @@ static int pseries_remove_memblock(unsigned long base, unsigned int memblock_siz
         * while writing to it. So we have to defer it to here.
         */
        sections_to_remove = (memblock_size >> PAGE_SHIFT) / PAGES_PER_SECTION;
-       for (i = 0; i < sections_to_remove; i++) {
-               unsigned long pfn = start_pfn + i * PAGES_PER_SECTION;
-               ret = __remove_pages(zone, start_pfn,  PAGES_PER_SECTION);
+       for (section = 0; section < sections_to_remove; section++) {
+               unsigned long pfn = start_pfn + section * PAGES_PER_SECTION;
+               ret = __remove_pages(zone, pfn, PAGES_PER_SECTION);
                if (ret)
                        return ret;
        }
index ceff7aef2477ad5ff896db12886204e773475d28..e5dac123618519051f776b78b74c869d2267d693 100644 (file)
@@ -131,10 +131,11 @@ config S390
        select HAVE_UID16 if 32BIT
        select ARCH_WANT_IPC_PARSE_VERSION
        select GENERIC_SMP_IDLE_THREAD
-       select GENERIC_TIME_VSYSCALL
+       select GENERIC_TIME_VSYSCALL_OLD
        select GENERIC_CLOCKEVENTS
        select KTIME_SCALAR if 32BIT
        select HAVE_ARCH_SECCOMP_FILTER
+       select GENERIC_KERNEL_THREAD
 
 config SCHED_OMIT_FRAME_POINTER
        def_bool y
index d76cef3fef37bac6f3df5ad6d336a30cdfc8233f..fc32a2df497464cf7707f6843ba55a5d60f56341 100644 (file)
@@ -31,6 +31,18 @@ config DEBUG_STRICT_USER_COPY_CHECKS
 
          If unsure, or if you run an older (pre 4.4) gcc, say N.
 
+config S390_PTDUMP
+       bool "Export kernel pagetable layout to userspace via debugfs"
+       depends on DEBUG_KERNEL
+       select DEBUG_FS
+       ---help---
+         Say Y here if you want to show the kernel pagetable layout in a
+         debugfs file. This information is only useful for kernel developers
+         who are working in architecture specific areas of the kernel.
+         It is probably not a good idea to enable this feature in a production
+         kernel.
+         If in doubt, say "N"
+
 config DEBUG_SET_MODULE_RONX
        def_bool y
        depends on MODULES
index f18fc796beef6c24545be2f4aedb3487cb770e16..0633dc6d254da93deff0e73019740dd46c88af33 100644 (file)
@@ -1,17 +1,3 @@
-include include/asm-generic/Kbuild.asm
 
-header-y += chpid.h
-header-y += chsc.h
-header-y += cmb.h
-header-y += dasd.h
-header-y += debug.h
-header-y += kvm_virtio.h
-header-y += monwriter.h
-header-y += qeth.h
-header-y += schid.h
-header-y += tape390.h
-header-y += ucontext.h
-header-y += vtoc.h
-header-y += zcrypt.h
 
 generic-y += clkdev.h
index e5bde9f9291f9a57b7bd6cfce430f7a9c7e37160..38c405ef89cee13a1790308de7d32382bf316548 100644 (file)
@@ -1,24 +1,11 @@
 /*
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2012
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
-
 #ifndef _ASM_S390_CHPID_H
 #define _ASM_S390_CHPID_H
 
-#include <linux/string.h>
-#include <linux/types.h>
-
-#define __MAX_CHPID 255
-
-struct chp_id {
-       u8 reserved1;
-       u8 cssid;
-       u8 reserved2;
-       u8 id;
-} __attribute__((packed));
-
-#ifdef __KERNEL__
+#include <uapi/asm/chpid.h>
 #include <asm/cio.h>
 
 static inline void chp_id_init(struct chp_id *chpid)
@@ -49,6 +36,4 @@ static inline int chp_id_is_valid(struct chp_id *chpid)
 
 #define chp_id_for_each(c) \
        for (chp_id_init(c); chp_id_is_valid(c); chp_id_next(c))
-#endif /* __KERNEL */
-
 #endif /* _ASM_S390_CHPID_H */
index 39ae03294794f23b852a233e724d8a1b98342c6e..806eac12e3bda71c3921c4b9d56a3a79ca46a121 100644 (file)
@@ -1,61 +1,12 @@
 #ifndef S390_CMB_H
 #define S390_CMB_H
 
-#include <linux/types.h>
+#include <uapi/asm/cmb.h>
 
-/**
- * struct cmbdata - channel measurement block data for user space
- * @size: size of the stored data
- * @elapsed_time: time since last sampling
- * @ssch_rsch_count: number of ssch and rsch
- * @sample_count: number of samples
- * @device_connect_time: time of device connect
- * @function_pending_time: time of function pending
- * @device_disconnect_time: time of device disconnect
- * @control_unit_queuing_time: time of control unit queuing
- * @device_active_only_time: time of device active only
- * @device_busy_time: time of device busy (ext. format)
- * @initial_command_response_time: initial command response time (ext. format)
- *
- * All values are stored as 64 bit for simplicity, especially
- * in 32 bit emulation mode. All time values are normalized to
- * nanoseconds.
- * Currently, two formats are known, which differ by the size of
- * this structure, i.e. the last two members are only set when
- * the extended channel measurement facility (first shipped in
- * z990 machines) is activated.
- * Potentially, more fields could be added, which would result in a
- * new ioctl number.
- */
-struct cmbdata {
-       __u64 size;
-       __u64 elapsed_time;
- /* basic and exended format: */
-       __u64 ssch_rsch_count;
-       __u64 sample_count;
-       __u64 device_connect_time;
-       __u64 function_pending_time;
-       __u64 device_disconnect_time;
-       __u64 control_unit_queuing_time;
-       __u64 device_active_only_time;
- /* extended format only: */
-       __u64 device_busy_time;
-       __u64 initial_command_response_time;
-};
-
-/* enable channel measurement */
-#define BIODASDCMFENABLE       _IO(DASD_IOCTL_LETTER, 32)
-/* enable channel measurement */
-#define BIODASDCMFDISABLE      _IO(DASD_IOCTL_LETTER, 33)
-/* read channel measurement data */
-#define BIODASDREADALLCMB      _IOWR(DASD_IOCTL_LETTER, 33, struct cmbdata)
-
-#ifdef __KERNEL__
 struct ccw_device;
 extern int enable_cmf(struct ccw_device *cdev);
 extern int disable_cmf(struct ccw_device *cdev);
 extern u64 cmf_read(struct ccw_device *cdev, int index);
 extern int cmf_readall(struct ccw_device *cdev, struct cmbdata *data);
 
-#endif /* __KERNEL__ */
 #endif /* S390_CMB_H */
index a06ebc2623fb7e8b2a63b7d54466b0dddd828daf..7e1c917bbba2ace4f6b5785f67db518ba7c2cfc1 100644 (file)
@@ -3,8 +3,6 @@
 
 #include <linux/types.h>
 
-#ifdef __KERNEL__
-
 struct css_general_char {
        u64 : 12;
        u32 dynio : 1;   /* bit 12 */
@@ -35,5 +33,4 @@ struct css_general_char {
 
 extern struct css_general_char css_general_characteristics;
 
-#endif /* __KERNEL__ */
 #endif
index f39677e6ccdef3105776d6062ca8a11a9431367b..188c5052a20ab663f878afc2c23889ec53384d8e 100644 (file)
@@ -3,39 +3,14 @@
  *
  *    Copyright IBM Corp. 1999, 2000
  */
-
 #ifndef DEBUG_H
 #define DEBUG_H
 
-#include <linux/fs.h>
-
-/* Note:
- * struct __debug_entry must be defined outside of #ifdef __KERNEL__ 
- * in order to allow a user program to analyze the 'raw'-view.
- */
-
-struct __debug_entry{
-        union {
-                struct {
-                        unsigned long long clock:52;
-                        unsigned long long exception:1;
-                        unsigned long long level:3;
-                        unsigned long long cpuid:8;
-                } fields;
-
-                unsigned long long stck;
-        } id;
-        void* caller;
-} __attribute__((packed));
-
-
-#define __DEBUG_FEATURE_VERSION      2  /* version of debug feature */
-
-#ifdef __KERNEL__
 #include <linux/string.h>
 #include <linux/spinlock.h>
 #include <linux/kernel.h>
 #include <linux/time.h>
+#include <uapi/asm/debug.h>
 
 #define DEBUG_MAX_LEVEL            6  /* debug levels range from 0 to 6 */
 #define DEBUG_OFF_LEVEL            -1 /* level where debug is switched off */
@@ -254,5 +229,4 @@ int debug_unregister_view(debug_info_t* id, struct debug_view* view);
 #define PRINT_FATAL(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
 #endif                         /* DASD_DEBUG */
 
-#endif                         /* __KERNEL__ */
 #endif                         /* DEBUG_H */
index da44867de60f6e1deaa6b8edbd35c9e834db027b..e0f842308a68f5292cbc4d0b470a3f3eeaec0f62 100644 (file)
@@ -9,12 +9,6 @@
  *
  *    Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
  */
-
-#ifndef __S390_KVM_PARA_H
-#define __S390_KVM_PARA_H
-
-#ifdef __KERNEL__
-
 /*
  * Hypercalls for KVM on s390. The calling convention is similar to the
  * s390 ABI, so we use R2-R6 for parameters 1-5. In addition we use R1
  *
  * This work is licensed under the terms of the GNU GPL, version 2.
  */
+#ifndef __S390_KVM_PARA_H
+#define __S390_KVM_PARA_H
+
+#include <uapi/asm/kvm_para.h>
+
+
 
 static inline long kvm_hypercall0(unsigned long nr)
 {
@@ -154,6 +154,4 @@ static inline bool kvm_check_and_clear_guest_paused(void)
        return false;
 }
 
-#endif
-
 #endif /* __S390_KVM_PARA_H */
index abc1932ac4e163b3a6f3df36e012dea0cac18d06..0e47a576d666b92ce1fb88f46daae16e736cbfc9 100644 (file)
@@ -3,17 +3,13 @@
  *
  *  Derived from "include/asm-i386/mman.h"
  */
-
 #ifndef __S390_MMAN_H__
 #define __S390_MMAN_H__
 
-#include <asm-generic/mman.h>
+#include <uapi/asm/mman.h>
 
-#if defined(__KERNEL__)
 #if !defined(__ASSEMBLY__) && defined(CONFIG_64BIT)
 int s390_mmap_check(unsigned long addr, unsigned long len);
 #define arch_mmap_check(addr,len,flags)        s390_mmap_check(addr,len)
 #endif
-#endif
-
 #endif /* __S390_MMAN_H__ */
index 27ab3c7c1e8bc7e3e353b3eaefc0a806edc8400c..6d5367060a5656a92d5d1b95f28dc3097fa47e78 100644 (file)
 #include <asm/setup.h>
 #ifndef __ASSEMBLY__
 
+static unsigned long pfmf(unsigned long function, unsigned long address)
+{
+       asm volatile(
+               "       .insn   rre,0xb9af0000,%[function],%[address]"
+               : [address] "+a" (address)
+               : [function] "d" (function)
+               : "memory");
+       return address;
+}
+
 static inline void clear_page(void *page)
 {
        if (MACHINE_HAS_PFMF) {
-               asm volatile(
-                       "       .insn   rre,0xb9af0000,%0,%1"
-                       : : "d" (0x10000), "a" (page) : "memory", "cc");
+               pfmf(0x10000, (unsigned long)page);
        } else {
                register unsigned long reg1 asm ("1") = 0;
                register void *reg2 asm ("2") = page;
index 979fe3dc07889b0cd50df90508ace5513c2392f3..dd647c919a66c766a75a8114588f1cd51afdafd7 100644 (file)
@@ -119,13 +119,12 @@ static inline int is_zero_pfn(unsigned long pfn)
 
 #ifndef __ASSEMBLY__
 /*
- * The vmalloc area will always be on the topmost area of the kernel
- * mapping. We reserve 96MB (31bit) / 128GB (64bit) for vmalloc,
- * which should be enough for any sane case.
- * By putting vmalloc at the top, we maximise the gap between physical
- * memory and vmalloc to catch misplaced memory accesses. As a side
- * effect, this also makes sure that 64 bit module code cannot be used
- * as system call address.
+ * The vmalloc and module area will always be on the topmost area of the kernel
+ * mapping. We reserve 96MB (31bit) / 128GB (64bit) for vmalloc and modules.
+ * On 64 bit kernels we have a 2GB area at the top of the vmalloc area where
+ * modules will reside. That makes sure that inter module branches always
+ * happen without trampolines and in addition the placement within a 2GB frame
+ * is branch prediction unit friendly.
  */
 extern unsigned long VMALLOC_START;
 extern unsigned long VMALLOC_END;
@@ -133,6 +132,14 @@ extern struct page *vmemmap;
 
 #define VMEM_MAX_PHYS ((unsigned long) vmemmap)
 
+#ifdef CONFIG_64BIT
+extern unsigned long MODULES_VADDR;
+extern unsigned long MODULES_END;
+#define MODULES_VADDR  MODULES_VADDR
+#define MODULES_END    MODULES_END
+#define MODULES_LEN    (1UL << 31)
+#endif
+
 /*
  * A 31 bit pagetable entry of S390 has following format:
  *  |   PFRA          |    |  OS  |
@@ -507,6 +514,15 @@ static inline int pmd_none(pmd_t pmd)
        return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) != 0UL;
 }
 
+static inline int pmd_large(pmd_t pmd)
+{
+#ifdef CONFIG_64BIT
+       return !!(pmd_val(pmd) & _SEGMENT_ENTRY_LARGE);
+#else
+       return 0;
+#endif
+}
+
 static inline int pmd_bad(pmd_t pmd)
 {
        unsigned long mask = ~_SEGMENT_ENTRY_ORIGIN & ~_SEGMENT_ENTRY_INV;
index 56831dfa9198c6e2192605fd5ee9d68c538d8b17..94e749c90230d9f824949429d505625f90f7b4e7 100644 (file)
@@ -35,6 +35,7 @@ static inline void get_cpu_id(struct cpuid *ptr)
 extern void s390_adjust_jiffies(void);
 extern const struct seq_operations cpuinfo_op;
 extern int sysctl_ieee_emulation_warnings;
+extern void execve_tail(void);
 
 /*
  * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.
@@ -126,6 +127,7 @@ struct stack_frame {
        regs->psw.mask  = psw_user_bits | PSW_MASK_EA | PSW_MASK_BA;    \
        regs->psw.addr  = new_psw | PSW_ADDR_AMODE;                     \
        regs->gprs[15]  = new_stackp;                                   \
+       execve_tail();                                                  \
 } while (0)
 
 #define start_thread31(regs, new_psw, new_stackp) do {                 \
@@ -135,6 +137,7 @@ struct stack_frame {
        __tlb_flush_mm(current->mm);                                    \
        crst_table_downgrade(current->mm, 1UL << 31);                   \
        update_mm(current->mm, current);                                \
+       execve_tail();                                                  \
 } while (0)
 
 /* Forward declaration, a strange C thing */
@@ -150,7 +153,6 @@ static inline void show_cacheinfo(struct seq_file *m) { }
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 /*
  * Return saved PC of a blocked thread.
index ce20a53afe9160caa6d664a2ece149b8ceb7d078..3ee5da3bc10ca26993c76072ec9195b1ec866c28 100644 (file)
  *    Copyright IBM Corp. 1999, 2000
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  */
-
 #ifndef _S390_PTRACE_H
 #define _S390_PTRACE_H
 
-/*
- * Offsets in the user_regs_struct. They are used for the ptrace
- * system call and in entry.S
- */
-#ifndef __s390x__
-
-#define PT_PSWMASK  0x00
-#define PT_PSWADDR  0x04
-#define PT_GPR0     0x08
-#define PT_GPR1     0x0C
-#define PT_GPR2     0x10
-#define PT_GPR3     0x14
-#define PT_GPR4     0x18
-#define PT_GPR5     0x1C
-#define PT_GPR6     0x20
-#define PT_GPR7     0x24
-#define PT_GPR8     0x28
-#define PT_GPR9     0x2C
-#define PT_GPR10    0x30
-#define PT_GPR11    0x34
-#define PT_GPR12    0x38
-#define PT_GPR13    0x3C
-#define PT_GPR14    0x40
-#define PT_GPR15    0x44
-#define PT_ACR0     0x48
-#define PT_ACR1     0x4C
-#define PT_ACR2     0x50
-#define PT_ACR3     0x54
-#define PT_ACR4            0x58
-#define PT_ACR5            0x5C
-#define PT_ACR6            0x60
-#define PT_ACR7            0x64
-#define PT_ACR8            0x68
-#define PT_ACR9            0x6C
-#define PT_ACR10    0x70
-#define PT_ACR11    0x74
-#define PT_ACR12    0x78
-#define PT_ACR13    0x7C
-#define PT_ACR14    0x80
-#define PT_ACR15    0x84
-#define PT_ORIGGPR2 0x88
-#define PT_FPC     0x90
-/*
- * A nasty fact of life that the ptrace api
- * only supports passing of longs.
- */
-#define PT_FPR0_HI  0x98
-#define PT_FPR0_LO  0x9C
-#define PT_FPR1_HI  0xA0
-#define PT_FPR1_LO  0xA4
-#define PT_FPR2_HI  0xA8
-#define PT_FPR2_LO  0xAC
-#define PT_FPR3_HI  0xB0
-#define PT_FPR3_LO  0xB4
-#define PT_FPR4_HI  0xB8
-#define PT_FPR4_LO  0xBC
-#define PT_FPR5_HI  0xC0
-#define PT_FPR5_LO  0xC4
-#define PT_FPR6_HI  0xC8
-#define PT_FPR6_LO  0xCC
-#define PT_FPR7_HI  0xD0
-#define PT_FPR7_LO  0xD4
-#define PT_FPR8_HI  0xD8
-#define PT_FPR8_LO  0XDC
-#define PT_FPR9_HI  0xE0
-#define PT_FPR9_LO  0xE4
-#define PT_FPR10_HI 0xE8
-#define PT_FPR10_LO 0xEC
-#define PT_FPR11_HI 0xF0
-#define PT_FPR11_LO 0xF4
-#define PT_FPR12_HI 0xF8
-#define PT_FPR12_LO 0xFC
-#define PT_FPR13_HI 0x100
-#define PT_FPR13_LO 0x104
-#define PT_FPR14_HI 0x108
-#define PT_FPR14_LO 0x10C
-#define PT_FPR15_HI 0x110
-#define PT_FPR15_LO 0x114
-#define PT_CR_9            0x118
-#define PT_CR_10    0x11C
-#define PT_CR_11    0x120
-#define PT_IEEE_IP  0x13C
-#define PT_LASTOFF  PT_IEEE_IP
-#define PT_ENDREGS  0x140-1
-
-#define GPR_SIZE       4
-#define CR_SIZE                4
-
-#define STACK_FRAME_OVERHEAD   96      /* size of minimum stack frame */
-
-#else /* __s390x__ */
-
-#define PT_PSWMASK  0x00
-#define PT_PSWADDR  0x08
-#define PT_GPR0     0x10
-#define PT_GPR1     0x18
-#define PT_GPR2     0x20
-#define PT_GPR3     0x28
-#define PT_GPR4     0x30
-#define PT_GPR5     0x38
-#define PT_GPR6     0x40
-#define PT_GPR7     0x48
-#define PT_GPR8     0x50
-#define PT_GPR9     0x58
-#define PT_GPR10    0x60
-#define PT_GPR11    0x68
-#define PT_GPR12    0x70
-#define PT_GPR13    0x78
-#define PT_GPR14    0x80
-#define PT_GPR15    0x88
-#define PT_ACR0     0x90
-#define PT_ACR1     0x94
-#define PT_ACR2     0x98
-#define PT_ACR3     0x9C
-#define PT_ACR4            0xA0
-#define PT_ACR5            0xA4
-#define PT_ACR6            0xA8
-#define PT_ACR7            0xAC
-#define PT_ACR8            0xB0
-#define PT_ACR9            0xB4
-#define PT_ACR10    0xB8
-#define PT_ACR11    0xBC
-#define PT_ACR12    0xC0
-#define PT_ACR13    0xC4
-#define PT_ACR14    0xC8
-#define PT_ACR15    0xCC
-#define PT_ORIGGPR2 0xD0
-#define PT_FPC     0xD8
-#define PT_FPR0     0xE0
-#define PT_FPR1     0xE8
-#define PT_FPR2     0xF0
-#define PT_FPR3     0xF8
-#define PT_FPR4     0x100
-#define PT_FPR5     0x108
-#define PT_FPR6     0x110
-#define PT_FPR7     0x118
-#define PT_FPR8     0x120
-#define PT_FPR9     0x128
-#define PT_FPR10    0x130
-#define PT_FPR11    0x138
-#define PT_FPR12    0x140
-#define PT_FPR13    0x148
-#define PT_FPR14    0x150
-#define PT_FPR15    0x158
-#define PT_CR_9     0x160
-#define PT_CR_10    0x168
-#define PT_CR_11    0x170
-#define PT_IEEE_IP  0x1A8
-#define PT_LASTOFF  PT_IEEE_IP
-#define PT_ENDREGS  0x1B0-1
-
-#define GPR_SIZE       8
-#define CR_SIZE                8
-
-#define STACK_FRAME_OVERHEAD    160      /* size of minimum stack frame */
-
-#endif /* __s390x__ */
-
-#define NUM_GPRS       16
-#define NUM_FPRS       16
-#define NUM_CRS                16
-#define NUM_ACRS       16
-
-#define NUM_CR_WORDS   3
-
-#define FPR_SIZE       8
-#define FPC_SIZE       4
-#define FPC_PAD_SIZE   4 /* gcc insists on aligning the fpregs */
-#define ACR_SIZE       4
-
-
-#define PTRACE_OLDSETOPTIONS         21
+#include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
-#include <linux/stddef.h>
-#include <linux/types.h>
-
-typedef union
-{
-       float   f;
-       double  d;
-        __u64   ui;
-       struct
-       {
-               __u32 hi;
-               __u32 lo;
-       } fp;
-} freg_t;
-
-typedef struct
-{
-       __u32   fpc;
-       freg_t  fprs[NUM_FPRS];              
-} s390_fp_regs;
-
-#define FPC_EXCEPTION_MASK      0xF8000000
-#define FPC_FLAGS_MASK          0x00F80000
-#define FPC_DXC_MASK            0x0000FF00
-#define FPC_RM_MASK             0x00000003
-#define FPC_VALID_MASK          0xF8F8FF03
-
-/* this typedef defines how a Program Status Word looks like */
-typedef struct 
-{
-        unsigned long mask;
-        unsigned long addr;
-} __attribute__ ((aligned(8))) psw_t;
-
-typedef struct
-{
-       __u32   mask;
-       __u32   addr;
-} __attribute__ ((aligned(8))) psw_compat_t;
-
 #ifndef __s390x__
-
-#define PSW_MASK_PER           0x40000000UL
-#define PSW_MASK_DAT           0x04000000UL
-#define PSW_MASK_IO            0x02000000UL
-#define PSW_MASK_EXT           0x01000000UL
-#define PSW_MASK_KEY           0x00F00000UL
-#define PSW_MASK_BASE          0x00080000UL    /* always one */
-#define PSW_MASK_MCHECK                0x00040000UL
-#define PSW_MASK_WAIT          0x00020000UL
-#define PSW_MASK_PSTATE                0x00010000UL
-#define PSW_MASK_ASC           0x0000C000UL
-#define PSW_MASK_CC            0x00003000UL
-#define PSW_MASK_PM            0x00000F00UL
-#define PSW_MASK_RI            0x00000000UL
-#define PSW_MASK_EA            0x00000000UL
-#define PSW_MASK_BA            0x00000000UL
-
-#define PSW_MASK_USER          0x00003F00UL
-
-#define PSW_ADDR_AMODE         0x80000000UL
-#define PSW_ADDR_INSN          0x7FFFFFFFUL
-
-#define PSW_DEFAULT_KEY                (((unsigned long) PAGE_DEFAULT_ACC) << 20)
-
-#define PSW_ASC_PRIMARY                0x00000000UL
-#define PSW_ASC_ACCREG         0x00004000UL
-#define PSW_ASC_SECONDARY      0x00008000UL
-#define PSW_ASC_HOME           0x0000C000UL
-
 #else /* __s390x__ */
-
-#define PSW_MASK_PER           0x4000000000000000UL
-#define PSW_MASK_DAT           0x0400000000000000UL
-#define PSW_MASK_IO            0x0200000000000000UL
-#define PSW_MASK_EXT           0x0100000000000000UL
-#define PSW_MASK_BASE          0x0000000000000000UL
-#define PSW_MASK_KEY           0x00F0000000000000UL
-#define PSW_MASK_MCHECK                0x0004000000000000UL
-#define PSW_MASK_WAIT          0x0002000000000000UL
-#define PSW_MASK_PSTATE                0x0001000000000000UL
-#define PSW_MASK_ASC           0x0000C00000000000UL
-#define PSW_MASK_CC            0x0000300000000000UL
-#define PSW_MASK_PM            0x00000F0000000000UL
-#define PSW_MASK_RI            0x0000008000000000UL
-#define PSW_MASK_EA            0x0000000100000000UL
-#define PSW_MASK_BA            0x0000000080000000UL
-
-#define PSW_MASK_USER          0x00003F8180000000UL
-
-#define PSW_ADDR_AMODE         0x0000000000000000UL
-#define PSW_ADDR_INSN          0xFFFFFFFFFFFFFFFFUL
-
-#define PSW_DEFAULT_KEY                (((unsigned long) PAGE_DEFAULT_ACC) << 52)
-
-#define PSW_ASC_PRIMARY                0x0000000000000000UL
-#define PSW_ASC_ACCREG         0x0000400000000000UL
-#define PSW_ASC_SECONDARY      0x0000800000000000UL
-#define PSW_ASC_HOME           0x0000C00000000000UL
-
 #endif /* __s390x__ */
-
-#ifdef __KERNEL__
 extern long psw_kernel_bits;
 extern long psw_user_bits;
-#endif
-
-/*
- * The s390_regs structure is used to define the elf_gregset_t.
- */
-typedef struct
-{
-       psw_t psw;
-       unsigned long gprs[NUM_GPRS];
-       unsigned int  acrs[NUM_ACRS];
-       unsigned long orig_gpr2;
-} s390_regs;
-
-typedef struct
-{
-       psw_compat_t    psw;
-       __u32           gprs[NUM_GPRS];
-       __u32           acrs[NUM_ACRS];
-       __u32           orig_gpr2;
-} s390_compat_regs;
-
-typedef struct
-{
-       __u32           gprs_high[NUM_GPRS];
-} s390_compat_regs_high;
-
-#ifdef __KERNEL__
 
 /*
  * The pt_regs struct defines the way the registers are stored on
@@ -376,167 +77,8 @@ struct per_struct_kernel {
 #define PER_CONTROL_SUSPENSION         0x00400000UL
 #define PER_CONTROL_ALTERATION         0x00200000UL
 
-#endif
-
-/*
- * Now for the user space program event recording (trace) definitions.
- * The following structures are used only for the ptrace interface, don't
- * touch or even look at it if you don't want to modify the user-space
- * ptrace interface. In particular stay away from it for in-kernel PER.
- */
-typedef struct
-{
-       unsigned long cr[NUM_CR_WORDS];
-} per_cr_words;
-
-#define PER_EM_MASK 0xE8000000UL
-
-typedef        struct
-{
 #ifdef __s390x__
-       unsigned                       : 32;
 #endif /* __s390x__ */
-       unsigned em_branching          : 1;
-       unsigned em_instruction_fetch  : 1;
-       /*
-        * Switching on storage alteration automatically fixes
-        * the storage alteration event bit in the users std.
-        */
-       unsigned em_storage_alteration : 1;
-       unsigned em_gpr_alt_unused     : 1;
-       unsigned em_store_real_address : 1;
-       unsigned                       : 3;
-       unsigned branch_addr_ctl       : 1;
-       unsigned                       : 1;
-       unsigned storage_alt_space_ctl : 1;
-       unsigned                       : 21;
-       unsigned long starting_addr;
-       unsigned long ending_addr;
-} per_cr_bits;
-
-typedef struct
-{
-       unsigned short perc_atmid;
-       unsigned long address;
-       unsigned char access_id;
-} per_lowcore_words;
-
-typedef struct
-{
-       unsigned perc_branching          : 1;
-       unsigned perc_instruction_fetch  : 1;
-       unsigned perc_storage_alteration : 1;
-       unsigned perc_gpr_alt_unused     : 1;
-       unsigned perc_store_real_address : 1;
-       unsigned                         : 3;
-       unsigned atmid_psw_bit_31        : 1;
-       unsigned atmid_validity_bit      : 1;
-       unsigned atmid_psw_bit_32        : 1;
-       unsigned atmid_psw_bit_5         : 1;
-       unsigned atmid_psw_bit_16        : 1;
-       unsigned atmid_psw_bit_17        : 1;
-       unsigned si                      : 2;
-       unsigned long address;
-       unsigned                         : 4;
-       unsigned access_id               : 4;
-} per_lowcore_bits;
-
-typedef struct
-{
-       union {
-               per_cr_words   words;
-               per_cr_bits    bits;
-       } control_regs;
-       /*
-        * Use these flags instead of setting em_instruction_fetch
-        * directly they are used so that single stepping can be
-        * switched on & off while not affecting other tracing
-        */
-       unsigned  single_step       : 1;
-       unsigned  instruction_fetch : 1;
-       unsigned                    : 30;
-       /*
-        * These addresses are copied into cr10 & cr11 if single
-        * stepping is switched off
-        */
-       unsigned long starting_addr;
-       unsigned long ending_addr;
-       union {
-               per_lowcore_words words;
-               per_lowcore_bits  bits;
-       } lowcore; 
-} per_struct;
-
-typedef struct
-{
-       unsigned int  len;
-       unsigned long kernel_addr;
-       unsigned long process_addr;
-} ptrace_area;
-
-/*
- * S/390 specific non posix ptrace requests. I chose unusual values so
- * they are unlikely to clash with future ptrace definitions.
- */
-#define PTRACE_PEEKUSR_AREA           0x5000
-#define PTRACE_POKEUSR_AREA           0x5001
-#define PTRACE_PEEKTEXT_AREA         0x5002
-#define PTRACE_PEEKDATA_AREA         0x5003
-#define PTRACE_POKETEXT_AREA         0x5004
-#define PTRACE_POKEDATA_AREA         0x5005
-#define PTRACE_GET_LAST_BREAK        0x5006
-#define PTRACE_PEEK_SYSTEM_CALL       0x5007
-#define PTRACE_POKE_SYSTEM_CALL              0x5008
-#define PTRACE_ENABLE_TE             0x5009
-#define PTRACE_DISABLE_TE            0x5010
-
-/*
- * PT_PROT definition is loosely based on hppa bsd definition in
- * gdb/hppab-nat.c
- */
-#define PTRACE_PROT                       21
-
-typedef enum
-{
-       ptprot_set_access_watchpoint,
-       ptprot_set_write_watchpoint,
-       ptprot_disable_watchpoint
-} ptprot_flags;
-
-typedef struct
-{
-       unsigned long lowaddr;
-       unsigned long hiaddr;
-       ptprot_flags prot;
-} ptprot_area;                     
-
-/* Sequence of bytes for breakpoint illegal instruction.  */
-#define S390_BREAKPOINT     {0x0,0x1}
-#define S390_BREAKPOINT_U16 ((__u16)0x0001)
-#define S390_SYSCALL_OPCODE ((__u16)0x0a00)
-#define S390_SYSCALL_SIZE   2
-
-/*
- * The user_regs_struct defines the way the user registers are
- * store on the stack for signal handling.
- */
-struct user_regs_struct
-{
-       psw_t psw;
-       unsigned long gprs[NUM_GPRS];
-       unsigned int  acrs[NUM_ACRS];
-       unsigned long orig_gpr2;
-       s390_fp_regs fp_regs;
-       /*
-        * These per registers are in here so that gdb can modify them
-        * itself as there is no "official" ptrace interface for hardware
-        * watchpoints. This is the way intel does it.
-        */
-       per_struct per_info;
-       unsigned long ieee_instruction_pointer; /* obsolete, always 0 */
-};
-
-#ifdef __KERNEL__
 /*
  * These are defined as per linux/ptrace.h, which see.
  */
@@ -562,7 +104,5 @@ static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
        return regs->gprs[15] & PSW_ADDR_INSN;
 }
 
-#endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
-
 #endif /* _S390_PTRACE_H */
index 3e4d401b4e45978a9cad899495d11a05efa07437..40b47dfa9d66d4859ada7a44806484bef5561d89 100644 (file)
@@ -1,19 +1,8 @@
 #ifndef ASM_SCHID_H
 #define ASM_SCHID_H
 
-#include <linux/types.h>
-
-struct subchannel_id {
-       __u32 cssid : 8;
-       __u32 : 4;
-       __u32 m : 1;
-       __u32 ssid : 2;
-       __u32 one : 1;
-       __u32 sch_no : 16;
-} __attribute__ ((packed, aligned(4)));
-
-#ifdef __KERNEL__
 #include <linux/string.h>
+#include <uapi/asm/schid.h>
 
 /* Helper function for sane state of pre-allocated subchannel_id. */
 static inline void
@@ -29,6 +18,4 @@ schid_equal(struct subchannel_id *schid1, struct subchannel_id *schid2)
        return !memcmp(schid1, schid2, sizeof(struct subchannel_id));
 }
 
-#endif /* __KERNEL__ */
-
 #endif /* ASM_SCHID_H */
index 8cfd731a18d86260dfbf0cb025cc24b19ff997a4..f69f76b3447a0e685959ec43cf10f53ac99adb5c 100644 (file)
@@ -2,15 +2,11 @@
  *  S390 version
  *    Copyright IBM Corp. 1999, 2010
  */
-
 #ifndef _ASM_S390_SETUP_H
 #define _ASM_S390_SETUP_H
 
-#define COMMAND_LINE_SIZE      4096
-
-#define ARCH_COMMAND_LINE_SIZE 896
+#include <uapi/asm/setup.h>
 
-#ifdef __KERNEL__
 
 #define PARMAREA               0x10400
 #define MEMORY_CHUNKS          256
@@ -75,8 +71,8 @@ extern unsigned int s390_user_mode;
 #define MACHINE_FLAG_DIAG9C    (1UL << 7)
 #define MACHINE_FLAG_MVCOS     (1UL << 8)
 #define MACHINE_FLAG_KVM       (1UL << 9)
-#define MACHINE_FLAG_HPAGE     (1UL << 10)
-#define MACHINE_FLAG_PFMF      (1UL << 11)
+#define MACHINE_FLAG_EDAT1     (1UL << 10)
+#define MACHINE_FLAG_EDAT2     (1UL << 11)
 #define MACHINE_FLAG_LPAR      (1UL << 12)
 #define MACHINE_FLAG_SPP       (1UL << 13)
 #define MACHINE_FLAG_TOPOLOGY  (1UL << 14)
@@ -88,6 +84,8 @@ extern unsigned int s390_user_mode;
 #define MACHINE_IS_LPAR                (S390_lowcore.machine_flags & MACHINE_FLAG_LPAR)
 
 #define MACHINE_HAS_DIAG9C     (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG9C)
+#define MACHINE_HAS_PFMF       MACHINE_HAS_EDAT1
+#define MACHINE_HAS_HPAGE      MACHINE_HAS_EDAT1
 
 #ifndef CONFIG_64BIT
 #define MACHINE_HAS_IEEE       (S390_lowcore.machine_flags & MACHINE_FLAG_IEEE)
@@ -96,8 +94,8 @@ extern unsigned int s390_user_mode;
 #define MACHINE_HAS_DIAG44     (1)
 #define MACHINE_HAS_MVPG       (S390_lowcore.machine_flags & MACHINE_FLAG_MVPG)
 #define MACHINE_HAS_MVCOS      (0)
-#define MACHINE_HAS_HPAGE      (0)
-#define MACHINE_HAS_PFMF       (0)
+#define MACHINE_HAS_EDAT1      (0)
+#define MACHINE_HAS_EDAT2      (0)
 #define MACHINE_HAS_SPP                (0)
 #define MACHINE_HAS_TOPOLOGY   (0)
 #define MACHINE_HAS_TE         (0)
@@ -109,8 +107,8 @@ extern unsigned int s390_user_mode;
 #define MACHINE_HAS_DIAG44     (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG44)
 #define MACHINE_HAS_MVPG       (1)
 #define MACHINE_HAS_MVCOS      (S390_lowcore.machine_flags & MACHINE_FLAG_MVCOS)
-#define MACHINE_HAS_HPAGE      (S390_lowcore.machine_flags & MACHINE_FLAG_HPAGE)
-#define MACHINE_HAS_PFMF       (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF)
+#define MACHINE_HAS_EDAT1      (S390_lowcore.machine_flags & MACHINE_FLAG_EDAT1)
+#define MACHINE_HAS_EDAT2      (S390_lowcore.machine_flags & MACHINE_FLAG_EDAT2)
 #define MACHINE_HAS_SPP                (S390_lowcore.machine_flags & MACHINE_FLAG_SPP)
 #define MACHINE_HAS_TOPOLOGY   (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
 #define MACHINE_HAS_TE         (S390_lowcore.machine_flags & MACHINE_FLAG_TE)
@@ -173,5 +171,4 @@ extern void (*_machine_power_off)(void);
 #define COMMAND_LINE      0x10480
 
 #endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
 #endif /* _ASM_S390_SETUP_H */
index 6d4d9d1faee9e24eac40741b2f24c8c9f3a3c5ae..bffdbdd5b3d72171fb05fad336474763d53041de 100644 (file)
@@ -3,18 +3,11 @@
  *
  *  Derived from "include/asm-i386/signal.h"
  */
-
 #ifndef _ASMS390_SIGNAL_H
 #define _ASMS390_SIGNAL_H
 
-#include <linux/types.h>
-#include <linux/time.h>
-
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-struct pt_regs;
+#include <uapi/asm/signal.h>
 
-#ifdef __KERNEL__
 /* Most things should be clean enough to redefine this at will, if care
    is taken to make libc match.  */
 #include <asm/sigcontext.h>
@@ -28,94 +21,6 @@ typedef struct {
         unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-#define NSIG            32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-
-#define SIGHUP           1
-#define SIGINT           2
-#define SIGQUIT          3
-#define SIGILL           4
-#define SIGTRAP          5
-#define SIGABRT          6
-#define SIGIOT           6
-#define SIGBUS           7
-#define SIGFPE           8
-#define SIGKILL          9
-#define SIGUSR1         10
-#define SIGSEGV         11
-#define SIGUSR2         12
-#define SIGPIPE         13
-#define SIGALRM         14
-#define SIGTERM         15
-#define SIGSTKFLT       16
-#define SIGCHLD         17
-#define SIGCONT         18
-#define SIGSTOP         19
-#define SIGTSTP         20
-#define SIGTTIN         21
-#define SIGTTOU         22
-#define SIGURG          23
-#define SIGXCPU         24
-#define SIGXFSZ         25
-#define SIGVTALRM       26
-#define SIGPROF         27
-#define SIGWINCH        28
-#define SIGIO           29
-#define SIGPOLL         SIGIO
-/*
-#define SIGLOST         29
-*/
-#define SIGPWR          30
-#define SIGSYS         31
-#define SIGUNUSED       31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN        32
-#define SIGRTMAX        _NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP    0x00000001
-#define SA_NOCLDWAIT    0x00000002
-#define SA_SIGINFO      0x00000004
-#define SA_ONSTACK      0x08000000
-#define SA_RESTART      0x10000000
-#define SA_NODEFER      0x40000000
-#define SA_RESETHAND    0x80000000
-
-#define SA_NOMASK       SA_NODEFER
-#define SA_ONESHOT      SA_RESETHAND
-
-#define SA_RESTORER     0x04000000
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK      1
-#define SS_DISABLE      2
-
-#define MINSIGSTKSZ     2048
-#define SIGSTKSZ        8192
-
-#include <asm-generic/signal-defs.h>
-
-#ifdef __KERNEL__
 struct old_sigaction {
         __sighandler_t sa_handler;
         old_sigset_t sa_mask;
@@ -136,35 +41,4 @@ struct k_sigaction {
 
 #define ptrace_signal_deliver(regs, cookie) do { } while (0)
 
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-struct sigaction {
-        union {
-          __sighandler_t _sa_handler;
-          void (*_sa_sigaction)(int, struct siginfo *, void *);
-        } _u;
-#ifndef __s390x__ /* lovely */
-        sigset_t sa_mask;
-        unsigned long sa_flags;
-        void (*sa_restorer)(void);
-#else  /* __s390x__ */
-        unsigned long sa_flags;
-        void (*sa_restorer)(void);
-       sigset_t sa_mask;
-#endif /* __s390x__ */
-};
-
-#define sa_handler      _u._sa_handler
-#define sa_sigaction    _u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
-        void __user *ss_sp;
-        int ss_flags;
-        size_t ss_size;
-} stack_t;
-
-
 #endif
index cb9fe2786b8174e3b1be80fdfd5705d6d171c9a9..db028d17f0611f7000884bb8cb319bbc6053cec4 100644 (file)
@@ -3,49 +3,11 @@
  *
  *  Derived from "include/asm-i386/termios.h"
  */
-
 #ifndef _S390_TERMIOS_H
 #define _S390_TERMIOS_H
 
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-
-struct winsize {
-       unsigned short ws_row;
-       unsigned short ws_col;
-       unsigned short ws_xpixel;
-       unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-       unsigned short c_iflag;         /* input mode flags */
-       unsigned short c_oflag;         /* output mode flags */
-       unsigned short c_cflag;         /* control mode flags */
-       unsigned short c_lflag;         /* local mode flags */
-       unsigned char c_line;           /* line discipline */
-       unsigned char c_cc[NCC];        /* control characters */
-};
+#include <uapi/asm/termios.h>
 
-/* modem lines */
-#define TIOCM_LE       0x001
-#define TIOCM_DTR      0x002
-#define TIOCM_RTS      0x004
-#define TIOCM_ST       0x008
-#define TIOCM_SR       0x010
-#define TIOCM_CTS      0x020
-#define TIOCM_CAR      0x040
-#define TIOCM_RNG      0x080
-#define TIOCM_DSR      0x100
-#define TIOCM_CD       TIOCM_CAR
-#define TIOCM_RI       TIOCM_RNG
-#define TIOCM_OUT1     0x2000
-#define TIOCM_OUT2     0x4000
-#define TIOCM_LOOP     0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
 
 /*     intr=^C         quit=^\         erase=del       kill=^U
        eof=^D          vtime=\0        vmin=\1         sxtc=\0
@@ -60,6 +22,4 @@ struct termio {
 
 #include <asm-generic/termios-base.h>
 
-#endif /* __KERNEL__ */
-
 #endif /* _S390_TERMIOS_H */
index bb08e2afc5de6c570787ce518d7aeda778a28b92..9e2cfe0349c3c5f50177a870ba6061ec7bd85dd0 100644 (file)
@@ -91,8 +91,6 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_AUDIT      9       /* syscall auditing active */
 #define TIF_SECCOMP            10      /* secure computing */
 #define TIF_SYSCALL_TRACEPOINT 11      /* syscall tracepoint instrumentation */
-#define TIF_POLLING_NRFLAG     16      /* true if poll_idle() is polling
-                                          TIF_NEED_RESCHED */
 #define TIF_31BIT              17      /* 32bit process */
 #define TIF_MEMDIE             18      /* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK    19      /* restore signal mask in do_signal() */
@@ -100,7 +98,6 @@ static inline struct thread_info *current_thread_info(void)
 
 #define _TIF_SYSCALL           (1<<TIF_SYSCALL)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
-#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_PER_TRAP          (1<<TIF_PER_TRAP)
@@ -109,7 +106,6 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_AUDIT     (1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1<<TIF_SECCOMP)
 #define _TIF_SYSCALL_TRACEPOINT        (1<<TIF_SYSCALL_TRACEPOINT)
-#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT             (1<<TIF_31BIT)
 #define _TIF_SINGLE_STEP       (1<<TIF_SINGLE_STEP)
 
index 6ba7c2c7217afa3fc6b221506a44449d3535d481..dccef3ca91fa5dbecaa468a5aa8570897d5b8cf0 100644 (file)
@@ -3,26 +3,14 @@
  *
  *  Derived from "include/asm-i386/types.h"
  */
-
 #ifndef _S390_TYPES_H
 #define _S390_TYPES_H
 
-#include <asm-generic/int-ll64.h>
-
-#ifndef __ASSEMBLY__
-
-/* A address type so that arithmetic can be done on it & it can be upgraded to
-   64 bit when necessary 
-*/
-typedef unsigned long addr_t; 
-typedef __signed__ long saddr_t;
-
-#endif /* __ASSEMBLY__ */
+#include <uapi/asm/types.h>
 
 /*
  * These aren't exported outside the kernel to avoid name space clashes
  */
-#ifdef __KERNEL__
 
 #ifndef __ASSEMBLY__
 
@@ -37,5 +25,4 @@ typedef union {
 
 #endif /* ! CONFIG_64BIT   */
 #endif /* __ASSEMBLY__  */
-#endif /* __KERNEL__    */
 #endif /* _S390_TYPES_H */
index 4e64b5cd1558762016ef166b1a73022f9ccfc084..bbbae41fa9a555dd587831a6c7e85a8a996d963c 100644 (file)
  *
  *  Derived from "include/asm-i386/unistd.h"
  */
-
 #ifndef _ASM_S390_UNISTD_H_
 #define _ASM_S390_UNISTD_H_
 
-/*
- * This file contains the system call numbers.
- */
-
-#define __NR_exit                 1
-#define __NR_fork                 2
-#define __NR_read                 3
-#define __NR_write                4
-#define __NR_open                 5
-#define __NR_close                6
-#define __NR_restart_syscall     7
-#define __NR_creat                8
-#define __NR_link                 9
-#define __NR_unlink              10
-#define __NR_execve              11
-#define __NR_chdir               12
-#define __NR_mknod               14
-#define __NR_chmod               15
-#define __NR_lseek               19
-#define __NR_getpid              20
-#define __NR_mount               21
-#define __NR_umount              22
-#define __NR_ptrace              26
-#define __NR_alarm               27
-#define __NR_pause               29
-#define __NR_utime               30
-#define __NR_access              33
-#define __NR_nice                34
-#define __NR_sync                36
-#define __NR_kill                37
-#define __NR_rename              38
-#define __NR_mkdir               39
-#define __NR_rmdir               40
-#define __NR_dup                 41
-#define __NR_pipe                42
-#define __NR_times               43
-#define __NR_brk                 45
-#define __NR_signal              48
-#define __NR_acct                51
-#define __NR_umount2             52
-#define __NR_ioctl               54
-#define __NR_fcntl               55
-#define __NR_setpgid             57
-#define __NR_umask               60
-#define __NR_chroot              61
-#define __NR_ustat               62
-#define __NR_dup2                63
-#define __NR_getppid             64
-#define __NR_getpgrp             65
-#define __NR_setsid              66
-#define __NR_sigaction           67
-#define __NR_sigsuspend          72
-#define __NR_sigpending          73
-#define __NR_sethostname         74
-#define __NR_setrlimit           75
-#define __NR_getrusage           77
-#define __NR_gettimeofday        78
-#define __NR_settimeofday        79
-#define __NR_symlink             83
-#define __NR_readlink            85
-#define __NR_uselib              86
-#define __NR_swapon              87
-#define __NR_reboot              88
-#define __NR_readdir             89
-#define __NR_mmap                90
-#define __NR_munmap              91
-#define __NR_truncate            92
-#define __NR_ftruncate           93
-#define __NR_fchmod              94
-#define __NR_getpriority         96
-#define __NR_setpriority         97
-#define __NR_statfs              99
-#define __NR_fstatfs            100
-#define __NR_socketcall         102
-#define __NR_syslog             103
-#define __NR_setitimer          104
-#define __NR_getitimer          105
-#define __NR_stat               106
-#define __NR_lstat              107
-#define __NR_fstat              108
-#define __NR_lookup_dcookie     110
-#define __NR_vhangup            111
-#define __NR_idle               112
-#define __NR_wait4              114
-#define __NR_swapoff            115
-#define __NR_sysinfo            116
-#define __NR_ipc                117
-#define __NR_fsync              118
-#define __NR_sigreturn          119
-#define __NR_clone              120
-#define __NR_setdomainname      121
-#define __NR_uname              122
-#define __NR_adjtimex           124
-#define __NR_mprotect           125
-#define __NR_sigprocmask        126
-#define __NR_create_module      127
-#define __NR_init_module        128
-#define __NR_delete_module      129
-#define __NR_get_kernel_syms    130
-#define __NR_quotactl           131
-#define __NR_getpgid            132
-#define __NR_fchdir             133
-#define __NR_bdflush            134
-#define __NR_sysfs              135
-#define __NR_personality        136
-#define __NR_afs_syscall        137 /* Syscall for Andrew File System */
-#define __NR_getdents           141
-#define __NR_flock              143
-#define __NR_msync              144
-#define __NR_readv              145
-#define __NR_writev             146
-#define __NR_getsid             147
-#define __NR_fdatasync          148
-#define __NR__sysctl            149
-#define __NR_mlock              150
-#define __NR_munlock            151
-#define __NR_mlockall           152
-#define __NR_munlockall         153
-#define __NR_sched_setparam             154
-#define __NR_sched_getparam             155
-#define __NR_sched_setscheduler         156
-#define __NR_sched_getscheduler         157
-#define __NR_sched_yield                158
-#define __NR_sched_get_priority_max     159
-#define __NR_sched_get_priority_min     160
-#define __NR_sched_rr_get_interval      161
-#define __NR_nanosleep          162
-#define __NR_mremap             163
-#define __NR_query_module       167
-#define __NR_poll               168
-#define __NR_nfsservctl         169
-#define __NR_prctl              172
-#define __NR_rt_sigreturn       173
-#define __NR_rt_sigaction       174
-#define __NR_rt_sigprocmask     175
-#define __NR_rt_sigpending      176
-#define __NR_rt_sigtimedwait    177
-#define __NR_rt_sigqueueinfo    178
-#define __NR_rt_sigsuspend      179
-#define __NR_pread64            180
-#define __NR_pwrite64           181
-#define __NR_getcwd             183
-#define __NR_capget             184
-#define __NR_capset             185
-#define __NR_sigaltstack        186
-#define __NR_sendfile           187
-#define __NR_getpmsg           188
-#define __NR_putpmsg           189
-#define __NR_vfork             190
-#define __NR_pivot_root         217
-#define __NR_mincore            218
-#define __NR_madvise            219
-#define __NR_getdents64                220
-#define __NR_readahead         222
-#define __NR_setxattr          224
-#define __NR_lsetxattr         225
-#define __NR_fsetxattr         226
-#define __NR_getxattr          227
-#define __NR_lgetxattr         228
-#define __NR_fgetxattr         229
-#define __NR_listxattr         230
-#define __NR_llistxattr                231
-#define __NR_flistxattr                232
-#define __NR_removexattr       233
-#define __NR_lremovexattr      234
-#define __NR_fremovexattr      235
-#define __NR_gettid            236
-#define __NR_tkill             237
-#define __NR_futex             238
-#define __NR_sched_setaffinity 239
-#define __NR_sched_getaffinity 240
-#define __NR_tgkill            241
-/* Number 242 is reserved for tux */
-#define __NR_io_setup          243
-#define __NR_io_destroy                244
-#define __NR_io_getevents      245
-#define __NR_io_submit         246
-#define __NR_io_cancel         247
-#define __NR_exit_group                248
-#define __NR_epoll_create      249
-#define __NR_epoll_ctl         250
-#define __NR_epoll_wait                251
-#define __NR_set_tid_address   252
-#define __NR_fadvise64         253
-#define __NR_timer_create      254
-#define __NR_timer_settime     (__NR_timer_create+1)
-#define __NR_timer_gettime     (__NR_timer_create+2)
-#define __NR_timer_getoverrun  (__NR_timer_create+3)
-#define __NR_timer_delete      (__NR_timer_create+4)
-#define __NR_clock_settime     (__NR_timer_create+5)
-#define __NR_clock_gettime     (__NR_timer_create+6)
-#define __NR_clock_getres      (__NR_timer_create+7)
-#define __NR_clock_nanosleep   (__NR_timer_create+8)
-/* Number 263 is reserved for vserver */
-#define __NR_statfs64          265
-#define __NR_fstatfs64         266
-#define __NR_remap_file_pages  267
-/* Number 268 is reserved for new sys_mbind */
-/* Number 269 is reserved for new sys_get_mempolicy */
-/* Number 270 is reserved for new sys_set_mempolicy */
-#define __NR_mq_open           271
-#define __NR_mq_unlink         272
-#define __NR_mq_timedsend      273
-#define __NR_mq_timedreceive   274
-#define __NR_mq_notify         275
-#define __NR_mq_getsetattr     276
-#define __NR_kexec_load                277
-#define __NR_add_key           278
-#define __NR_request_key       279
-#define __NR_keyctl            280
-#define __NR_waitid            281
-#define __NR_ioprio_set                282
-#define __NR_ioprio_get                283
-#define __NR_inotify_init      284
-#define __NR_inotify_add_watch 285
-#define __NR_inotify_rm_watch  286
-/* Number 287 is reserved for new sys_migrate_pages */
-#define __NR_openat            288
-#define __NR_mkdirat           289
-#define __NR_mknodat           290
-#define __NR_fchownat          291
-#define __NR_futimesat         292
-#define __NR_unlinkat          294
-#define __NR_renameat          295
-#define __NR_linkat            296
-#define __NR_symlinkat         297
-#define __NR_readlinkat                298
-#define __NR_fchmodat          299
-#define __NR_faccessat         300
-#define __NR_pselect6          301
-#define __NR_ppoll             302
-#define __NR_unshare           303
-#define __NR_set_robust_list   304
-#define __NR_get_robust_list   305
-#define __NR_splice            306
-#define __NR_sync_file_range   307
-#define __NR_tee               308
-#define __NR_vmsplice          309
-/* Number 310 is reserved for new sys_move_pages */
-#define __NR_getcpu            311
-#define __NR_epoll_pwait       312
-#define __NR_utimes            313
-#define __NR_fallocate         314
-#define __NR_utimensat         315
-#define __NR_signalfd          316
-#define __NR_timerfd           317
-#define __NR_eventfd           318
-#define __NR_timerfd_create    319
-#define __NR_timerfd_settime   320
-#define __NR_timerfd_gettime   321
-#define __NR_signalfd4         322
-#define __NR_eventfd2          323
-#define __NR_inotify_init1     324
-#define __NR_pipe2             325
-#define __NR_dup3              326
-#define __NR_epoll_create1     327
-#define        __NR_preadv             328
-#define        __NR_pwritev            329
-#define __NR_rt_tgsigqueueinfo 330
-#define __NR_perf_event_open   331
-#define __NR_fanotify_init     332
-#define __NR_fanotify_mark     333
-#define __NR_prlimit64         334
-#define __NR_name_to_handle_at 335
-#define __NR_open_by_handle_at 336
-#define __NR_clock_adjtime     337
-#define __NR_syncfs            338
-#define __NR_setns             339
-#define __NR_process_vm_readv  340
-#define __NR_process_vm_writev 341
-#define __NR_s390_runtime_instr 342
-#define __NR_kcmp              343
-#define NR_syscalls 344
-
-/* 
- * There are some system calls that are not present on 64 bit, some
- * have a different name although they do the same (e.g. __NR_chown32
- * is __NR_chown on 64 bit).
- */
-#ifndef __s390x__
-
-#define __NR_time               13
-#define __NR_lchown             16
-#define __NR_setuid             23
-#define __NR_getuid             24
-#define __NR_stime              25
-#define __NR_setgid             46
-#define __NR_getgid             47
-#define __NR_geteuid            49
-#define __NR_getegid            50
-#define __NR_setreuid           70
-#define __NR_setregid           71
-#define __NR_getrlimit          76
-#define __NR_getgroups          80
-#define __NR_setgroups          81
-#define __NR_fchown             95
-#define __NR_ioperm            101
-#define __NR_setfsuid          138
-#define __NR_setfsgid          139
-#define __NR__llseek           140
-#define __NR__newselect        142
-#define __NR_setresuid         164
-#define __NR_getresuid         165
-#define __NR_setresgid         170
-#define __NR_getresgid         171
-#define __NR_chown             182
-#define __NR_ugetrlimit                191     /* SuS compliant getrlimit */
-#define __NR_mmap2             192
-#define __NR_truncate64                193
-#define __NR_ftruncate64       194
-#define __NR_stat64            195
-#define __NR_lstat64           196
-#define __NR_fstat64           197
-#define __NR_lchown32          198
-#define __NR_getuid32          199
-#define __NR_getgid32          200
-#define __NR_geteuid32         201
-#define __NR_getegid32         202
-#define __NR_setreuid32                203
-#define __NR_setregid32                204
-#define __NR_getgroups32       205
-#define __NR_setgroups32       206
-#define __NR_fchown32          207
-#define __NR_setresuid32       208
-#define __NR_getresuid32       209
-#define __NR_setresgid32       210
-#define __NR_getresgid32       211
-#define __NR_chown32           212
-#define __NR_setuid32          213
-#define __NR_setgid32          214
-#define __NR_setfsuid32                215
-#define __NR_setfsgid32                216
-#define __NR_fcntl64           221
-#define __NR_sendfile64                223
-#define __NR_fadvise64_64      264
-#define __NR_fstatat64         293
-
-#else
-
-#define __NR_select            142
-#define __NR_getrlimit         191     /* SuS compliant getrlimit */
-#define __NR_lchown            198
-#define __NR_getuid            199
-#define __NR_getgid            200
-#define __NR_geteuid           201
-#define __NR_getegid           202
-#define __NR_setreuid                  203
-#define __NR_setregid                  204
-#define __NR_getgroups         205
-#define __NR_setgroups         206
-#define __NR_fchown            207
-#define __NR_setresuid         208
-#define __NR_getresuid         209
-#define __NR_setresgid         210
-#define __NR_getresgid         211
-#define __NR_chown             212
-#define __NR_setuid            213
-#define __NR_setgid            214
-#define __NR_setfsuid                  215
-#define __NR_setfsgid                  216
-#define __NR_newfstatat                293
-
-#endif
+#include <uapi/asm/unistd.h>
 
-#ifdef __KERNEL__
 
 #ifndef CONFIG_64BIT
 #define __IGNORE_select
 #   define __ARCH_WANT_COMPAT_SYS_TIME
 #   define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 # endif
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_S390_UNISTD_H_ */
index baebb3da1d44160fc6f6f259886656e6f494b167..7bf68fff7c5d28cd2255d8d86189eb55368ddd71 100644 (file)
@@ -1,3 +1,48 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += auxvec.h
+header-y += bitsperlong.h
+header-y += byteorder.h
+header-y += chpid.h
+header-y += chsc.h
+header-y += cmb.h
+header-y += dasd.h
+header-y += debug.h
+header-y += errno.h
+header-y += fcntl.h
+header-y += ioctl.h
+header-y += ioctls.h
+header-y += ipcbuf.h
+header-y += kvm.h
+header-y += kvm_para.h
+header-y += kvm_virtio.h
+header-y += mman.h
+header-y += monwriter.h
+header-y += msgbuf.h
+header-y += param.h
+header-y += poll.h
+header-y += posix_types.h
+header-y += ptrace.h
+header-y += qeth.h
+header-y += resource.h
+header-y += schid.h
+header-y += sembuf.h
+header-y += setup.h
+header-y += shmbuf.h
+header-y += sigcontext.h
+header-y += siginfo.h
+header-y += signal.h
+header-y += socket.h
+header-y += sockios.h
+header-y += stat.h
+header-y += statfs.h
+header-y += swab.h
+header-y += tape390.h
+header-y += termbits.h
+header-y += termios.h
+header-y += types.h
+header-y += ucontext.h
+header-y += unistd.h
+header-y += vtoc.h
+header-y += zcrypt.h
diff --git a/arch/s390/include/uapi/asm/chpid.h b/arch/s390/include/uapi/asm/chpid.h
new file mode 100644 (file)
index 0000000..581992d
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
+ */
+
+#ifndef _UAPI_ASM_S390_CHPID_H
+#define _UAPI_ASM_S390_CHPID_H
+
+#include <linux/string.h>
+#include <linux/types.h>
+
+#define __MAX_CHPID 255
+
+struct chp_id {
+       u8 reserved1;
+       u8 cssid;
+       u8 reserved2;
+       u8 id;
+} __attribute__((packed));
+
+
+#endif /* _UAPI_ASM_S390_CHPID_H */
similarity index 92%
rename from arch/s390/include/asm/chsc.h
rename to arch/s390/include/uapi/asm/chsc.h
index aea451fd182ec123982cd3321b06aa3110f85645..1c6a7f85a5819d5354acb38f91820be5767d789c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ioctl interface for /dev/chsc
  *
- * Copyright IBM Corp. 2008
+ * Copyright IBM Corp. 2008, 2012
  * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
  */
 
@@ -9,9 +9,12 @@
 #define _ASM_CHSC_H
 
 #include <linux/types.h>
+#include <linux/ioctl.h>
 #include <asm/chpid.h>
 #include <asm/schid.h>
 
+#define CHSC_SIZE 0x1000
+
 struct chsc_async_header {
        __u16 length;
        __u16 code;
@@ -23,15 +26,14 @@ struct chsc_async_header {
 
 struct chsc_async_area {
        struct chsc_async_header header;
-       __u8 data[PAGE_SIZE - 16 /* size of chsc_async_header */];
+       __u8 data[CHSC_SIZE - sizeof(struct chsc_async_header)];
 } __attribute__ ((packed));
 
-
 struct chsc_response_struct {
        __u16 length;
        __u16 code;
        __u32 parms;
-       __u8 data[PAGE_SIZE - 8];
+       __u8 data[CHSC_SIZE - 2 * sizeof(__u16) - sizeof(__u32)];
 } __attribute__ ((packed));
 
 struct chsc_chp_cd {
diff --git a/arch/s390/include/uapi/asm/cmb.h b/arch/s390/include/uapi/asm/cmb.h
new file mode 100644 (file)
index 0000000..0c086d0
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _UAPIS390_CMB_H
+#define _UAPIS390_CMB_H
+
+#include <linux/types.h>
+
+/**
+ * struct cmbdata - channel measurement block data for user space
+ * @size: size of the stored data
+ * @elapsed_time: time since last sampling
+ * @ssch_rsch_count: number of ssch and rsch
+ * @sample_count: number of samples
+ * @device_connect_time: time of device connect
+ * @function_pending_time: time of function pending
+ * @device_disconnect_time: time of device disconnect
+ * @control_unit_queuing_time: time of control unit queuing
+ * @device_active_only_time: time of device active only
+ * @device_busy_time: time of device busy (ext. format)
+ * @initial_command_response_time: initial command response time (ext. format)
+ *
+ * All values are stored as 64 bit for simplicity, especially
+ * in 32 bit emulation mode. All time values are normalized to
+ * nanoseconds.
+ * Currently, two formats are known, which differ by the size of
+ * this structure, i.e. the last two members are only set when
+ * the extended channel measurement facility (first shipped in
+ * z990 machines) is activated.
+ * Potentially, more fields could be added, which would result in a
+ * new ioctl number.
+ */
+struct cmbdata {
+       __u64 size;
+       __u64 elapsed_time;
+ /* basic and exended format: */
+       __u64 ssch_rsch_count;
+       __u64 sample_count;
+       __u64 device_connect_time;
+       __u64 function_pending_time;
+       __u64 device_disconnect_time;
+       __u64 control_unit_queuing_time;
+       __u64 device_active_only_time;
+ /* extended format only: */
+       __u64 device_busy_time;
+       __u64 initial_command_response_time;
+};
+
+/* enable channel measurement */
+#define BIODASDCMFENABLE       _IO(DASD_IOCTL_LETTER, 32)
+/* enable channel measurement */
+#define BIODASDCMFDISABLE      _IO(DASD_IOCTL_LETTER, 33)
+/* read channel measurement data */
+#define BIODASDREADALLCMB      _IOWR(DASD_IOCTL_LETTER, 33, struct cmbdata)
+
+#endif /* _UAPIS390_CMB_H */
diff --git a/arch/s390/include/uapi/asm/debug.h b/arch/s390/include/uapi/asm/debug.h
new file mode 100644 (file)
index 0000000..c59fc79
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *   S/390 debug facility
+ *
+ *    Copyright IBM Corp. 1999, 2000
+ */
+
+#ifndef _UAPIDEBUG_H
+#define _UAPIDEBUG_H
+
+#include <linux/fs.h>
+
+/* Note:
+ * struct __debug_entry must be defined outside of #ifdef __KERNEL__ 
+ * in order to allow a user program to analyze the 'raw'-view.
+ */
+
+struct __debug_entry{
+        union {
+                struct {
+                        unsigned long long clock:52;
+                        unsigned long long exception:1;
+                        unsigned long long level:3;
+                        unsigned long long cpuid:8;
+                } fields;
+
+                unsigned long long stck;
+        } id;
+        void* caller;
+} __attribute__((packed));
+
+
+#define __DEBUG_FEATURE_VERSION      2  /* version of debug feature */
+
+#endif /* _UAPIDEBUG_H */
diff --git a/arch/s390/include/uapi/asm/kvm_para.h b/arch/s390/include/uapi/asm/kvm_para.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/arch/s390/include/uapi/asm/mman.h b/arch/s390/include/uapi/asm/mman.h
new file mode 100644 (file)
index 0000000..de23da1
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/mman.h"
+ */
+#include <asm-generic/mman.h>
diff --git a/arch/s390/include/uapi/asm/ptrace.h b/arch/s390/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..705588a
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ *  S390 version
+ *    Copyright IBM Corp. 1999, 2000
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ */
+
+#ifndef _UAPI_S390_PTRACE_H
+#define _UAPI_S390_PTRACE_H
+
+/*
+ * Offsets in the user_regs_struct. They are used for the ptrace
+ * system call and in entry.S
+ */
+#ifndef __s390x__
+
+#define PT_PSWMASK  0x00
+#define PT_PSWADDR  0x04
+#define PT_GPR0     0x08
+#define PT_GPR1     0x0C
+#define PT_GPR2     0x10
+#define PT_GPR3     0x14
+#define PT_GPR4     0x18
+#define PT_GPR5     0x1C
+#define PT_GPR6     0x20
+#define PT_GPR7     0x24
+#define PT_GPR8     0x28
+#define PT_GPR9     0x2C
+#define PT_GPR10    0x30
+#define PT_GPR11    0x34
+#define PT_GPR12    0x38
+#define PT_GPR13    0x3C
+#define PT_GPR14    0x40
+#define PT_GPR15    0x44
+#define PT_ACR0     0x48
+#define PT_ACR1     0x4C
+#define PT_ACR2     0x50
+#define PT_ACR3     0x54
+#define PT_ACR4            0x58
+#define PT_ACR5            0x5C
+#define PT_ACR6            0x60
+#define PT_ACR7            0x64
+#define PT_ACR8            0x68
+#define PT_ACR9            0x6C
+#define PT_ACR10    0x70
+#define PT_ACR11    0x74
+#define PT_ACR12    0x78
+#define PT_ACR13    0x7C
+#define PT_ACR14    0x80
+#define PT_ACR15    0x84
+#define PT_ORIGGPR2 0x88
+#define PT_FPC     0x90
+/*
+ * A nasty fact of life that the ptrace api
+ * only supports passing of longs.
+ */
+#define PT_FPR0_HI  0x98
+#define PT_FPR0_LO  0x9C
+#define PT_FPR1_HI  0xA0
+#define PT_FPR1_LO  0xA4
+#define PT_FPR2_HI  0xA8
+#define PT_FPR2_LO  0xAC
+#define PT_FPR3_HI  0xB0
+#define PT_FPR3_LO  0xB4
+#define PT_FPR4_HI  0xB8
+#define PT_FPR4_LO  0xBC
+#define PT_FPR5_HI  0xC0
+#define PT_FPR5_LO  0xC4
+#define PT_FPR6_HI  0xC8
+#define PT_FPR6_LO  0xCC
+#define PT_FPR7_HI  0xD0
+#define PT_FPR7_LO  0xD4
+#define PT_FPR8_HI  0xD8
+#define PT_FPR8_LO  0XDC
+#define PT_FPR9_HI  0xE0
+#define PT_FPR9_LO  0xE4
+#define PT_FPR10_HI 0xE8
+#define PT_FPR10_LO 0xEC
+#define PT_FPR11_HI 0xF0
+#define PT_FPR11_LO 0xF4
+#define PT_FPR12_HI 0xF8
+#define PT_FPR12_LO 0xFC
+#define PT_FPR13_HI 0x100
+#define PT_FPR13_LO 0x104
+#define PT_FPR14_HI 0x108
+#define PT_FPR14_LO 0x10C
+#define PT_FPR15_HI 0x110
+#define PT_FPR15_LO 0x114
+#define PT_CR_9            0x118
+#define PT_CR_10    0x11C
+#define PT_CR_11    0x120
+#define PT_IEEE_IP  0x13C
+#define PT_LASTOFF  PT_IEEE_IP
+#define PT_ENDREGS  0x140-1
+
+#define GPR_SIZE       4
+#define CR_SIZE                4
+
+#define STACK_FRAME_OVERHEAD   96      /* size of minimum stack frame */
+
+#else /* __s390x__ */
+
+#define PT_PSWMASK  0x00
+#define PT_PSWADDR  0x08
+#define PT_GPR0     0x10
+#define PT_GPR1     0x18
+#define PT_GPR2     0x20
+#define PT_GPR3     0x28
+#define PT_GPR4     0x30
+#define PT_GPR5     0x38
+#define PT_GPR6     0x40
+#define PT_GPR7     0x48
+#define PT_GPR8     0x50
+#define PT_GPR9     0x58
+#define PT_GPR10    0x60
+#define PT_GPR11    0x68
+#define PT_GPR12    0x70
+#define PT_GPR13    0x78
+#define PT_GPR14    0x80
+#define PT_GPR15    0x88
+#define PT_ACR0     0x90
+#define PT_ACR1     0x94
+#define PT_ACR2     0x98
+#define PT_ACR3     0x9C
+#define PT_ACR4            0xA0
+#define PT_ACR5            0xA4
+#define PT_ACR6            0xA8
+#define PT_ACR7            0xAC
+#define PT_ACR8            0xB0
+#define PT_ACR9            0xB4
+#define PT_ACR10    0xB8
+#define PT_ACR11    0xBC
+#define PT_ACR12    0xC0
+#define PT_ACR13    0xC4
+#define PT_ACR14    0xC8
+#define PT_ACR15    0xCC
+#define PT_ORIGGPR2 0xD0
+#define PT_FPC     0xD8
+#define PT_FPR0     0xE0
+#define PT_FPR1     0xE8
+#define PT_FPR2     0xF0
+#define PT_FPR3     0xF8
+#define PT_FPR4     0x100
+#define PT_FPR5     0x108
+#define PT_FPR6     0x110
+#define PT_FPR7     0x118
+#define PT_FPR8     0x120
+#define PT_FPR9     0x128
+#define PT_FPR10    0x130
+#define PT_FPR11    0x138
+#define PT_FPR12    0x140
+#define PT_FPR13    0x148
+#define PT_FPR14    0x150
+#define PT_FPR15    0x158
+#define PT_CR_9     0x160
+#define PT_CR_10    0x168
+#define PT_CR_11    0x170
+#define PT_IEEE_IP  0x1A8
+#define PT_LASTOFF  PT_IEEE_IP
+#define PT_ENDREGS  0x1B0-1
+
+#define GPR_SIZE       8
+#define CR_SIZE                8
+
+#define STACK_FRAME_OVERHEAD    160      /* size of minimum stack frame */
+
+#endif /* __s390x__ */
+
+#define NUM_GPRS       16
+#define NUM_FPRS       16
+#define NUM_CRS                16
+#define NUM_ACRS       16
+
+#define NUM_CR_WORDS   3
+
+#define FPR_SIZE       8
+#define FPC_SIZE       4
+#define FPC_PAD_SIZE   4 /* gcc insists on aligning the fpregs */
+#define ACR_SIZE       4
+
+
+#define PTRACE_OLDSETOPTIONS         21
+
+#ifndef __ASSEMBLY__
+#include <linux/stddef.h>
+#include <linux/types.h>
+
+typedef union
+{
+       float   f;
+       double  d;
+        __u64   ui;
+       struct
+       {
+               __u32 hi;
+               __u32 lo;
+       } fp;
+} freg_t;
+
+typedef struct
+{
+       __u32   fpc;
+       freg_t  fprs[NUM_FPRS];              
+} s390_fp_regs;
+
+#define FPC_EXCEPTION_MASK      0xF8000000
+#define FPC_FLAGS_MASK          0x00F80000
+#define FPC_DXC_MASK            0x0000FF00
+#define FPC_RM_MASK             0x00000003
+#define FPC_VALID_MASK          0xF8F8FF03
+
+/* this typedef defines how a Program Status Word looks like */
+typedef struct 
+{
+        unsigned long mask;
+        unsigned long addr;
+} __attribute__ ((aligned(8))) psw_t;
+
+typedef struct
+{
+       __u32   mask;
+       __u32   addr;
+} __attribute__ ((aligned(8))) psw_compat_t;
+
+#ifndef __s390x__
+
+#define PSW_MASK_PER           0x40000000UL
+#define PSW_MASK_DAT           0x04000000UL
+#define PSW_MASK_IO            0x02000000UL
+#define PSW_MASK_EXT           0x01000000UL
+#define PSW_MASK_KEY           0x00F00000UL
+#define PSW_MASK_BASE          0x00080000UL    /* always one */
+#define PSW_MASK_MCHECK                0x00040000UL
+#define PSW_MASK_WAIT          0x00020000UL
+#define PSW_MASK_PSTATE                0x00010000UL
+#define PSW_MASK_ASC           0x0000C000UL
+#define PSW_MASK_CC            0x00003000UL
+#define PSW_MASK_PM            0x00000F00UL
+#define PSW_MASK_RI            0x00000000UL
+#define PSW_MASK_EA            0x00000000UL
+#define PSW_MASK_BA            0x00000000UL
+
+#define PSW_MASK_USER          0x00003F00UL
+
+#define PSW_ADDR_AMODE         0x80000000UL
+#define PSW_ADDR_INSN          0x7FFFFFFFUL
+
+#define PSW_DEFAULT_KEY                (((unsigned long) PAGE_DEFAULT_ACC) << 20)
+
+#define PSW_ASC_PRIMARY                0x00000000UL
+#define PSW_ASC_ACCREG         0x00004000UL
+#define PSW_ASC_SECONDARY      0x00008000UL
+#define PSW_ASC_HOME           0x0000C000UL
+
+#else /* __s390x__ */
+
+#define PSW_MASK_PER           0x4000000000000000UL
+#define PSW_MASK_DAT           0x0400000000000000UL
+#define PSW_MASK_IO            0x0200000000000000UL
+#define PSW_MASK_EXT           0x0100000000000000UL
+#define PSW_MASK_BASE          0x0000000000000000UL
+#define PSW_MASK_KEY           0x00F0000000000000UL
+#define PSW_MASK_MCHECK                0x0004000000000000UL
+#define PSW_MASK_WAIT          0x0002000000000000UL
+#define PSW_MASK_PSTATE                0x0001000000000000UL
+#define PSW_MASK_ASC           0x0000C00000000000UL
+#define PSW_MASK_CC            0x0000300000000000UL
+#define PSW_MASK_PM            0x00000F0000000000UL
+#define PSW_MASK_RI            0x0000008000000000UL
+#define PSW_MASK_EA            0x0000000100000000UL
+#define PSW_MASK_BA            0x0000000080000000UL
+
+#define PSW_MASK_USER          0x00003F8180000000UL
+
+#define PSW_ADDR_AMODE         0x0000000000000000UL
+#define PSW_ADDR_INSN          0xFFFFFFFFFFFFFFFFUL
+
+#define PSW_DEFAULT_KEY                (((unsigned long) PAGE_DEFAULT_ACC) << 52)
+
+#define PSW_ASC_PRIMARY                0x0000000000000000UL
+#define PSW_ASC_ACCREG         0x0000400000000000UL
+#define PSW_ASC_SECONDARY      0x0000800000000000UL
+#define PSW_ASC_HOME           0x0000C00000000000UL
+
+#endif /* __s390x__ */
+
+
+/*
+ * The s390_regs structure is used to define the elf_gregset_t.
+ */
+typedef struct
+{
+       psw_t psw;
+       unsigned long gprs[NUM_GPRS];
+       unsigned int  acrs[NUM_ACRS];
+       unsigned long orig_gpr2;
+} s390_regs;
+
+typedef struct
+{
+       psw_compat_t    psw;
+       __u32           gprs[NUM_GPRS];
+       __u32           acrs[NUM_ACRS];
+       __u32           orig_gpr2;
+} s390_compat_regs;
+
+typedef struct
+{
+       __u32           gprs_high[NUM_GPRS];
+} s390_compat_regs_high;
+
+
+/*
+ * Now for the user space program event recording (trace) definitions.
+ * The following structures are used only for the ptrace interface, don't
+ * touch or even look at it if you don't want to modify the user-space
+ * ptrace interface. In particular stay away from it for in-kernel PER.
+ */
+typedef struct
+{
+       unsigned long cr[NUM_CR_WORDS];
+} per_cr_words;
+
+#define PER_EM_MASK 0xE8000000UL
+
+typedef        struct
+{
+#ifdef __s390x__
+       unsigned                       : 32;
+#endif /* __s390x__ */
+       unsigned em_branching          : 1;
+       unsigned em_instruction_fetch  : 1;
+       /*
+        * Switching on storage alteration automatically fixes
+        * the storage alteration event bit in the users std.
+        */
+       unsigned em_storage_alteration : 1;
+       unsigned em_gpr_alt_unused     : 1;
+       unsigned em_store_real_address : 1;
+       unsigned                       : 3;
+       unsigned branch_addr_ctl       : 1;
+       unsigned                       : 1;
+       unsigned storage_alt_space_ctl : 1;
+       unsigned                       : 21;
+       unsigned long starting_addr;
+       unsigned long ending_addr;
+} per_cr_bits;
+
+typedef struct
+{
+       unsigned short perc_atmid;
+       unsigned long address;
+       unsigned char access_id;
+} per_lowcore_words;
+
+typedef struct
+{
+       unsigned perc_branching          : 1;
+       unsigned perc_instruction_fetch  : 1;
+       unsigned perc_storage_alteration : 1;
+       unsigned perc_gpr_alt_unused     : 1;
+       unsigned perc_store_real_address : 1;
+       unsigned                         : 3;
+       unsigned atmid_psw_bit_31        : 1;
+       unsigned atmid_validity_bit      : 1;
+       unsigned atmid_psw_bit_32        : 1;
+       unsigned atmid_psw_bit_5         : 1;
+       unsigned atmid_psw_bit_16        : 1;
+       unsigned atmid_psw_bit_17        : 1;
+       unsigned si                      : 2;
+       unsigned long address;
+       unsigned                         : 4;
+       unsigned access_id               : 4;
+} per_lowcore_bits;
+
+typedef struct
+{
+       union {
+               per_cr_words   words;
+               per_cr_bits    bits;
+       } control_regs;
+       /*
+        * Use these flags instead of setting em_instruction_fetch
+        * directly they are used so that single stepping can be
+        * switched on & off while not affecting other tracing
+        */
+       unsigned  single_step       : 1;
+       unsigned  instruction_fetch : 1;
+       unsigned                    : 30;
+       /*
+        * These addresses are copied into cr10 & cr11 if single
+        * stepping is switched off
+        */
+       unsigned long starting_addr;
+       unsigned long ending_addr;
+       union {
+               per_lowcore_words words;
+               per_lowcore_bits  bits;
+       } lowcore; 
+} per_struct;
+
+typedef struct
+{
+       unsigned int  len;
+       unsigned long kernel_addr;
+       unsigned long process_addr;
+} ptrace_area;
+
+/*
+ * S/390 specific non posix ptrace requests. I chose unusual values so
+ * they are unlikely to clash with future ptrace definitions.
+ */
+#define PTRACE_PEEKUSR_AREA           0x5000
+#define PTRACE_POKEUSR_AREA           0x5001
+#define PTRACE_PEEKTEXT_AREA         0x5002
+#define PTRACE_PEEKDATA_AREA         0x5003
+#define PTRACE_POKETEXT_AREA         0x5004
+#define PTRACE_POKEDATA_AREA         0x5005
+#define PTRACE_GET_LAST_BREAK        0x5006
+#define PTRACE_PEEK_SYSTEM_CALL       0x5007
+#define PTRACE_POKE_SYSTEM_CALL              0x5008
+#define PTRACE_ENABLE_TE             0x5009
+#define PTRACE_DISABLE_TE            0x5010
+
+/*
+ * PT_PROT definition is loosely based on hppa bsd definition in
+ * gdb/hppab-nat.c
+ */
+#define PTRACE_PROT                       21
+
+typedef enum
+{
+       ptprot_set_access_watchpoint,
+       ptprot_set_write_watchpoint,
+       ptprot_disable_watchpoint
+} ptprot_flags;
+
+typedef struct
+{
+       unsigned long lowaddr;
+       unsigned long hiaddr;
+       ptprot_flags prot;
+} ptprot_area;                     
+
+/* Sequence of bytes for breakpoint illegal instruction.  */
+#define S390_BREAKPOINT     {0x0,0x1}
+#define S390_BREAKPOINT_U16 ((__u16)0x0001)
+#define S390_SYSCALL_OPCODE ((__u16)0x0a00)
+#define S390_SYSCALL_SIZE   2
+
+/*
+ * The user_regs_struct defines the way the user registers are
+ * store on the stack for signal handling.
+ */
+struct user_regs_struct
+{
+       psw_t psw;
+       unsigned long gprs[NUM_GPRS];
+       unsigned int  acrs[NUM_ACRS];
+       unsigned long orig_gpr2;
+       s390_fp_regs fp_regs;
+       /*
+        * These per registers are in here so that gdb can modify them
+        * itself as there is no "official" ptrace interface for hardware
+        * watchpoints. This is the way intel does it.
+        */
+       per_struct per_info;
+       unsigned long ieee_instruction_pointer; /* obsolete, always 0 */
+};
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _UAPI_S390_PTRACE_H */
diff --git a/arch/s390/include/uapi/asm/schid.h b/arch/s390/include/uapi/asm/schid.h
new file mode 100644 (file)
index 0000000..32f3ab2
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _UAPIASM_SCHID_H
+#define _UAPIASM_SCHID_H
+
+#include <linux/types.h>
+
+struct subchannel_id {
+       __u32 cssid : 8;
+       __u32 : 4;
+       __u32 m : 1;
+       __u32 ssid : 2;
+       __u32 one : 1;
+       __u32 sch_no : 16;
+} __attribute__ ((packed, aligned(4)));
+
+
+#endif /* _UAPIASM_SCHID_H */
diff --git a/arch/s390/include/uapi/asm/setup.h b/arch/s390/include/uapi/asm/setup.h
new file mode 100644 (file)
index 0000000..5a637e3
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ *  S390 version
+ *    Copyright IBM Corp. 1999, 2010
+ */
+
+#ifndef _UAPI_ASM_S390_SETUP_H
+#define _UAPI_ASM_S390_SETUP_H
+
+#define COMMAND_LINE_SIZE      4096
+
+#define ARCH_COMMAND_LINE_SIZE 896
+
+#endif /* _UAPI_ASM_S390_SETUP_H */
diff --git a/arch/s390/include/uapi/asm/signal.h b/arch/s390/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..8c6a49e
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/signal.h"
+ */
+
+#ifndef _UAPI_ASMS390_SIGNAL_H
+#define _UAPI_ASMS390_SIGNAL_H
+
+#include <linux/types.h>
+#include <linux/time.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+struct pt_regs;
+
+#ifndef __KERNEL__
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG            32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
+#define SIGHUP           1
+#define SIGINT           2
+#define SIGQUIT          3
+#define SIGILL           4
+#define SIGTRAP          5
+#define SIGABRT          6
+#define SIGIOT           6
+#define SIGBUS           7
+#define SIGFPE           8
+#define SIGKILL          9
+#define SIGUSR1         10
+#define SIGSEGV         11
+#define SIGUSR2         12
+#define SIGPIPE         13
+#define SIGALRM         14
+#define SIGTERM         15
+#define SIGSTKFLT       16
+#define SIGCHLD         17
+#define SIGCONT         18
+#define SIGSTOP         19
+#define SIGTSTP         20
+#define SIGTTIN         21
+#define SIGTTOU         22
+#define SIGURG          23
+#define SIGXCPU         24
+#define SIGXFSZ         25
+#define SIGVTALRM       26
+#define SIGPROF         27
+#define SIGWINCH        28
+#define SIGIO           29
+#define SIGPOLL         SIGIO
+/*
+#define SIGLOST         29
+*/
+#define SIGPWR          30
+#define SIGSYS         31
+#define SIGUNUSED       31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN        32
+#define SIGRTMAX        _NSIG
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP    0x00000001
+#define SA_NOCLDWAIT    0x00000002
+#define SA_SIGINFO      0x00000004
+#define SA_ONSTACK      0x08000000
+#define SA_RESTART      0x10000000
+#define SA_NODEFER      0x40000000
+#define SA_RESETHAND    0x80000000
+
+#define SA_NOMASK       SA_NODEFER
+#define SA_ONESHOT      SA_RESETHAND
+
+#define SA_RESTORER     0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK      1
+#define SS_DISABLE      2
+
+#define MINSIGSTKSZ     2048
+#define SIGSTKSZ        8192
+
+#include <asm-generic/signal-defs.h>
+
+#ifndef __KERNEL__
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+        union {
+          __sighandler_t _sa_handler;
+          void (*_sa_sigaction)(int, struct siginfo *, void *);
+        } _u;
+#ifndef __s390x__ /* lovely */
+        sigset_t sa_mask;
+        unsigned long sa_flags;
+        void (*sa_restorer)(void);
+#else  /* __s390x__ */
+        unsigned long sa_flags;
+        void (*sa_restorer)(void);
+       sigset_t sa_mask;
+#endif /* __s390x__ */
+};
+
+#define sa_handler      _u._sa_handler
+#define sa_sigaction    _u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+        void __user *ss_sp;
+        int ss_flags;
+        size_t ss_size;
+} stack_t;
+
+
+#endif /* _UAPI_ASMS390_SIGNAL_H */
diff --git a/arch/s390/include/uapi/asm/termios.h b/arch/s390/include/uapi/asm/termios.h
new file mode 100644 (file)
index 0000000..554f973
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/termios.h"
+ */
+
+#ifndef _UAPI_S390_TERMIOS_H
+#define _UAPI_S390_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+       unsigned short ws_row;
+       unsigned short ws_col;
+       unsigned short ws_xpixel;
+       unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+       unsigned short c_iflag;         /* input mode flags */
+       unsigned short c_oflag;         /* output mode flags */
+       unsigned short c_cflag;         /* control mode flags */
+       unsigned short c_lflag;         /* local mode flags */
+       unsigned char c_line;           /* line discipline */
+       unsigned char c_cc[NCC];        /* control characters */
+};
+
+/* modem lines */
+#define TIOCM_LE       0x001
+#define TIOCM_DTR      0x002
+#define TIOCM_RTS      0x004
+#define TIOCM_ST       0x008
+#define TIOCM_SR       0x010
+#define TIOCM_CTS      0x020
+#define TIOCM_CAR      0x040
+#define TIOCM_RNG      0x080
+#define TIOCM_DSR      0x100
+#define TIOCM_CD       TIOCM_CAR
+#define TIOCM_RI       TIOCM_RNG
+#define TIOCM_OUT1     0x2000
+#define TIOCM_OUT2     0x4000
+#define TIOCM_LOOP     0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+
+#endif /* _UAPI_S390_TERMIOS_H */
diff --git a/arch/s390/include/uapi/asm/types.h b/arch/s390/include/uapi/asm/types.h
new file mode 100644 (file)
index 0000000..038f2b9
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/types.h"
+ */
+
+#ifndef _UAPI_S390_TYPES_H
+#define _UAPI_S390_TYPES_H
+
+#include <asm-generic/int-ll64.h>
+
+#ifndef __ASSEMBLY__
+
+/* A address type so that arithmetic can be done on it & it can be upgraded to
+   64 bit when necessary 
+*/
+typedef unsigned long addr_t; 
+typedef __signed__ long saddr_t;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _UAPI_S390_TYPES_H */
diff --git a/arch/s390/include/uapi/asm/unistd.h b/arch/s390/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..63e6078
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/unistd.h"
+ */
+
+#ifndef _UAPI_ASM_S390_UNISTD_H_
+#define _UAPI_ASM_S390_UNISTD_H_
+
+/*
+ * This file contains the system call numbers.
+ */
+
+#define __NR_exit                 1
+#define __NR_fork                 2
+#define __NR_read                 3
+#define __NR_write                4
+#define __NR_open                 5
+#define __NR_close                6
+#define __NR_restart_syscall     7
+#define __NR_creat                8
+#define __NR_link                 9
+#define __NR_unlink              10
+#define __NR_execve              11
+#define __NR_chdir               12
+#define __NR_mknod               14
+#define __NR_chmod               15
+#define __NR_lseek               19
+#define __NR_getpid              20
+#define __NR_mount               21
+#define __NR_umount              22
+#define __NR_ptrace              26
+#define __NR_alarm               27
+#define __NR_pause               29
+#define __NR_utime               30
+#define __NR_access              33
+#define __NR_nice                34
+#define __NR_sync                36
+#define __NR_kill                37
+#define __NR_rename              38
+#define __NR_mkdir               39
+#define __NR_rmdir               40
+#define __NR_dup                 41
+#define __NR_pipe                42
+#define __NR_times               43
+#define __NR_brk                 45
+#define __NR_signal              48
+#define __NR_acct                51
+#define __NR_umount2             52
+#define __NR_ioctl               54
+#define __NR_fcntl               55
+#define __NR_setpgid             57
+#define __NR_umask               60
+#define __NR_chroot              61
+#define __NR_ustat               62
+#define __NR_dup2                63
+#define __NR_getppid             64
+#define __NR_getpgrp             65
+#define __NR_setsid              66
+#define __NR_sigaction           67
+#define __NR_sigsuspend          72
+#define __NR_sigpending          73
+#define __NR_sethostname         74
+#define __NR_setrlimit           75
+#define __NR_getrusage           77
+#define __NR_gettimeofday        78
+#define __NR_settimeofday        79
+#define __NR_symlink             83
+#define __NR_readlink            85
+#define __NR_uselib              86
+#define __NR_swapon              87
+#define __NR_reboot              88
+#define __NR_readdir             89
+#define __NR_mmap                90
+#define __NR_munmap              91
+#define __NR_truncate            92
+#define __NR_ftruncate           93
+#define __NR_fchmod              94
+#define __NR_getpriority         96
+#define __NR_setpriority         97
+#define __NR_statfs              99
+#define __NR_fstatfs            100
+#define __NR_socketcall         102
+#define __NR_syslog             103
+#define __NR_setitimer          104
+#define __NR_getitimer          105
+#define __NR_stat               106
+#define __NR_lstat              107
+#define __NR_fstat              108
+#define __NR_lookup_dcookie     110
+#define __NR_vhangup            111
+#define __NR_idle               112
+#define __NR_wait4              114
+#define __NR_swapoff            115
+#define __NR_sysinfo            116
+#define __NR_ipc                117
+#define __NR_fsync              118
+#define __NR_sigreturn          119
+#define __NR_clone              120
+#define __NR_setdomainname      121
+#define __NR_uname              122
+#define __NR_adjtimex           124
+#define __NR_mprotect           125
+#define __NR_sigprocmask        126
+#define __NR_create_module      127
+#define __NR_init_module        128
+#define __NR_delete_module      129
+#define __NR_get_kernel_syms    130
+#define __NR_quotactl           131
+#define __NR_getpgid            132
+#define __NR_fchdir             133
+#define __NR_bdflush            134
+#define __NR_sysfs              135
+#define __NR_personality        136
+#define __NR_afs_syscall        137 /* Syscall for Andrew File System */
+#define __NR_getdents           141
+#define __NR_flock              143
+#define __NR_msync              144
+#define __NR_readv              145
+#define __NR_writev             146
+#define __NR_getsid             147
+#define __NR_fdatasync          148
+#define __NR__sysctl            149
+#define __NR_mlock              150
+#define __NR_munlock            151
+#define __NR_mlockall           152
+#define __NR_munlockall         153
+#define __NR_sched_setparam             154
+#define __NR_sched_getparam             155
+#define __NR_sched_setscheduler         156
+#define __NR_sched_getscheduler         157
+#define __NR_sched_yield                158
+#define __NR_sched_get_priority_max     159
+#define __NR_sched_get_priority_min     160
+#define __NR_sched_rr_get_interval      161
+#define __NR_nanosleep          162
+#define __NR_mremap             163
+#define __NR_query_module       167
+#define __NR_poll               168
+#define __NR_nfsservctl         169
+#define __NR_prctl              172
+#define __NR_rt_sigreturn       173
+#define __NR_rt_sigaction       174
+#define __NR_rt_sigprocmask     175
+#define __NR_rt_sigpending      176
+#define __NR_rt_sigtimedwait    177
+#define __NR_rt_sigqueueinfo    178
+#define __NR_rt_sigsuspend      179
+#define __NR_pread64            180
+#define __NR_pwrite64           181
+#define __NR_getcwd             183
+#define __NR_capget             184
+#define __NR_capset             185
+#define __NR_sigaltstack        186
+#define __NR_sendfile           187
+#define __NR_getpmsg           188
+#define __NR_putpmsg           189
+#define __NR_vfork             190
+#define __NR_pivot_root         217
+#define __NR_mincore            218
+#define __NR_madvise            219
+#define __NR_getdents64                220
+#define __NR_readahead         222
+#define __NR_setxattr          224
+#define __NR_lsetxattr         225
+#define __NR_fsetxattr         226
+#define __NR_getxattr          227
+#define __NR_lgetxattr         228
+#define __NR_fgetxattr         229
+#define __NR_listxattr         230
+#define __NR_llistxattr                231
+#define __NR_flistxattr                232
+#define __NR_removexattr       233
+#define __NR_lremovexattr      234
+#define __NR_fremovexattr      235
+#define __NR_gettid            236
+#define __NR_tkill             237
+#define __NR_futex             238
+#define __NR_sched_setaffinity 239
+#define __NR_sched_getaffinity 240
+#define __NR_tgkill            241
+/* Number 242 is reserved for tux */
+#define __NR_io_setup          243
+#define __NR_io_destroy                244
+#define __NR_io_getevents      245
+#define __NR_io_submit         246
+#define __NR_io_cancel         247
+#define __NR_exit_group                248
+#define __NR_epoll_create      249
+#define __NR_epoll_ctl         250
+#define __NR_epoll_wait                251
+#define __NR_set_tid_address   252
+#define __NR_fadvise64         253
+#define __NR_timer_create      254
+#define __NR_timer_settime     (__NR_timer_create+1)
+#define __NR_timer_gettime     (__NR_timer_create+2)
+#define __NR_timer_getoverrun  (__NR_timer_create+3)
+#define __NR_timer_delete      (__NR_timer_create+4)
+#define __NR_clock_settime     (__NR_timer_create+5)
+#define __NR_clock_gettime     (__NR_timer_create+6)
+#define __NR_clock_getres      (__NR_timer_create+7)
+#define __NR_clock_nanosleep   (__NR_timer_create+8)
+/* Number 263 is reserved for vserver */
+#define __NR_statfs64          265
+#define __NR_fstatfs64         266
+#define __NR_remap_file_pages  267
+/* Number 268 is reserved for new sys_mbind */
+/* Number 269 is reserved for new sys_get_mempolicy */
+/* Number 270 is reserved for new sys_set_mempolicy */
+#define __NR_mq_open           271
+#define __NR_mq_unlink         272
+#define __NR_mq_timedsend      273
+#define __NR_mq_timedreceive   274
+#define __NR_mq_notify         275
+#define __NR_mq_getsetattr     276
+#define __NR_kexec_load                277
+#define __NR_add_key           278
+#define __NR_request_key       279
+#define __NR_keyctl            280
+#define __NR_waitid            281
+#define __NR_ioprio_set                282
+#define __NR_ioprio_get                283
+#define __NR_inotify_init      284
+#define __NR_inotify_add_watch 285
+#define __NR_inotify_rm_watch  286
+/* Number 287 is reserved for new sys_migrate_pages */
+#define __NR_openat            288
+#define __NR_mkdirat           289
+#define __NR_mknodat           290
+#define __NR_fchownat          291
+#define __NR_futimesat         292
+#define __NR_unlinkat          294
+#define __NR_renameat          295
+#define __NR_linkat            296
+#define __NR_symlinkat         297
+#define __NR_readlinkat                298
+#define __NR_fchmodat          299
+#define __NR_faccessat         300
+#define __NR_pselect6          301
+#define __NR_ppoll             302
+#define __NR_unshare           303
+#define __NR_set_robust_list   304
+#define __NR_get_robust_list   305
+#define __NR_splice            306
+#define __NR_sync_file_range   307
+#define __NR_tee               308
+#define __NR_vmsplice          309
+/* Number 310 is reserved for new sys_move_pages */
+#define __NR_getcpu            311
+#define __NR_epoll_pwait       312
+#define __NR_utimes            313
+#define __NR_fallocate         314
+#define __NR_utimensat         315
+#define __NR_signalfd          316
+#define __NR_timerfd           317
+#define __NR_eventfd           318
+#define __NR_timerfd_create    319
+#define __NR_timerfd_settime   320
+#define __NR_timerfd_gettime   321
+#define __NR_signalfd4         322
+#define __NR_eventfd2          323
+#define __NR_inotify_init1     324
+#define __NR_pipe2             325
+#define __NR_dup3              326
+#define __NR_epoll_create1     327
+#define        __NR_preadv             328
+#define        __NR_pwritev            329
+#define __NR_rt_tgsigqueueinfo 330
+#define __NR_perf_event_open   331
+#define __NR_fanotify_init     332
+#define __NR_fanotify_mark     333
+#define __NR_prlimit64         334
+#define __NR_name_to_handle_at 335
+#define __NR_open_by_handle_at 336
+#define __NR_clock_adjtime     337
+#define __NR_syncfs            338
+#define __NR_setns             339
+#define __NR_process_vm_readv  340
+#define __NR_process_vm_writev 341
+#define __NR_s390_runtime_instr 342
+#define __NR_kcmp              343
+#define NR_syscalls 344
+
+/* 
+ * There are some system calls that are not present on 64 bit, some
+ * have a different name although they do the same (e.g. __NR_chown32
+ * is __NR_chown on 64 bit).
+ */
+#ifndef __s390x__
+
+#define __NR_time               13
+#define __NR_lchown             16
+#define __NR_setuid             23
+#define __NR_getuid             24
+#define __NR_stime              25
+#define __NR_setgid             46
+#define __NR_getgid             47
+#define __NR_geteuid            49
+#define __NR_getegid            50
+#define __NR_setreuid           70
+#define __NR_setregid           71
+#define __NR_getrlimit          76
+#define __NR_getgroups          80
+#define __NR_setgroups          81
+#define __NR_fchown             95
+#define __NR_ioperm            101
+#define __NR_setfsuid          138
+#define __NR_setfsgid          139
+#define __NR__llseek           140
+#define __NR__newselect        142
+#define __NR_setresuid         164
+#define __NR_getresuid         165
+#define __NR_setresgid         170
+#define __NR_getresgid         171
+#define __NR_chown             182
+#define __NR_ugetrlimit                191     /* SuS compliant getrlimit */
+#define __NR_mmap2             192
+#define __NR_truncate64                193
+#define __NR_ftruncate64       194
+#define __NR_stat64            195
+#define __NR_lstat64           196
+#define __NR_fstat64           197
+#define __NR_lchown32          198
+#define __NR_getuid32          199
+#define __NR_getgid32          200
+#define __NR_geteuid32         201
+#define __NR_getegid32         202
+#define __NR_setreuid32                203
+#define __NR_setregid32                204
+#define __NR_getgroups32       205
+#define __NR_setgroups32       206
+#define __NR_fchown32          207
+#define __NR_setresuid32       208
+#define __NR_getresuid32       209
+#define __NR_setresgid32       210
+#define __NR_getresgid32       211
+#define __NR_chown32           212
+#define __NR_setuid32          213
+#define __NR_setgid32          214
+#define __NR_setfsuid32                215
+#define __NR_setfsgid32                216
+#define __NR_fcntl64           221
+#define __NR_sendfile64                223
+#define __NR_fadvise64_64      264
+#define __NR_fstatat64         293
+
+#else
+
+#define __NR_select            142
+#define __NR_getrlimit         191     /* SuS compliant getrlimit */
+#define __NR_lchown            198
+#define __NR_getuid            199
+#define __NR_getgid            200
+#define __NR_geteuid           201
+#define __NR_getegid           202
+#define __NR_setreuid                  203
+#define __NR_setregid                  204
+#define __NR_getgroups         205
+#define __NR_setgroups         206
+#define __NR_fchown            207
+#define __NR_setresuid         208
+#define __NR_getresuid         209
+#define __NR_setresgid         210
+#define __NR_getresgid         211
+#define __NR_chown             212
+#define __NR_setuid            213
+#define __NR_setgid            214
+#define __NR_setfsuid                  215
+#define __NR_setfsgid                  216
+#define __NR_newfstatat                293
+
+#endif
+
+#endif /* _UAPI_ASM_S390_UNISTD_H_ */
index 189963c90c6eb09deb498947f057ae6ad3450f12..65cca95843e112d170c40535a95030a087614adb 100644 (file)
@@ -432,32 +432,6 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
        return ret;
 }
 
-/*
- * sys32_execve() executes a new program after the asm stub has set
- * things up for us.  This should basically do what I want it to.
- */
-asmlinkage long sys32_execve(const char __user *name, compat_uptr_t __user *argv,
-                            compat_uptr_t __user *envp)
-{
-       struct pt_regs *regs = task_pt_regs(current);
-       char *filename;
-       long rc;
-
-       filename = getname(name);
-       rc = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               return rc;
-       rc = compat_do_execve(filename, argv, envp, regs);
-       if (rc)
-               goto out;
-       current->thread.fp_regs.fpc=0;
-       asm volatile("sfpc %0,0" : : "d" (0));
-       rc = regs->gprs[2];
-out:
-       putname(filename);
-       return rc;
-}
-
 asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf,
                                size_t count, u32 poshi, u32 poslo)
 {
index 90887bd98cf0b384ce91d2f1bc1ce7187e51498f..d4d0239970ac1f9b3953a38f62fc6a2f6f2b23b7 100644 (file)
@@ -125,8 +125,6 @@ long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
                          compat_sigset_t __user *oset, size_t sigsetsize);
 long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize);
 long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo);
-long sys32_execve(const char __user *name, compat_uptr_t __user *argv,
-                 compat_uptr_t __user *envp);
 long sys32_init_module(void __user *umod, unsigned long len,
                       const char __user *uargs);
 long sys32_delete_module(const char __user *name_user, unsigned int flags);
index 3afba804fe97e9e9eb19ee9f2040cf3466f23361..ad79b846535c4d9345e884341f40481e9d38c492 100644 (file)
@@ -1576,7 +1576,7 @@ ENTRY(sys32_execve_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # compat_uptr_t *
        llgtr   %r4,%r4                 # compat_uptr_t *
-       jg      sys32_execve            # branch to system call
+       jg      compat_sys_execve       # branch to system call
 
 ENTRY(sys_fanotify_init_wrapper)
        llgfr   %r2,%r2                 # unsigned int
index 00d11444506882d9cb771dd0cd2874902c549727..1f0eee9e7daab7f84c0b21a2402b1f69947071b3 100644 (file)
@@ -283,14 +283,6 @@ static noinline __init void setup_facility_list(void)
              ARRAY_SIZE(S390_lowcore.stfle_fac_list));
 }
 
-static noinline __init void setup_hpage(void)
-{
-       if (!test_facility(2) || !test_facility(8))
-               return;
-       S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE;
-       __ctl_set_bit(0, 23);
-}
-
 static __init void detect_mvpg(void)
 {
 #ifndef CONFIG_64BIT
@@ -378,10 +370,14 @@ static __init void detect_diag44(void)
 static __init void detect_machine_facilities(void)
 {
 #ifdef CONFIG_64BIT
+       if (test_facility(8)) {
+               S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT1;
+               __ctl_set_bit(0, 23);
+       }
+       if (test_facility(78))
+               S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT2;
        if (test_facility(3))
                S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE;
-       if (test_facility(8))
-               S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF;
        if (test_facility(27))
                S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
        if (test_facility(40))
@@ -484,7 +480,6 @@ void __init startup_init(void)
        detect_diag9c();
        detect_diag44();
        detect_machine_facilities();
-       setup_hpage();
        setup_topology();
        sclp_facilities_detect();
        detect_memory_layout(memory_chunk);
index 870bad6d56fc4fb7a5a9e308446148a7efec6633..ef46f66bc0d6bdf0caa0dc4ecaae4225f3d3b1ef 100644 (file)
@@ -331,45 +331,38 @@ ENTRY(ret_from_fork)
        l       %r12,__LC_THREAD_INFO
        l       %r13,__LC_SVC_NEW_PSW+4
        tm      __PT_PSW+1(%r11),0x01   # forking a kernel thread ?
-       jo      0f
-       st      %r15,__PT_R15(%r11)     # store stack pointer for new kthread
-0:     l       %r1,BASED(.Lschedule_tail)
+       je      1f
+       l       %r1,BASED(.Lschedule_tail)
        basr    %r14,%r1                # call schedule_tail
        TRACE_IRQS_ON
        ssm     __LC_SVC_NEW_PSW        # reenable interrupts
        j       sysc_tracenogo
 
+1:     # it's a kernel thread
+       st      %r15,__PT_R15(%r11)     # store stack pointer for new kthread
+       l       %r1,BASED(.Lschedule_tail)
+       basr    %r14,%r1                # call schedule_tail
+       TRACE_IRQS_ON
+       ssm     __LC_SVC_NEW_PSW        # reenable interrupts
+       lm      %r9,%r11,__PT_R9(%r11)  # load gprs
+ENTRY(kernel_thread_starter)
+       la      %r2,0(%r10)
+       basr    %r14,%r9
+       la      %r2,0
+       br      %r11                    # do_exit
+
 #
 # kernel_execve function needs to deal with pt_regs that is not
 # at the usual place
 #
-ENTRY(kernel_execve)
-       stm     %r12,%r15,48(%r15)
-       lr      %r14,%r15
-       l       %r13,__LC_SVC_NEW_PSW+4
-       ahi     %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-       st      %r14,__SF_BACKCHAIN(%r15)
-       la      %r12,STACK_FRAME_OVERHEAD(%r15)
-       xc      0(__PT_SIZE,%r12),0(%r12)
-       l       %r1,BASED(.Ldo_execve)
-       lr      %r5,%r12
-       basr    %r14,%r1                # call do_execve
-       ltr     %r2,%r2
-       je      0f
-       ahi     %r15,(STACK_FRAME_OVERHEAD + __PT_SIZE)
-       lm      %r12,%r15,48(%r15)
-       br      %r14
-       # execve succeeded.
-0:     ssm     __LC_PGM_NEW_PSW        # disable I/O and ext. interrupts
-       l       %r15,__LC_KERNEL_STACK  # load ksp
-       ahi     %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-       la      %r11,STACK_FRAME_OVERHEAD(%r15)
-       mvc     0(__PT_SIZE,%r11),0(%r12)       # copy pt_regs
-       l       %r12,__LC_THREAD_INFO
+ENTRY(ret_from_kernel_execve)
+       ssm     __LC_PGM_NEW_PSW        # disable I/O and ext. interrupts
+       lr      %r15,%r2
+       lr      %r11,%r2
+       ahi     %r15,-STACK_FRAME_OVERHEAD
        xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
+       l       %r12,__LC_THREAD_INFO
        ssm     __LC_SVC_NEW_PSW        # reenable interrupts
-       l       %r1,BASED(.Lexecve_tail)
-       basr    %r14,%r1                # call execve_tail
        j       sysc_return
 
 /*
@@ -931,8 +924,6 @@ cleanup_idle_wait:
 .Ldo_signal:           .long   do_signal
 .Ldo_notify_resume:    .long   do_notify_resume
 .Ldo_per_trap:         .long   do_per_trap
-.Ldo_execve:           .long   do_execve
-.Lexecve_tail:         .long   execve_tail
 .Ljump_table:          .long   pgm_check_table
 .Lschedule:            .long   schedule
 #ifdef CONFIG_PREEMPT
index a5f4dc42a5db18843e54972cfdfb28216a30daa2..d0d3f69a73463744edc3d3ec53fdd37dddd0adca 100644 (file)
@@ -58,9 +58,6 @@ long sys_fork(void);
 long sys_clone(unsigned long newsp, unsigned long clone_flags,
               int __user *parent_tidptr, int __user *child_tidptr);
 long sys_vfork(void);
-void execve_tail(void);
-long sys_execve(const char __user *name, const char __user *const __user *argv,
-               const char __user *const __user *envp);
 long sys_sigsuspend(int history0, int history1, old_sigset_t mask);
 long sys_sigaction(int sig, const struct old_sigaction __user *act,
                   struct old_sigaction __user *oact);
index 7549985402f726515e49694708957e710c50e17e..07d8de353984da0fd8c8792348cebba214391c0c 100644 (file)
@@ -295,7 +295,7 @@ sysc_sigpending:
        jno     sysc_return
        lmg     %r2,%r7,__PT_R2(%r11)   # load svc arguments
        lghi    %r8,0                   # svc 0 returns -ENOSYS
-       lh      %r1,__PT_INT_CODE+2(%r11)       # load new svc number
+       llgh    %r1,__PT_INT_CODE+2(%r11)       # load new svc number
        cghi    %r1,NR_syscalls
        jnl     sysc_nr_ok              # invalid svc number -> do svc 0
        slag    %r8,%r1,2
@@ -353,41 +353,31 @@ ENTRY(ret_from_fork)
        la      %r11,STACK_FRAME_OVERHEAD(%r15)
        lg      %r12,__LC_THREAD_INFO
        tm      __PT_PSW+1(%r11),0x01   # forking a kernel thread ?
-       jo      0f
-       stg     %r15,__PT_R15(%r11)     # store stack pointer for new kthread
-0:     brasl   %r14,schedule_tail
+       je      1f
+       brasl   %r14,schedule_tail
        TRACE_IRQS_ON
        ssm     __LC_SVC_NEW_PSW        # reenable interrupts
        j       sysc_tracenogo
-
-#
-# kernel_execve function needs to deal with pt_regs that is not
-# at the usual place
-#
-ENTRY(kernel_execve)
-       stmg    %r12,%r15,96(%r15)
-       lgr     %r14,%r15
-       aghi    %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-       stg     %r14,__SF_BACKCHAIN(%r15)
-       la      %r12,STACK_FRAME_OVERHEAD(%r15)
-       xc      0(__PT_SIZE,%r12),0(%r12)
-       lgr     %r5,%r12
-       brasl   %r14,do_execve
-       ltgfr   %r2,%r2
-       je      0f
-       aghi    %r15,(STACK_FRAME_OVERHEAD + __PT_SIZE)
-       lmg     %r12,%r15,96(%r15)
-       br      %r14
-       # execve succeeded.
-0:     ssm     __LC_PGM_NEW_PSW        # disable I/O and ext. interrupts
-       lg      %r15,__LC_KERNEL_STACK  # load ksp
-       aghi    %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-       la      %r11,STACK_FRAME_OVERHEAD(%r15)
-       mvc     0(__PT_SIZE,%r11),0(%r12)       # copy pt_regs
-       lg      %r12,__LC_THREAD_INFO
+1:     # it's a kernel thread
+       stg     %r15,__PT_R15(%r11)     # store stack pointer for new kthread
+       brasl   %r14,schedule_tail
+       TRACE_IRQS_ON
+       ssm     __LC_SVC_NEW_PSW        # reenable interrupts
+       lmg     %r9,%r11,__PT_R9(%r11)  # load gprs
+ENTRY(kernel_thread_starter)
+       la      %r2,0(%r10)
+       basr    %r14,%r9
+       la      %r2,0
+       br      %r11                    # do_exit
+
+ENTRY(ret_from_kernel_execve)
+       ssm     __LC_PGM_NEW_PSW        # disable I/O and ext. interrupts
+       lgr     %r15,%r2
+       lgr     %r11,%r2
+       aghi    %r15,-STACK_FRAME_OVERHEAD
        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
+       lg      %r12,__LC_THREAD_INFO
        ssm     __LC_SVC_NEW_PSW        # reenable interrupts
-       brasl   %r14,execve_tail
        j       sysc_return
 
 /*
index 805b6686b641dacf24afd15e4e34ee61d42cac8b..984726cbce1607855672dbb6210d7b38b56ea122 100644 (file)
@@ -52,7 +52,7 @@ __HEAD
        .long   0x02000370,0x60000050           # the channel program the PSW
        .long   0x020003c0,0x60000050           # at location 0 is loaded.
        .long   0x02000410,0x60000050           # Initial processing starts
-       .long   0x02000460,0x60000050           # at 0xf0 = iplstart.
+       .long   0x02000460,0x60000050           # at 0x200 = iplstart.
        .long   0x020004b0,0x60000050
        .long   0x02000500,0x60000050
        .long   0x02000550,0x60000050
@@ -62,11 +62,54 @@ __HEAD
        .long   0x02000690,0x60000050
        .long   0x020006e0,0x20000050
 
-       .org    0xf0
+       .org    0x200
+#
+# subroutine to set architecture mode
+#
+.Lsetmode:
+#ifdef CONFIG_64BIT
+       mvi     __LC_AR_MODE_ID,1       # set esame flag
+       slr     %r0,%r0                 # set cpuid to zero
+       lhi     %r1,2                   # mode 2 = esame (dump)
+       sigp    %r1,%r0,0x12            # switch to esame mode
+       bras    %r13,0f
+       .fill   16,4,0x0
+0:     lmh     %r0,%r15,0(%r13)        # clear high-order half of gprs
+       sam31                           # switch to 31 bit addressing mode
+#else
+       mvi     __LC_AR_MODE_ID,0       # set ESA flag (mode 0)
+#endif
+       br      %r14
+
+#
+# subroutine to wait for end I/O
+#
+.Lirqwait:
+#ifdef CONFIG_64BIT
+       mvc     0x1f0(16),.Lnewpsw      # set up IO interrupt psw
+       lpsw    .Lwaitpsw
+.Lioint:
+       br      %r14
+       .align  8
+.Lnewpsw:
+       .quad   0x0000000080000000,.Lioint
+#else
+       mvc     0x78(8),.Lnewpsw        # set up IO interrupt psw
+       lpsw    .Lwaitpsw
+.Lioint:
+       br      %r14
+       .align  8
+.Lnewpsw:
+       .long   0x00080000,0x80000000+.Lioint
+#endif
+.Lwaitpsw:
+       .long   0x020a0000,0x80000000+.Lioint
+
 #
 # subroutine for loading cards from the reader
 #
 .Lloader:
+       la      %r4,0(%r14)
        la      %r3,.Lorb               # r2 = address of orb into r2
        la      %r5,.Lirb               # r4 = address of irb
        la      %r6,.Lccws
@@ -83,9 +126,7 @@ __HEAD
        ssch    0(%r3)                  # load chunk of 1600 bytes
        bnz     .Llderr
 .Lwait4irq:
-       mvc     0x78(8),.Lnewpsw        # set up IO interrupt psw
-       lpsw    .Lwaitpsw
-.Lioint:
+       bas     %r14,.Lirqwait
        c       %r1,0xb8                # compare subchannel number
        bne     .Lwait4irq
        tsch    0(%r5)
@@ -104,7 +145,7 @@ __HEAD
        sr      %r0,%r3                 # #ccws*80-residual=#bytes read
        ar      %r2,%r0
 
-       br      %r14                    # r2 contains the total size
+       br      %r                    # r2 contains the total size
 
 .Lcont:
        ahi     %r2,0x640               # add 0x640 to total size
@@ -128,10 +169,6 @@ __HEAD
 .Lloadp:.long  0,0
        .align  8
 .Lcrash:.long  0x000a0000,0x00000000
-.Lnewpsw:
-       .long   0x00080000,0x80000000+.Lioint
-.Lwaitpsw:
-       .long   0x020a0000,0x80000000+.Lioint
 
        .align  8
 .Lccws: .rept  19
@@ -140,6 +177,7 @@ __HEAD
        .long   0x02200050,0x00000000
 
 iplstart:
+       bas     %r14,.Lsetmode          # Immediately switch to 64 bit mode
        lh      %r1,0xb8                # test if subchannel number
        bct     %r1,.Lnoload            #  is valid
        l       %r1,0xb8                # load ipl subchannel number
@@ -209,8 +247,8 @@ iplstart:
 #
 # reset files in VM reader
 #
-       stidp   __LC_SAVE_AREA_SYNC     # store cpuid
-       tm      __LC_SAVE_AREA_SYNC,0xff# running VM ?
+       stidp   .Lcpuid                 # store cpuid
+       tm      .Lcpuid,0xff            # running VM ?
        bno     .Lnoreset
        la      %r2,.Lreset
        lhi     %r3,26
@@ -222,23 +260,14 @@ iplstart:
        tm      31(%r5),0xff            # bits is set in the schib
        bz      .Lnoreset
 .Lwaitforirq:
-       mvc     0x78(8),.Lrdrnewpsw     # set up IO interrupt psw
-.Lwaitrdrirq:
-       lpsw    .Lrdrwaitpsw
-.Lrdrint:
+       bas     %r14,.Lirqwait          # wait for IO interrupt
        c       %r1,0xb8                # compare subchannel number
-       bne     .Lwaitrdrirq
+       bne     .Lwaitforirq
        la      %r5,.Lirb
        tsch    0(%r5)
 .Lnoreset:
        b       .Lnoload
 
-       .align  8
-.Lrdrnewpsw:
-       .long   0x00080000,0x80000000+.Lrdrint
-.Lrdrwaitpsw:
-       .long   0x020a0000,0x80000000+.Lrdrint
-
 #
 # everything loaded, go for it
 #
@@ -254,6 +283,8 @@ iplstart:
        .byte   0xc8,0xd6,0xd3,0xc4     # "change rdr all keep nohold"
 .L_eof: .long  0xc5d6c600       /* C'EOF' */
 .L_hdr: .long  0xc8c4d900       /* C'HDR' */
+       .align  8
+.Lcpuid:.fill  8,1,0
 
 #
 # SALIPL loader support. Based on a patch by Rob van der Heij.
@@ -263,6 +294,7 @@ iplstart:
        .org    0x800
 ENTRY(start)
        stm     %r0,%r15,0x07b0         # store registers
+       bas     %r14,.Lsetmode          # Immediately switch to 64 bit mode
        basr    %r12,%r0
 .base:
        l       %r11,.parm
@@ -343,6 +375,18 @@ ENTRY(startup)
 ENTRY(startup_kdump)
        j       .Lep_startup_kdump
 .Lep_startup_normal:
+#ifdef CONFIG_64BIT
+       mvi     __LC_AR_MODE_ID,1       # set esame flag
+       slr     %r0,%r0                 # set cpuid to zero
+       lhi     %r1,2                   # mode 2 = esame (dump)
+       sigp    %r1,%r0,0x12            # switch to esame mode
+       bras    %r13,0f
+       .fill   16,4,0x0
+0:     lmh     %r0,%r15,0(%r13)        # clear high-order half of gprs
+       sam31                           # switch to 31 bit addressing mode
+#else
+       mvi     __LC_AR_MODE_ID,0       # set ESA flag (mode 0)
+#endif
        basr    %r13,0                  # get base
 .LPG0:
        xc      0x200(256),0x200        # partially clear lowcore
@@ -410,22 +454,17 @@ ENTRY(startup_kdump)
 #endif
 
 #ifdef CONFIG_64BIT
-       mvi     __LC_AR_MODE_ID,1       # set esame flag
-       slr     %r0,%r0                 # set cpuid to zero
-       lhi     %r1,2                   # mode 2 = esame (dump)
-       sigp    %r1,%r0,0x12            # switch to esame mode
+       /* Continue with 64bit startup code in head64.S */
        sam64                           # switch to 64 bit mode
-       larl    %r13,4f
-       lmh     %r0,%r15,0(%r13)        # clear high-order half
        jg      startup_continue
-4:     .fill   16,4,0x0
 #else
-       mvi     __LC_AR_MODE_ID,0       # set ESA flag (mode 0)
+       /* Continue with 31bit startup code in head31.S */
        l       %r13,4f-.LPG0(%r13)
        b       0(%r13)
        .align  8
 4:     .long   startup_continue
 #endif
+
        .align  8
 5:     .long   0x7fffffff,0xffffffff
 
index a1372ae24ae111229cc532a1f638abfc9f0b75f8..9a99856df1c93ea4d23612d7e2c4670cd82a1a81 100644 (file)
@@ -78,10 +78,7 @@ ENTRY(startup_continue)
 
 ENTRY(_ehead)
 
-#ifdef CONFIG_SHARED_KERNEL
        .org    0x100000 - 0x11000      # head.o ends at 0x11000
-#endif
-
 #
 # startup-code, running in absolute addressing mode
 #
index c108af28bbe890b95ec606300b1129e893071b87..b9e25ae2579c9f04c3d4bb422cab012c943dda58 100644 (file)
@@ -76,10 +76,7 @@ ENTRY(startup_continue)
 
 ENTRY(_ehead)
 
-#ifdef CONFIG_SHARED_KERNEL
        .org    0x100000 - 0x11000      # head.o ends at 0x11000
-#endif
-
 #
 # startup-code, running in absolute addressing mode
 #
index 46412b1d7e1e868243a083faa1a066e17f081c13..4610deafd953e0434f062ad359e3d53edb81426e 100644 (file)
 #define PLT_ENTRY_SIZE 20
 #endif /* CONFIG_64BIT */
 
+#ifdef CONFIG_64BIT
+void *module_alloc(unsigned long size)
+{
+       if (PAGE_ALIGN(size) > MODULES_LEN)
+               return NULL;
+       return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
+                                   GFP_KERNEL, PAGE_KERNEL, -1,
+                                   __builtin_return_address(0));
+}
+#endif
+
 /* Free memory returned from module_alloc */
 void module_free(struct module *mod, void *module_region)
 {
index 5024be27df444b3dedc669f823734404fcb0fe4c..cd31ad457a9bdb7890a0ff7eae840a63f5f0f48f 100644 (file)
@@ -100,35 +100,6 @@ void cpu_idle(void)
 
 extern void __kprobes kernel_thread_starter(void);
 
-asm(
-       ".section .kprobes.text, \"ax\"\n"
-       ".global kernel_thread_starter\n"
-       "kernel_thread_starter:\n"
-       "    la    2,0(10)\n"
-       "    basr  14,9\n"
-       "    la    2,0\n"
-       "    br    11\n"
-       ".previous\n");
-
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-       regs.psw.mask = psw_kernel_bits |
-               PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
-       regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE;
-       regs.gprs[9] = (unsigned long) fn;
-       regs.gprs[10] = (unsigned long) arg;
-       regs.gprs[11] = (unsigned long) do_exit;
-       regs.orig_gpr2 = -1;
-
-       /* Ok, create the new process.. */
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
-                      0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 /*
  * Free current thread data structures etc..
  */
@@ -146,7 +117,7 @@ void release_thread(struct task_struct *dead_task)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
-               unsigned long unused,
+               unsigned long arg,
                struct task_struct *p, struct pt_regs *regs)
 {
        struct thread_info *ti;
@@ -158,20 +129,44 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
 
        frame = container_of(task_pt_regs(p), struct fake_frame, childregs);
        p->thread.ksp = (unsigned long) frame;
-       /* Store access registers to kernel stack of new process. */
-       frame->childregs = *regs;
-       frame->childregs.gprs[2] = 0;   /* child returns 0 on fork. */
-       frame->childregs.gprs[15] = new_stackp;
-       frame->sf.back_chain = 0;
+       /* Save access registers to new thread structure. */
+       save_access_regs(&p->thread.acrs[0]);
+       /* start new process with ar4 pointing to the correct address space */
+       p->thread.mm_segment = get_fs();
+       /* Don't copy debug registers */
+       memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));
+       memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));
+       clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
+       clear_tsk_thread_flag(p, TIF_PER_TRAP);
+       /* Initialize per thread user and system timer values */
+       ti = task_thread_info(p);
+       ti->user_timer = 0;
+       ti->system_timer = 0;
 
+       frame->sf.back_chain = 0;
        /* new return point is ret_from_fork */
        frame->sf.gprs[8] = (unsigned long) ret_from_fork;
-
        /* fake return stack for resume(), don't go back to schedule */
        frame->sf.gprs[9] = (unsigned long) frame;
 
-       /* Save access registers to new thread structure. */
-       save_access_regs(&p->thread.acrs[0]);
+       /* Store access registers to kernel stack of new process. */
+       if (unlikely(!regs)) {
+               /* kernel thread */
+               memset(&frame->childregs, 0, sizeof(struct pt_regs));
+               frame->childregs.psw.mask = psw_kernel_bits | PSW_MASK_DAT |
+                               PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
+               frame->childregs.psw.addr = PSW_ADDR_AMODE |
+                               (unsigned long) kernel_thread_starter;
+               frame->childregs.gprs[9] = new_stackp; /* function */
+               frame->childregs.gprs[10] = arg;
+               frame->childregs.gprs[11] = (unsigned long) do_exit;
+               frame->childregs.orig_gpr2 = -1;
+
+               return 0;
+       }
+       frame->childregs = *regs;
+       frame->childregs.gprs[2] = 0;   /* child returns 0 on fork. */
+       frame->childregs.gprs[15] = new_stackp;
 
        /* Don't copy runtime instrumentation info */
        p->thread.ri_cb = NULL;
@@ -202,17 +197,6 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
                }
        }
 #endif /* CONFIG_64BIT */
-       /* start new process with ar4 pointing to the correct address space */
-       p->thread.mm_segment = get_fs();
-       /* Don't copy debug registers */
-       memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));
-       memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));
-       clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
-       clear_tsk_thread_flag(p, TIF_PER_TRAP);
-       /* Initialize per thread user and system timer values */
-       ti = task_thread_info(p);
-       ti->user_timer = 0;
-       ti->system_timer = 0;
        return 0;
 }
 
@@ -257,31 +241,6 @@ asmlinkage void execve_tail(void)
                asm volatile("sfpc %0,%0" : : "d" (0));
 }
 
-/*
- * sys_execve() executes a new program.
- */
-SYSCALL_DEFINE3(execve, const char __user *, name,
-               const char __user *const __user *, argv,
-               const char __user *const __user *, envp)
-{
-       struct pt_regs *regs = task_pt_regs(current);
-       char *filename;
-       long rc;
-
-       filename = getname(name);
-       rc = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               return rc;
-       rc = do_execve(filename, argv, envp, regs);
-       if (rc)
-               goto out;
-       execve_tail();
-       rc = regs->gprs[2];
-out:
-       putname(filename);
-       return rc;
-}
-
 /*
  * fill in the FPU structure for a core dump.
  */
index afa9fdba200ec855a03c078795142ba8a7344cf2..b1f2be9aaaad7459b339af793e6e95d754543723 100644 (file)
@@ -105,6 +105,11 @@ EXPORT_SYMBOL(VMALLOC_END);
 struct page *vmemmap;
 EXPORT_SYMBOL(vmemmap);
 
+#ifdef CONFIG_64BIT
+unsigned long MODULES_VADDR;
+unsigned long MODULES_END;
+#endif
+
 /* An array with a pointer to the lowcore of every CPU. */
 struct _lowcore *lowcore_ptr[NR_CPUS];
 EXPORT_SYMBOL(lowcore_ptr);
@@ -544,19 +549,23 @@ static void __init setup_memory_end(void)
 
        /* Choose kernel address space layout: 2, 3, or 4 levels. */
 #ifdef CONFIG_64BIT
-       vmalloc_size = VMALLOC_END ?: 128UL << 30;
+       vmalloc_size = VMALLOC_END ?: (128UL << 30) - MODULES_LEN;
        tmp = (memory_end ?: real_memory_size) / PAGE_SIZE;
        tmp = tmp * (sizeof(struct page) + PAGE_SIZE) + vmalloc_size;
        if (tmp <= (1UL << 42))
                vmax = 1UL << 42;       /* 3-level kernel page table */
        else
                vmax = 1UL << 53;       /* 4-level kernel page table */
+       /* module area is at the end of the kernel address space. */
+       MODULES_END = vmax;
+       MODULES_VADDR = MODULES_END - MODULES_LEN;
+       VMALLOC_END = MODULES_VADDR;
 #else
        vmalloc_size = VMALLOC_END ?: 96UL << 20;
        vmax = 1UL << 31;               /* 2-level kernel page table */
-#endif
        /* vmalloc area is at the end of the kernel address space. */
        VMALLOC_END = vmax;
+#endif
        VMALLOC_START = vmax - vmalloc_size;
 
        /* Split remaining virtual space between 1:1 mapping & vmemmap array */
@@ -768,6 +777,40 @@ static void __init reserve_crashkernel(void)
 #endif
 }
 
+static void __init init_storage_keys(unsigned long start, unsigned long end)
+{
+       unsigned long boundary, function, size;
+
+       while (start < end) {
+               if (MACHINE_HAS_EDAT2) {
+                       /* set storage keys for a 2GB frame */
+                       function = 0x22000 | PAGE_DEFAULT_KEY;
+                       size = 1UL << 31;
+                       boundary = (start + size) & ~(size - 1);
+                       if (boundary <= end) {
+                               do {
+                                       start = pfmf(function, start);
+                               } while (start < boundary);
+                               continue;
+                       }
+               }
+               if (MACHINE_HAS_EDAT1) {
+                       /* set storage keys for a 1MB frame */
+                       function = 0x21000 | PAGE_DEFAULT_KEY;
+                       size = 1UL << 20;
+                       boundary = (start + size) & ~(size - 1);
+                       if (boundary <= end) {
+                               do {
+                                       start = pfmf(function, start);
+                               } while (start < boundary);
+                               continue;
+                       }
+               }
+               page_set_storage_key(start, PAGE_DEFAULT_KEY, 0);
+               start += PAGE_SIZE;
+       }
+}
+
 static void __init setup_memory(void)
 {
         unsigned long bootmap_size;
@@ -846,9 +889,7 @@ static void __init setup_memory(void)
                memblock_add_node(PFN_PHYS(start_chunk),
                                  PFN_PHYS(end_chunk - start_chunk), 0);
                pfn = max(start_chunk, start_pfn);
-               for (; pfn < end_chunk; pfn++)
-                       page_set_storage_key(PFN_PHYS(pfn),
-                                            PAGE_DEFAULT_KEY, 0);
+               init_storage_keys(PFN_PHYS(pfn), PFN_PHYS(end_chunk));
        }
 
        psw_set_key(PAGE_DEFAULT_KEY);
index 2db1011b8b1974a3de5b387b7ee2d68ca6fc18b9..7fcd690d42c753bfd027d00b05da12e35cf711cd 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/profile.h>
 #include <linux/timex.h>
 #include <linux/notifier.h>
-#include <linux/clocksource.h>
+#include <linux/timekeeper_internal.h>
 #include <linux/clockchips.h>
 #include <linux/gfp.h>
 #include <linux/kprobes.h>
@@ -219,7 +219,7 @@ struct clocksource * __init clocksource_default_clock(void)
        return &clocksource_tod;
 }
 
-void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
+void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
                        struct clocksource *clock, u32 mult)
 {
        if (clock != &clocksource_tod)
index 0f5536b0c1a1c5368ff9976ff70beb873e92675b..1bea6d1f55ab334b86db2042d84c84e5f01231df 100644 (file)
@@ -7,3 +7,4 @@ obj-y    := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \
 obj-$(CONFIG_CMM) += cmm.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
 obj-$(CONFIG_DEBUG_SET_MODULE_RONX) += pageattr.o
+obj-$(CONFIG_S390_PTDUMP) += dump_pagetables.o
diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c
new file mode 100644 (file)
index 0000000..cbc6668
--- /dev/null
@@ -0,0 +1,226 @@
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/sections.h>
+#include <asm/pgtable.h>
+
+static unsigned long max_addr;
+
+struct addr_marker {
+       unsigned long start_address;
+       const char *name;
+};
+
+enum address_markers_idx {
+       IDENTITY_NR = 0,
+       KERNEL_START_NR,
+       KERNEL_END_NR,
+       VMEMMAP_NR,
+       VMALLOC_NR,
+#ifdef CONFIG_64BIT
+       MODULES_NR,
+#endif
+};
+
+static struct addr_marker address_markers[] = {
+       [IDENTITY_NR]     = {0, "Identity Mapping"},
+       [KERNEL_START_NR] = {(unsigned long)&_stext, "Kernel Image Start"},
+       [KERNEL_END_NR]   = {(unsigned long)&_end, "Kernel Image End"},
+       [VMEMMAP_NR]      = {0, "vmemmap Area"},
+       [VMALLOC_NR]      = {0, "vmalloc Area"},
+#ifdef CONFIG_64BIT
+       [MODULES_NR]      = {0, "Modules Area"},
+#endif
+       { -1, NULL }
+};
+
+struct pg_state {
+       int level;
+       unsigned int current_prot;
+       unsigned long start_address;
+       unsigned long current_address;
+       const struct addr_marker *marker;
+};
+
+static void print_prot(struct seq_file *m, unsigned int pr, int level)
+{
+       static const char * const level_name[] =
+               { "ASCE", "PGD", "PUD", "PMD", "PTE" };
+
+       seq_printf(m, "%s ", level_name[level]);
+       if (pr & _PAGE_INVALID)
+               seq_printf(m, "I\n");
+       else
+               seq_printf(m, "%s\n", pr & _PAGE_RO ? "RO" : "RW");
+}
+
+static void note_page(struct seq_file *m, struct pg_state *st,
+                    unsigned int new_prot, int level)
+{
+       static const char units[] = "KMGTPE";
+       int width = sizeof(unsigned long) * 2;
+       const char *unit = units;
+       unsigned int prot, cur;
+       unsigned long delta;
+
+       /*
+        * If we have a "break" in the series, we need to flush the state
+        * that we have now. "break" is either changing perms, levels or
+        * address space marker.
+        */
+       prot = new_prot;
+       cur = st->current_prot;
+
+       if (!st->level) {
+               /* First entry */
+               st->current_prot = new_prot;
+               st->level = level;
+               st->marker = address_markers;
+               seq_printf(m, "---[ %s ]---\n", st->marker->name);
+       } else if (prot != cur || level != st->level ||
+                  st->current_address >= st->marker[1].start_address) {
+               /* Print the actual finished series */
+               seq_printf(m, "0x%0*lx-0x%0*lx",
+                          width, st->start_address,
+                          width, st->current_address);
+               delta = (st->current_address - st->start_address) >> 10;
+               while (!(delta & 0x3ff) && unit[1]) {
+                       delta >>= 10;
+                       unit++;
+               }
+               seq_printf(m, "%9lu%c ", delta, *unit);
+               print_prot(m, st->current_prot, st->level);
+               if (st->current_address >= st->marker[1].start_address) {
+                       st->marker++;
+                       seq_printf(m, "---[ %s ]---\n", st->marker->name);
+               }
+               st->start_address = st->current_address;
+               st->current_prot = new_prot;
+               st->level = level;
+       }
+}
+
+/*
+ * The actual page table walker functions. In order to keep the implementation
+ * of print_prot() short, we only check and pass _PAGE_INVALID and _PAGE_RO
+ * flags to note_page() if a region, segment or page table entry is invalid or
+ * read-only.
+ * After all it's just a hint that the current level being walked contains an
+ * invalid or read-only entry.
+ */
+static void walk_pte_level(struct seq_file *m, struct pg_state *st,
+                          pmd_t *pmd, unsigned long addr)
+{
+       unsigned int prot;
+       pte_t *pte;
+       int i;
+
+       for (i = 0; i < PTRS_PER_PTE && addr < max_addr; i++) {
+               st->current_address = addr;
+               pte = pte_offset_kernel(pmd, addr);
+               prot = pte_val(*pte) & (_PAGE_RO | _PAGE_INVALID);
+               note_page(m, st, prot, 4);
+               addr += PAGE_SIZE;
+       }
+}
+
+static void walk_pmd_level(struct seq_file *m, struct pg_state *st,
+                          pud_t *pud, unsigned long addr)
+{
+       unsigned int prot;
+       pmd_t *pmd;
+       int i;
+
+       for (i = 0; i < PTRS_PER_PMD && addr < max_addr; i++) {
+               st->current_address = addr;
+               pmd = pmd_offset(pud, addr);
+               if (!pmd_none(*pmd)) {
+                       if (pmd_large(*pmd)) {
+                               prot = pmd_val(*pmd) & _SEGMENT_ENTRY_RO;
+                               note_page(m, st, prot, 3);
+                       } else
+                               walk_pte_level(m, st, pmd, addr);
+               } else
+                       note_page(m, st, _PAGE_INVALID, 3);
+               addr += PMD_SIZE;
+       }
+}
+
+static void walk_pud_level(struct seq_file *m, struct pg_state *st,
+                          pgd_t *pgd, unsigned long addr)
+{
+       pud_t *pud;
+       int i;
+
+       for (i = 0; i < PTRS_PER_PUD && addr < max_addr; i++) {
+               st->current_address = addr;
+               pud = pud_offset(pgd, addr);
+               if (!pud_none(*pud))
+                       walk_pmd_level(m, st, pud, addr);
+               else
+                       note_page(m, st, _PAGE_INVALID, 2);
+               addr += PUD_SIZE;
+       }
+}
+
+static void walk_pgd_level(struct seq_file *m)
+{
+       unsigned long addr = 0;
+       struct pg_state st;
+       pgd_t *pgd;
+       int i;
+
+       memset(&st, 0, sizeof(st));
+       for (i = 0; i < PTRS_PER_PGD && addr < max_addr; i++) {
+               st.current_address = addr;
+               pgd = pgd_offset_k(addr);
+               if (!pgd_none(*pgd))
+                       walk_pud_level(m, &st, pgd, addr);
+               else
+                       note_page(m, &st, _PAGE_INVALID, 1);
+               addr += PGDIR_SIZE;
+       }
+       /* Flush out the last page */
+       st.current_address = max_addr;
+       note_page(m, &st, 0, 0);
+}
+
+static int ptdump_show(struct seq_file *m, void *v)
+{
+       walk_pgd_level(m);
+       return 0;
+}
+
+static int ptdump_open(struct inode *inode, struct file *filp)
+{
+       return single_open(filp, ptdump_show, NULL);
+}
+
+static const struct file_operations ptdump_fops = {
+       .open           = ptdump_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int pt_dump_init(void)
+{
+       /*
+        * Figure out the maximum virtual address being accessible with the
+        * kernel ASCE. We need this to keep the page table walker functions
+        * from accessing non-existent entries.
+        */
+#ifdef CONFIG_32BIT
+       max_addr = 1UL << 31;
+#else
+       max_addr = (S390_lowcore.kernel_asce & _REGION_ENTRY_TYPE_MASK) >> 2;
+       max_addr = 1UL << (max_addr * 11 + 31);
+       address_markers[MODULES_NR].start_address = MODULES_VADDR;
+#endif
+       address_markers[VMEMMAP_NR].start_address = (unsigned long) vmemmap;
+       address_markers[VMALLOC_NR].start_address = VMALLOC_START;
+       debugfs_create_file("kernel_page_tables", 0400, NULL, NULL, &ptdump_fops);
+       return 0;
+}
+device_initcall(pt_dump_init);
index b36537a5f43e33e3a1a6cc9907efcf3920e8d583..00be01c4b4f3fc3ee8242ea1e7b6921bfc6afc2a 100644 (file)
@@ -8,25 +8,38 @@
 #include <asm/cacheflush.h>
 #include <asm/pgtable.h>
 
+static pte_t *walk_page_table(unsigned long addr)
+{
+       pgd_t *pgdp;
+       pud_t *pudp;
+       pmd_t *pmdp;
+       pte_t *ptep;
+
+       pgdp = pgd_offset_k(addr);
+       if (pgd_none(*pgdp))
+               return NULL;
+       pudp = pud_offset(pgdp, addr);
+       if (pud_none(*pudp))
+               return NULL;
+       pmdp = pmd_offset(pudp, addr);
+       if (pmd_none(*pmdp) || pmd_large(*pmdp))
+               return NULL;
+       ptep = pte_offset_kernel(pmdp, addr);
+       if (pte_none(*ptep))
+               return NULL;
+       return ptep;
+}
+
 static void change_page_attr(unsigned long addr, int numpages,
                             pte_t (*set) (pte_t))
 {
        pte_t *ptep, pte;
-       pmd_t *pmdp;
-       pud_t *pudp;
-       pgd_t *pgdp;
        int i;
 
        for (i = 0; i < numpages; i++) {
-               pgdp = pgd_offset(&init_mm, addr);
-               pudp = pud_offset(pgdp, addr);
-               pmdp = pmd_offset(pudp, addr);
-               if (pmd_huge(*pmdp)) {
-                       WARN_ON_ONCE(1);
-                       continue;
-               }
-               ptep = pte_offset_kernel(pmdp, addr);
-
+               ptep = walk_page_table(addr);
+               if (WARN_ON_ONCE(!ptep))
+                       break;
                pte = *ptep;
                pte = set(pte);
                __ptep_ipte(addr, ptep);
@@ -40,21 +53,18 @@ int set_memory_ro(unsigned long addr, int numpages)
        change_page_attr(addr, numpages, pte_wrprotect);
        return 0;
 }
-EXPORT_SYMBOL_GPL(set_memory_ro);
 
 int set_memory_rw(unsigned long addr, int numpages)
 {
        change_page_attr(addr, numpages, pte_mkwrite);
        return 0;
 }
-EXPORT_SYMBOL_GPL(set_memory_rw);
 
 /* not possible */
 int set_memory_nx(unsigned long addr, int numpages)
 {
        return 0;
 }
-EXPORT_SYMBOL_GPL(set_memory_nx);
 
 int set_memory_x(unsigned long addr, int numpages)
 {
index c22abf900c9e8a1e5b1db3bb36b9f77530dd0901..387c7c60b5b8d65a50bec087a54288a1cc913519 100644 (file)
@@ -79,7 +79,8 @@ static pte_t __ref *vmem_pte_alloc(unsigned long address)
  */
 static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
 {
-       unsigned long address;
+       unsigned long end = start + size;
+       unsigned long address = start;
        pgd_t *pg_dir;
        pud_t *pu_dir;
        pmd_t *pm_dir;
@@ -87,7 +88,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
        pte_t  pte;
        int ret = -ENOMEM;
 
-       for (address = start; address < start + size; address += PAGE_SIZE) {
+       while (address < end) {
                pg_dir = pgd_offset_k(address);
                if (pgd_none(*pg_dir)) {
                        pu_dir = vmem_pud_alloc();
@@ -108,12 +109,11 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
                pm_dir = pmd_offset(pu_dir, address);
 
 #if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC)
-               if (MACHINE_HAS_HPAGE && !(address & ~HPAGE_MASK) &&
-                   (address + HPAGE_SIZE <= start + size) &&
-                   (address >= HPAGE_SIZE)) {
+               if (MACHINE_HAS_EDAT1 && pmd_none(*pm_dir) && address &&
+                   !(address & ~PMD_MASK) && (address + PMD_SIZE <= end)) {
                        pte_val(pte) |= _SEGMENT_ENTRY_LARGE;
                        pmd_val(*pm_dir) = pte_val(pte);
-                       address += HPAGE_SIZE - PAGE_SIZE;
+                       address += PMD_SIZE;
                        continue;
                }
 #endif
@@ -126,10 +126,11 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
 
                pt_dir = pte_offset_kernel(pm_dir, address);
                *pt_dir = pte;
+               address += PAGE_SIZE;
        }
        ret = 0;
 out:
-       flush_tlb_kernel_range(start, start + size);
+       flush_tlb_kernel_range(start, end);
        return ret;
 }
 
@@ -139,7 +140,8 @@ out:
  */
 static void vmem_remove_range(unsigned long start, unsigned long size)
 {
-       unsigned long address;
+       unsigned long end = start + size;
+       unsigned long address = start;
        pgd_t *pg_dir;
        pud_t *pu_dir;
        pmd_t *pm_dir;
@@ -147,25 +149,32 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
        pte_t  pte;
 
        pte_val(pte) = _PAGE_TYPE_EMPTY;
-       for (address = start; address < start + size; address += PAGE_SIZE) {
+       while (address < end) {
                pg_dir = pgd_offset_k(address);
+               if (pgd_none(*pg_dir)) {
+                       address += PGDIR_SIZE;
+                       continue;
+               }
                pu_dir = pud_offset(pg_dir, address);
-               if (pud_none(*pu_dir))
+               if (pud_none(*pu_dir)) {
+                       address += PUD_SIZE;
                        continue;
+               }
                pm_dir = pmd_offset(pu_dir, address);
-               if (pmd_none(*pm_dir))
+               if (pmd_none(*pm_dir)) {
+                       address += PMD_SIZE;
                        continue;
-
-               if (pmd_huge(*pm_dir)) {
+               }
+               if (pmd_large(*pm_dir)) {
                        pmd_clear(pm_dir);
-                       address += HPAGE_SIZE - PAGE_SIZE;
+                       address += PMD_SIZE;
                        continue;
                }
-
                pt_dir = pte_offset_kernel(pm_dir, address);
                *pt_dir = pte;
+               address += PAGE_SIZE;
        }
-       flush_tlb_kernel_range(start, start + size);
+       flush_tlb_kernel_range(start, end);
 }
 
 /*
@@ -330,8 +339,8 @@ void __init vmem_map_init(void)
        unsigned long start, end;
        int i;
 
-       ro_start = ((unsigned long)&_stext) & PAGE_MASK;
-       ro_end = PFN_ALIGN((unsigned long)&_eshared);
+       ro_start = PFN_ALIGN((unsigned long)&_stext);
+       ro_end = (unsigned long)&_eshared & PAGE_MASK;
        for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
                if (memory_chunk[i].type == CHUNK_CRASHK ||
                    memory_chunk[i].type == CHUNK_OLDMEM)
index a18006e97f1c31ccbb2b23f1c5e270a28a33d8cb..1425cc034872e5993320e6722f4965bdb34f1189 100644 (file)
@@ -86,16 +86,12 @@ register struct thread_info *__current_thread_info __asm__("r28");
 #define TIF_NEED_RESCHED       2       /* rescheduling necessary */
 #define TIF_NOTIFY_RESUME      5       /* callback before returning to user */
 #define TIF_RESTORE_SIGMASK    9       /* restore signal mask in do_signal() */
-#define TIF_POLLING_NRFLAG     17      /* true if poll_idle() is polling
-                                                TIF_NEED_RESCHED */
 #define TIF_MEMDIE             18      /* is terminating due to OOM killer */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
-#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
-#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 
 #define _TIF_WORK_MASK         (0x0000ffff)
 
index e382c52ca0d90b455d9bee68f7587f4278d36bc8..c268bbf8b41047b2717a5a41a7ed86178a7df24e 100644 (file)
@@ -174,6 +174,7 @@ score_rt_sigreturn(struct pt_regs *regs)
        /* It is more difficult to avoid calling this function than to
           call it and ignore errors.  */
        do_sigaltstack((stack_t __user *)&st, NULL, regs->regs[0]);
+       regs->is_syscall = 0;
 
        __asm__ __volatile__(
                "mv\tr0, %0\n\t"
index 21e8679740667c8d1a2e314252f7f35cad143159..d45cf00a33511aee8c6616fc419569714bc6ebf8 100644 (file)
@@ -92,14 +92,14 @@ asmlinkage long
 score_execve(struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname((char __user*)regs->regs[4]);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                return error;
 
-       error = do_execve(filename,
+       error = do_execve(filename->name,
                          (const char __user *const __user *)regs->regs[5],
                          (const char __user *const __user *)regs->regs[6],
                          regs);
index 7b673ddcd5551cc887cbd393c331056c6c1cc20b..86eadceff097481b4ba5ce3494d60134f50e02ae 100644 (file)
@@ -7,6 +7,7 @@ generic-y += delay.h
 generic-y += div64.h
 generic-y += emergency-restart.h
 generic-y += errno.h
+generic-y += exec.h
 generic-y += fcntl.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
diff --git a/arch/sh/include/asm/exec.h b/arch/sh/include/asm/exec.h
deleted file mode 100644 (file)
index 69486a9..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * 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 bc13b57cdc834210b95aaa70ea603298ed55f468..7d5ac4e4848518118ad07fce5eb34a763bd6d405 100644 (file)
@@ -206,6 +206,9 @@ static inline bool test_and_clear_restore_sigmask(void)
        ti->status &= ~TS_RESTORE_SIGMASK;
        return true;
 }
+
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
index 59521e8a164dae01da367f2f60aef2e0a737551e..ba7345f37bc9d0c6a1e4cc62760ca5e34fe65342 100644 (file)
@@ -298,14 +298,14 @@ asmlinkage int sys_execve(const char __user *ufilename,
 {
        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(ufilename);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename, uargv, uenvp, regs);
+       error = do_execve(filename->name, uargv, uenvp, regs);
        putname(filename);
 out:
        return error;
index 602545b12a8678857c8752407be691a1bd511baa..98a709f0c3c45c1f6ece40d34b79a69cd4de4e2c 100644 (file)
@@ -491,14 +491,14 @@ asmlinkage int sys_execve(const char *ufilename, char **uargv,
                          struct pt_regs *pregs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname((char __user *)ufilename);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename,
+       error = do_execve(filename->name,
                          (const char __user *const __user *)uargv,
                          (const char __user *const __user *)uenvp,
                          pregs);
index d6b7b6154f8764576abac916033326ba1c1e6bd2..2f1f65356c0c39005a605c77f285e614019d387b 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/elf.h>
 #include <linux/personality.h>
 #include <linux/binfmts.h>
-#include <linux/freezer.h>
 #include <linux/io.h>
 #include <linux/tracehook.h>
 #include <asm/ucontext.h>
index 6b5b3dfe886b2d3c15a4b08a4d4f21ab74e90da0..23853814bd174284a3a75c62b88154ac8fb890d3 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/errno.h>
 #include <linux/wait.h>
 #include <linux/personality.h>
-#include <linux/freezer.h>
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/stddef.h>
index f80ff93f6f75a2c05be205167dcb2dd95f65278e..10d54e5e37f5c01d51b68218710fa0b062932b59 100644 (file)
@@ -1,24 +1,9 @@
 # User exported sparc header files
-include include/asm-generic/Kbuild.asm
 
-header-y += apc.h
-header-y += asi.h
-header-y += display7seg.h
-header-y += envctrl.h
-header-y += fbio.h
-header-y += jsflash.h
-header-y += openpromio.h
-header-y += perfctr.h
-header-y += psrcompat.h
-header-y += psr.h
-header-y += pstate.h
-header-y += traps.h
-header-y += uctx.h
-header-y += utrap.h
-header-y += watchdog.h
 
 generic-y += clkdev.h
 generic-y += div64.h
+generic-y += exec.h
 generic-y += local64.h
 generic-y += irq_regs.h
 generic-y += local.h
diff --git a/arch/sparc/include/asm/exec.h b/arch/sparc/include/asm/exec.h
deleted file mode 100644 (file)
index 2e08588..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __SPARC_EXEC_H
-#define __SPARC_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* __SPARC_EXEC_H */
index 0a21da87f7d6b409dff755b0e34434c2917ce278..1d9afe277e9c76d6a3481385758ae402da2e45e6 100644 (file)
 #ifndef __LINUX_FBIO_H
 #define __LINUX_FBIO_H
 
-#include <linux/compiler.h>
-#include <linux/types.h>
+#include <uapi/asm/fbio.h>
 
-/* Constants used for fbio SunOS compatibility */
-/* (C) 1996 Miguel de Icaza */
-
-/* Frame buffer types */
-#define FBTYPE_NOTYPE           -1
-#define FBTYPE_SUN1BW           0   /* mono */
-#define FBTYPE_SUN1COLOR        1 
-#define FBTYPE_SUN2BW           2 
-#define FBTYPE_SUN2COLOR        3 
-#define FBTYPE_SUN2GP           4 
-#define FBTYPE_SUN5COLOR        5 
-#define FBTYPE_SUN3COLOR        6 
-#define FBTYPE_MEMCOLOR         7 
-#define FBTYPE_SUN4COLOR        8 
-#define FBTYPE_NOTSUN1          9 
-#define FBTYPE_NOTSUN2          10
-#define FBTYPE_NOTSUN3          11
-#define FBTYPE_SUNFAST_COLOR    12  /* cg6 */
-#define FBTYPE_SUNROP_COLOR     13
-#define FBTYPE_SUNFB_VIDEO      14
-#define FBTYPE_SUNGIFB          15
-#define FBTYPE_SUNGPLAS         16
-#define FBTYPE_SUNGP3           17
-#define FBTYPE_SUNGT            18
-#define FBTYPE_SUNLEO           19      /* zx Leo card */
-#define FBTYPE_MDICOLOR         20      /* cg14 */
-#define FBTYPE_TCXCOLOR                21      /* SUNW,tcx card */
-
-#define FBTYPE_LASTPLUSONE      21     /* This is not last + 1 in fact... */
-
-/* Does not seem to be listed in the Sun file either */
-#define FBTYPE_CREATOR          22
-#define FBTYPE_PCI_IGA1682     23
-#define FBTYPE_P9100COLOR      24
-
-#define FBTYPE_PCI_GENERIC     1000
-#define FBTYPE_PCI_MACH64      1001
-
-/* fbio ioctls */
-/* Returned by FBIOGTYPE */
-struct  fbtype {
-        int     fb_type;        /* fb type, see above */
-        int     fb_height;      /* pixels */
-        int     fb_width;       /* pixels */
-        int     fb_depth;
-        int     fb_cmsize;      /* color map entries */
-        int     fb_size;        /* fb size in bytes */
-};
-#define FBIOGTYPE _IOR('F', 0, struct fbtype)
-
-struct  fbcmap {
-        int             index;          /* first element (0 origin) */
-        int             count;
-        unsigned char   __user *red;
-        unsigned char   __user *green;
-        unsigned char   __user *blue;
-};
-
-#ifdef __KERNEL__
 #define FBIOPUTCMAP_SPARC _IOW('F', 3, struct fbcmap)
 #define FBIOGETCMAP_SPARC _IOW('F', 4, struct fbcmap)
-#else
-#define FBIOPUTCMAP _IOW('F', 3, struct fbcmap)
-#define FBIOGETCMAP _IOW('F', 4, struct fbcmap)
-#endif
-
-/* # of device specific values */
-#define FB_ATTR_NDEVSPECIFIC    8
-/* # of possible emulations */
-#define FB_ATTR_NEMUTYPES       4
-struct fbsattr {
-        int     flags;
-        int     emu_type;      /* -1 if none */
-        int     dev_specific[FB_ATTR_NDEVSPECIFIC];
-};
-struct fbgattr {
-        int     real_type;     /* real frame buffer type */
-        int     owner;         /* unknown */
-        struct fbtype fbtype;  /* real frame buffer fbtype */
-        struct fbsattr sattr;   
-        int     emu_types[FB_ATTR_NEMUTYPES]; /* supported emulations */
-};
-#define FBIOSATTR  _IOW('F', 5, struct fbgattr) /* Unsupported: */
-#define FBIOGATTR  _IOR('F', 6, struct fbgattr)        /* supported */
-
-#define FBIOSVIDEO _IOW('F', 7, int)
-#define FBIOGVIDEO _IOR('F', 8, int)
-
-struct fbcursor {
-        short set;              /* what to set, choose from the list above */
-        short enable;           /* cursor on/off */
-        struct fbcurpos pos;    /* cursor position */
-        struct fbcurpos hot;    /* cursor hot spot */
-        struct fbcmap cmap;     /* color map info */
-        struct fbcurpos size;   /* cursor bit map size */
-        char __user *image;     /* cursor image bits */
-        char __user *mask;      /* cursor mask bits */
-};
-
-/* set/get cursor attributes/shape */
-#define FBIOSCURSOR     _IOW('F', 24, struct fbcursor)
-#define FBIOGCURSOR     _IOWR('F', 25, struct fbcursor)
-/* set/get cursor position */
-#define FBIOSCURPOS     _IOW('F', 26, struct fbcurpos)
-#define FBIOGCURPOS     _IOW('F', 27, struct fbcurpos)
-/* get max cursor size */
-#define FBIOGCURMAX     _IOR('F', 28, struct fbcurpos)
-
-/* wid manipulation */
-struct fb_wid_alloc {
-#define FB_WID_SHARED_8                0
-#define FB_WID_SHARED_24       1
-#define FB_WID_DBL_8           2
-#define FB_WID_DBL_24          3
-       __u32   wa_type;
-       __s32   wa_index;       /* Set on return */
-       __u32   wa_count;       
-};
-struct fb_wid_item {
-       __u32   wi_type;
-       __s32   wi_index;
-       __u32   wi_attrs;
-       __u32   wi_values[32];
-};
-struct fb_wid_list {
-       __u32   wl_flags;
-       __u32   wl_count;
-       struct fb_wid_item      *wl_list;
-};
-
-#define FBIO_WID_ALLOC _IOWR('F', 30, struct fb_wid_alloc)
-#define FBIO_WID_FREE  _IOW('F', 31, struct fb_wid_alloc)
-#define FBIO_WID_PUT   _IOW('F', 32, struct fb_wid_list)
-#define FBIO_WID_GET   _IOWR('F', 33, struct fb_wid_list)
-
-/* Creator ioctls */
-#define FFB_IOCTL      ('F'<<8)
-#define FFB_SYS_INFO           (FFB_IOCTL|80)
-#define FFB_CLUTREAD           (FFB_IOCTL|81)
-#define FFB_CLUTPOST           (FFB_IOCTL|82)
-#define FFB_SETDIAGMODE                (FFB_IOCTL|83)
-#define FFB_GETMONITORID       (FFB_IOCTL|84)
-#define FFB_GETVIDEOMODE       (FFB_IOCTL|85)
-#define FFB_SETVIDEOMODE       (FFB_IOCTL|86)
-#define FFB_SETSERVER          (FFB_IOCTL|87)
-#define FFB_SETOVCTL           (FFB_IOCTL|88)
-#define FFB_GETOVCTL           (FFB_IOCTL|89)
-#define FFB_GETSAXNUM          (FFB_IOCTL|90)
-#define FFB_FBDEBUG            (FFB_IOCTL|91)
-
-/* Cg14 ioctls */
-#define MDI_IOCTL          ('M'<<8)
-#define MDI_RESET          (MDI_IOCTL|1)
-#define MDI_GET_CFGINFO    (MDI_IOCTL|2)
-#define MDI_SET_PIXELMODE  (MDI_IOCTL|3)
-#    define MDI_32_PIX     32
-#    define MDI_16_PIX     16
-#    define MDI_8_PIX      8
-
-struct mdi_cfginfo {
-       int     mdi_ncluts;     /* Number of implemented CLUTs in this MDI */
-        int     mdi_type;       /* FBTYPE name */
-        int     mdi_height;     /* height */
-        int     mdi_width;      /* width */
-        int     mdi_size;       /* available ram */
-        int     mdi_mode;       /* 8bpp, 16bpp or 32bpp */
-        int     mdi_pixfreq;    /* pixel clock (from PROM) */
-};
-
-/* SparcLinux specific ioctl for the MDI, should be replaced for
- * the SET_XLUT/SET_CLUTn ioctls instead
- */
-#define MDI_CLEAR_XLUT       (MDI_IOCTL|9)
-
-/* leo & ffb ioctls */
-struct fb_clut_alloc {
-       __u32   clutid; /* Set on return */
-       __u32   flag;
-       __u32   index;
-};
-
-struct fb_clut {
-#define FB_CLUT_WAIT   0x00000001      /* Not yet implemented */
-       __u32   flag;
-       __u32   clutid;
-       __u32   offset;
-       __u32   count;
-       char *  red;
-       char *  green;
-       char *  blue;
-};
-
-struct fb_clut32 {
-       __u32   flag;
-       __u32   clutid;
-       __u32   offset;
-       __u32   count;
-       __u32   red;
-       __u32   green;
-       __u32   blue;
-};
-
-#define LEO_CLUTALLOC  _IOWR('L', 53, struct fb_clut_alloc)
-#define LEO_CLUTFREE   _IOW('L', 54, struct fb_clut_alloc)
-#define LEO_CLUTREAD   _IOW('L', 55, struct fb_clut)
-#define LEO_CLUTPOST   _IOW('L', 56, struct fb_clut)
-#define LEO_SETGAMMA   _IOW('L', 68, int) /* Not yet implemented */
-#define LEO_GETGAMMA   _IOR('L', 69, int) /* Not yet implemented */
-
-#ifdef __KERNEL__
 /* Addresses on the fd of a cgsix that are mappable */
 #define CG6_FBC    0x70000000
 #define CG6_TEC    0x70001000
@@ -260,47 +45,6 @@ struct fb_clut32 {
 #define CG14_CLUT3       0x6000  /* Color Look Up Table */
 #define CG14_AUTO       0xf000
 
-#endif /* KERNEL */
-
-/* These are exported to userland for applications to use */
-/* Mappable offsets for the cg14: control registers */
-#define MDI_DIRECT_MAP 0x10000000
-#define MDI_CTLREG_MAP 0x20000000
-#define MDI_CURSOR_MAP 0x30000000
-#define MDI_SHDW_VRT_MAP 0x40000000
-
-/* Mappable offsets for the cg14: frame buffer resolutions */
-/* 32 bits */
-#define MDI_CHUNKY_XBGR_MAP 0x50000000
-#define MDI_CHUNKY_BGR_MAP 0x60000000
-
-/* 16 bits */
-#define MDI_PLANAR_X16_MAP 0x70000000
-#define MDI_PLANAR_C16_MAP 0x80000000
-
-/* 8 bit is done as CG3 MMAP offset */
-/* 32 bits, planar */
-#define MDI_PLANAR_X32_MAP 0x90000000
-#define MDI_PLANAR_B32_MAP 0xa0000000
-#define MDI_PLANAR_G32_MAP 0xb0000000
-#define MDI_PLANAR_R32_MAP 0xc0000000
-
-/* Mappable offsets on leo */
-#define LEO_SS0_MAP            0x00000000
-#define LEO_LC_SS0_USR_MAP     0x00800000
-#define LEO_LD_SS0_MAP         0x00801000
-#define LEO_LX_CURSOR_MAP      0x00802000
-#define LEO_SS1_MAP            0x00803000
-#define LEO_LC_SS1_USR_MAP     0x01003000
-#define LEO_LD_SS1_MAP         0x01004000
-#define LEO_UNK_MAP            0x01005000
-#define LEO_LX_KRN_MAP         0x01006000
-#define LEO_LC_SS0_KRN_MAP     0x01007000
-#define LEO_LC_SS1_KRN_MAP     0x01008000
-#define LEO_LD_GBL_MAP         0x01009000
-#define LEO_UNK2_MAP           0x0100a000
-
-#ifdef __KERNEL__
 struct  fbcmap32 {
        int             index;          /* first element (0 origin) */
        int             count;
@@ -325,6 +69,4 @@ struct fbcursor32 {
 
 #define FBIOSCURSOR32  _IOW('F', 24, struct fbcursor32)
 #define FBIOGCURSOR32  _IOW('F', 25, struct fbcursor32)
-#endif
-
 #endif /* __LINUX_FBIO_H */
index 28d0c8b02cc3c054dae2c23c737afd5ffdf8a9c2..77413b7e3a186e4c146b943a6dddc840a30155d4 100644 (file)
@@ -1,123 +1,8 @@
 #ifndef _ASM_SPARC_IOCTLS_H
 #define _ASM_SPARC_IOCTLS_H
 
-#include <asm/ioctl.h>
+#include <uapi/asm/ioctls.h>
 
-/* Big T */
-#define TCGETA         _IOR('T', 1, struct termio)
-#define TCSETA         _IOW('T', 2, struct termio)
-#define TCSETAW                _IOW('T', 3, struct termio)
-#define TCSETAF                _IOW('T', 4, struct termio)
-#define TCSBRK         _IO('T', 5)
-#define TCXONC         _IO('T', 6)
-#define TCFLSH         _IO('T', 7)
-#define TCGETS         _IOR('T', 8, struct termios)
-#define TCSETS         _IOW('T', 9, struct termios)
-#define TCSETSW                _IOW('T', 10, struct termios)
-#define TCSETSF                _IOW('T', 11, struct termios)
-#define TCGETS2                _IOR('T', 12, struct termios2)
-#define TCSETS2                _IOW('T', 13, struct termios2)
-#define TCSETSW2       _IOW('T', 14, struct termios2)
-#define TCSETSF2       _IOW('T', 15, struct termios2)
-#define TIOCGDEV       _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
-#define TIOCVHANGUP    _IO('T', 0x37)
-
-/* Note that all the ioctls that are not available in Linux have a 
- * double underscore on the front to: a) avoid some programs to
- * think we support some ioctls under Linux (autoconfiguration stuff)
- */
-/* Little t */
-#define TIOCGETD       _IOR('t', 0, int)
-#define TIOCSETD       _IOW('t', 1, int)
-#define __TIOCHPCL        _IO('t', 2) /* SunOS Specific */
-#define __TIOCMODG        _IOR('t', 3, int) /* SunOS Specific */
-#define __TIOCMODS        _IOW('t', 4, int) /* SunOS Specific */
-#define __TIOCGETP        _IOR('t', 8, struct sgttyb) /* SunOS Specific */
-#define __TIOCSETP        _IOW('t', 9, struct sgttyb) /* SunOS Specific */
-#define __TIOCSETN        _IOW('t', 10, struct sgttyb) /* SunOS Specific */
-#define TIOCEXCL       _IO('t', 13)
-#define TIOCNXCL       _IO('t', 14)
-#define __TIOCFLUSH       _IOW('t', 16, int) /* SunOS Specific */
-#define __TIOCSETC        _IOW('t', 17, struct tchars) /* SunOS Specific */
-#define __TIOCGETC        _IOR('t', 18, struct tchars) /* SunOS Specific */
-#define __TIOCTCNTL       _IOW('t', 32, int) /* SunOS Specific */
-#define __TIOCSIGNAL      _IOW('t', 33, int) /* SunOS Specific */
-#define __TIOCSETX        _IOW('t', 34, int) /* SunOS Specific */
-#define __TIOCGETX        _IOR('t', 35, int) /* SunOS Specific */
-#define TIOCCONS       _IO('t', 36)
-#define TIOCGSOFTCAR   _IOR('t', 100, int)
-#define TIOCSSOFTCAR   _IOW('t', 101, int)
-#define __TIOCUCNTL       _IOW('t', 102, int) /* SunOS Specific */
-#define TIOCSWINSZ     _IOW('t', 103, struct winsize)
-#define TIOCGWINSZ     _IOR('t', 104, struct winsize)
-#define __TIOCREMOTE      _IOW('t', 105, int) /* SunOS Specific */
-#define TIOCMGET       _IOR('t', 106, int)
-#define TIOCMBIC       _IOW('t', 107, int)
-#define TIOCMBIS       _IOW('t', 108, int)
-#define TIOCMSET       _IOW('t', 109, int)
-#define TIOCSTART       _IO('t', 110)
-#define TIOCSTOP        _IO('t', 111)
-#define TIOCPKT                _IOW('t', 112, int)
-#define TIOCNOTTY      _IO('t', 113)
-#define TIOCSTI                _IOW('t', 114, char)
-#define TIOCOUTQ       _IOR('t', 115, int)
-#define __TIOCGLTC        _IOR('t', 116, struct ltchars) /* SunOS Specific */
-#define __TIOCSLTC        _IOW('t', 117, struct ltchars) /* SunOS Specific */
-/* 118 is the non-posix setpgrp tty ioctl */
-/* 119 is the non-posix getpgrp tty ioctl */
-#define __TIOCCDTR        _IO('t', 120) /* SunOS Specific */
-#define __TIOCSDTR        _IO('t', 121) /* SunOS Specific */
-#define TIOCCBRK        _IO('t', 122)
-#define TIOCSBRK        _IO('t', 123)
-#define __TIOCLGET        _IOW('t', 124, int) /* SunOS Specific */
-#define __TIOCLSET        _IOW('t', 125, int) /* SunOS Specific */
-#define __TIOCLBIC        _IOW('t', 126, int) /* SunOS Specific */
-#define __TIOCLBIS        _IOW('t', 127, int) /* SunOS Specific */
-#define __TIOCISPACE      _IOR('t', 128, int) /* SunOS Specific */
-#define __TIOCISIZE       _IOR('t', 129, int) /* SunOS Specific */
-#define TIOCSPGRP      _IOW('t', 130, int)
-#define TIOCGPGRP      _IOR('t', 131, int)
-#define TIOCSCTTY      _IO('t', 132)
-#define TIOCGSID       _IOR('t', 133, int)
-/* Get minor device of a pty master's FD -- Solaris equiv is ISPTM */
-#define TIOCGPTN       _IOR('t', 134, unsigned int) /* Get Pty Number */
-#define TIOCSPTLCK     _IOW('t', 135, int) /* Lock/unlock PTY */
-#define TIOCSIG                _IOW('t', 136, int) /* Generate signal on Pty slave */
-
-/* Little f */
-#define FIOCLEX                _IO('f', 1)
-#define FIONCLEX       _IO('f', 2)
-#define FIOASYNC       _IOW('f', 125, int)
-#define FIONBIO                _IOW('f', 126, int)
-#define FIONREAD       _IOR('f', 127, int)
-#define TIOCINQ                FIONREAD
-#define FIOQSIZE       _IOR('f', 128, loff_t)
-
-/* SCARY Rutgers local SunOS kernel hackery, perhaps I will support it
- * someday.  This is completely bogus, I know...
- */
-#define __TCGETSTAT       _IO('T', 200) /* Rutgers specific */
-#define __TCSETSTAT       _IO('T', 201) /* Rutgers specific */
-
-/* Linux specific, no SunOS equivalent. */
-#define TIOCLINUX      0x541C
-#define TIOCGSERIAL    0x541E
-#define TIOCSSERIAL    0x541F
-#define TCSBRKP                0x5425
-#define TIOCSERCONFIG  0x5453
-#define TIOCSERGWILD   0x5454
-#define TIOCSERSWILD   0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-#define TIOCMIWAIT     0x545C /* Wait for change on serial input line(s) */
-#define TIOCGICOUNT    0x545D /* Read serial port inline interrupt counts */
-
-/* Kernel definitions */
-#ifdef __KERNEL__
 #define TIOCGETC __TIOCGETC
 #define TIOCGETP __TIOCGETP
 #define TIOCGLTC __TIOCGLTC
 #define TIOCSETP __TIOCSETP
 #define TIOCSETN __TIOCSETN
 #define TIOCSETC __TIOCSETC
-#endif
-
-/* Used for packet mode */
-#define TIOCPKT_DATA            0
-#define TIOCPKT_FLUSHREAD       1
-#define TIOCPKT_FLUSHWRITE      2
-#define TIOCPKT_STOP            4
-#define TIOCPKT_START           8
-#define TIOCPKT_NOSTOP         16
-#define TIOCPKT_DOSTOP         32
-#define TIOCPKT_IOCTL          64
-
 #endif /* !(_ASM_SPARC_IOCTLS_H) */
index c3029ad6619a31d7984138a3183432b9a7f59a2b..59bb5938d85273fd04a2a5345b22185e108eceb5 100644 (file)
@@ -1,33 +1,10 @@
 #ifndef __SPARC_MMAN_H__
 #define __SPARC_MMAN_H__
 
-#include <asm-generic/mman-common.h>
+#include <uapi/asm/mman.h>
 
-/* SunOS'ified... */
-
-#define MAP_RENAME      MAP_ANONYMOUS   /* In SunOS terminology */
-#define MAP_NORESERVE   0x40            /* don't reserve swap pages */
-#define MAP_INHERIT     0x80            /* SunOS doesn't do this, but... */
-#define MAP_LOCKED      0x100           /* lock the mapping */
-#define _MAP_NEW        0x80000000      /* Binary compatibility is fun... */
-
-#define MAP_GROWSDOWN  0x0200          /* stack-like segment */
-#define MAP_DENYWRITE  0x0800          /* ETXTBSY */
-#define MAP_EXECUTABLE 0x1000          /* mark it as an executable */
-
-#define MCL_CURRENT     0x2000          /* lock all currently mapped pages */
-#define MCL_FUTURE      0x4000          /* lock all additions to address space */
-
-#define MAP_POPULATE   0x8000          /* populate (prefault) pagetables */
-#define MAP_NONBLOCK   0x10000         /* do not block on IO */
-#define MAP_STACK      0x20000         /* give out an address that is best suited for process/thread stacks */
-#define MAP_HUGETLB    0x40000         /* create a huge page mapping */
-
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 #define arch_mmap_check(addr,len,flags)        sparc_mmap_check(addr,len)
 int sparc_mmap_check(unsigned long addr, unsigned long len);
 #endif
-#endif
-
 #endif /* __SPARC_MMAN_H__ */
index cee7ed9c927d9ac433db875646add31e212dc32b..e71eb57945e064eb4602464af190278578a1b53e 100644 (file)
@@ -7,43 +7,11 @@
  *
  * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
  */
-
 #ifndef __LINUX_SPARC_PSR_H
 #define __LINUX_SPARC_PSR_H
 
-/* The Sparc PSR fields are laid out as the following:
- *
- *  ------------------------------------------------------------------------
- *  | impl  | vers  | icc   | resv  | EC | EF | PIL  | S | PS | ET |  CWP  |
- *  | 31-28 | 27-24 | 23-20 | 19-14 | 13 | 12 | 11-8 | 7 | 6  | 5  |  4-0  |
- *  ------------------------------------------------------------------------
- */
-#define PSR_CWP     0x0000001f         /* current window pointer     */
-#define PSR_ET      0x00000020         /* enable traps field         */
-#define PSR_PS      0x00000040         /* previous privilege level   */
-#define PSR_S       0x00000080         /* current privilege level    */
-#define PSR_PIL     0x00000f00         /* processor interrupt level  */
-#define PSR_EF      0x00001000         /* enable floating point      */
-#define PSR_EC      0x00002000         /* enable co-processor        */
-#define PSR_SYSCALL 0x00004000         /* inside of a syscall        */
-#define PSR_LE      0x00008000         /* SuperSparcII little-endian */
-#define PSR_ICC     0x00f00000         /* integer condition codes    */
-#define PSR_C       0x00100000         /* carry bit                  */
-#define PSR_V       0x00200000         /* overflow bit               */
-#define PSR_Z       0x00400000         /* zero bit                   */
-#define PSR_N       0x00800000         /* negative bit               */
-#define PSR_VERS    0x0f000000         /* cpu-version field          */
-#define PSR_IMPL    0xf0000000         /* cpu-implementation field   */
-
-#define PSR_VERS_SHIFT         24
-#define PSR_IMPL_SHIFT         28
-#define PSR_VERS_SHIFTED_MASK  0xf
-#define PSR_IMPL_SHIFTED_MASK  0xf
-
-#define PSR_IMPL_TI            0x4
-#define PSR_IMPL_LEON          0xf
+#include <uapi/asm/psr.h>
 
-#ifdef __KERNEL__
 
 #ifndef __ASSEMBLY__
 /* Get the %psr register. */
@@ -96,6 +64,4 @@ static inline unsigned int get_fsr(void)
 
 #endif /* !(__ASSEMBLY__) */
 
-#endif /* (__KERNEL__) */
-
 #endif /* !(__LINUX_SPARC_PSR_H) */
index fd9c3f21cbf059d8130fd90d44cf67c3d0641942..0c6f6b068289ad4e74f8ea563a6ccd569f6743f5 100644 (file)
 #ifndef __SPARC_PTRACE_H
 #define __SPARC_PTRACE_H
 
-#if defined(__sparc__) && defined(__arch64__)
-/* 64 bit sparc */
-#include <asm/pstate.h>
-
-/* This struct defines the way the registers are stored on the
- * stack during a system call and basically all traps.
- */
-
-/* This magic value must have the low 9 bits clear,
- * as that is where we encode the %tt value, see below.
- */
-#define PT_REGS_MAGIC 0x57ac6c00
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-struct pt_regs {
-       unsigned long u_regs[16]; /* globals and ins */
-       unsigned long tstate;
-       unsigned long tpc;
-       unsigned long tnpc;
-       unsigned int y;
-
-       /* We encode a magic number, PT_REGS_MAGIC, along
-        * with the %tt (trap type) register value at trap
-        * entry time.  The magic number allows us to identify
-        * accurately a trap stack frame in the stack
-        * unwinder, and the %tt value allows us to test
-        * things like "in a system call" etc. for an arbitray
-        * process.
-        *
-        * The PT_REGS_MAGIC is chosen such that it can be
-        * loaded completely using just a sethi instruction.
-        */
-       unsigned int magic;
-};
-
-struct pt_regs32 {
-       unsigned int psr;
-       unsigned int pc;
-       unsigned int npc;
-       unsigned int y;
-       unsigned int u_regs[16]; /* globals and ins */
-};
-
-/* A V9 register window */
-struct reg_window {
-       unsigned long locals[8];
-       unsigned long ins[8];
-};
-
-/* A 32-bit register window. */
-struct reg_window32 {
-       unsigned int locals[8];
-       unsigned int ins[8];
-};
-
-/* A V9 Sparc stack frame */
-struct sparc_stackf {
-       unsigned long locals[8];
-        unsigned long ins[6];
-       struct sparc_stackf *fp;
-       unsigned long callers_pc;
-       char *structptr;
-       unsigned long xargs[6];
-       unsigned long xxargs[1];
-};
-
-/* A 32-bit Sparc stack frame */
-struct sparc_stackf32 {
-       unsigned int locals[8];
-        unsigned int ins[6];
-       unsigned int fp;
-       unsigned int callers_pc;
-       unsigned int structptr;
-       unsigned int xargs[6];
-       unsigned int xxargs[1];
-};
-
-struct sparc_trapf {
-       unsigned long locals[8];
-       unsigned long ins[8];
-       unsigned long _unused;
-       struct pt_regs *regs;
-};
-#endif /* (!__ASSEMBLY__) */
-#else
-/* 32 bit sparc */
-
-#include <asm/psr.h>
-
-/* This struct defines the way the registers are stored on the
- * stack during a system call and basically all traps.
- */
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-struct pt_regs {
-       unsigned long psr;
-       unsigned long pc;
-       unsigned long npc;
-       unsigned long y;
-       unsigned long u_regs[16]; /* globals and ins */
-};
-
-/* A 32-bit register window. */
-struct reg_window32 {
-       unsigned long locals[8];
-       unsigned long ins[8];
-};
-
-/* A Sparc stack frame */
-struct sparc_stackf {
-       unsigned long locals[8];
-        unsigned long ins[6];
-       struct sparc_stackf *fp;
-       unsigned long callers_pc;
-       char *structptr;
-       unsigned long xargs[6];
-       unsigned long xxargs[1];
-};
-#endif /* (!__ASSEMBLY__) */
-
-#endif /* (defined(__sparc__) && defined(__arch64__))*/
-
-#ifndef __ASSEMBLY__
-
-#define TRACEREG_SZ    sizeof(struct pt_regs)
-#define STACKFRAME_SZ  sizeof(struct sparc_stackf)
-
-#define TRACEREG32_SZ  sizeof(struct pt_regs32)
-#define STACKFRAME32_SZ        sizeof(struct sparc_stackf32)
-
-#endif /* (!__ASSEMBLY__) */
-
-#define UREG_G0        0
-#define UREG_G1        1
-#define UREG_G2        2
-#define UREG_G3        3
-#define UREG_G4        4
-#define UREG_G5        5
-#define UREG_G6        6
-#define UREG_G7        7
-#define UREG_I0        8
-#define UREG_I1        9
-#define UREG_I2        10
-#define UREG_I3        11
-#define UREG_I4        12
-#define UREG_I5        13
-#define UREG_I6        14
-#define UREG_I7        15
-#define UREG_FP        UREG_I6
-#define UREG_RETPC     UREG_I7
+#include <uapi/asm/ptrace.h>
 
 #if defined(__sparc__) && defined(__arch64__)
-/* 64 bit sparc */
-
 #ifndef __ASSEMBLY__
 
-#ifdef __KERNEL__
-
 #include <linux/threads.h>
 #include <asm/switch_to.h>
 
@@ -223,24 +65,10 @@ extern unsigned long profile_pc(struct pt_regs *);
 #else
 #define profile_pc(regs) instruction_pointer(regs)
 #endif
-#endif /* (__KERNEL__) */
-
 #else /* __ASSEMBLY__ */
-/* For assembly code. */
-#define TRACEREG_SZ            0xa0
-#define STACKFRAME_SZ          0xc0
-
-#define TRACEREG32_SZ          0x50
-#define STACKFRAME32_SZ                0x60
 #endif /* __ASSEMBLY__ */
-
 #else /* (defined(__sparc__) && defined(__arch64__)) */
-
-/* 32 bit sparc */
-
 #ifndef __ASSEMBLY__
-
-#ifdef __KERNEL__
 #include <asm/switch_to.h>
 
 static inline bool pt_regs_is_syscall(struct pt_regs *regs)
@@ -265,158 +93,10 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
 #define instruction_pointer(regs) ((regs)->pc)
 #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
 unsigned long profile_pc(struct pt_regs *);
-#endif /* (__KERNEL__) */
-
 #else /* (!__ASSEMBLY__) */
-/* For assembly code. */
-#define TRACEREG_SZ       0x50
-#define STACKFRAME_SZ     0x60
 #endif /* (!__ASSEMBLY__) */
-
 #endif /* (defined(__sparc__) && defined(__arch64__)) */
-
-#ifdef __KERNEL__
 #define STACK_BIAS             2047
-#endif
-
-/* These are for pt_regs. */
-#define PT_V9_G0     0x00
-#define PT_V9_G1     0x08
-#define PT_V9_G2     0x10
-#define PT_V9_G3     0x18
-#define PT_V9_G4     0x20
-#define PT_V9_G5     0x28
-#define PT_V9_G6     0x30
-#define PT_V9_G7     0x38
-#define PT_V9_I0     0x40
-#define PT_V9_I1     0x48
-#define PT_V9_I2     0x50
-#define PT_V9_I3     0x58
-#define PT_V9_I4     0x60
-#define PT_V9_I5     0x68
-#define PT_V9_I6     0x70
-#define PT_V9_FP     PT_V9_I6
-#define PT_V9_I7     0x78
-#define PT_V9_TSTATE 0x80
-#define PT_V9_TPC    0x88
-#define PT_V9_TNPC   0x90
-#define PT_V9_Y      0x98
-#define PT_V9_MAGIC  0x9c
-#define PT_TSTATE      PT_V9_TSTATE
-#define PT_TPC         PT_V9_TPC
-#define PT_TNPC                PT_V9_TNPC
-
-/* These for pt_regs32. */
-#define PT_PSR    0x0
-#define PT_PC     0x4
-#define PT_NPC    0x8
-#define PT_Y      0xc
-#define PT_G0     0x10
-#define PT_WIM    PT_G0
-#define PT_G1     0x14
-#define PT_G2     0x18
-#define PT_G3     0x1c
-#define PT_G4     0x20
-#define PT_G5     0x24
-#define PT_G6     0x28
-#define PT_G7     0x2c
-#define PT_I0     0x30
-#define PT_I1     0x34
-#define PT_I2     0x38
-#define PT_I3     0x3c
-#define PT_I4     0x40
-#define PT_I5     0x44
-#define PT_I6     0x48
-#define PT_FP     PT_I6
-#define PT_I7     0x4c
-
-/* Reg_window offsets */
-#define RW_V9_L0     0x00
-#define RW_V9_L1     0x08
-#define RW_V9_L2     0x10
-#define RW_V9_L3     0x18
-#define RW_V9_L4     0x20
-#define RW_V9_L5     0x28
-#define RW_V9_L6     0x30
-#define RW_V9_L7     0x38
-#define RW_V9_I0     0x40
-#define RW_V9_I1     0x48
-#define RW_V9_I2     0x50
-#define RW_V9_I3     0x58
-#define RW_V9_I4     0x60
-#define RW_V9_I5     0x68
-#define RW_V9_I6     0x70
-#define RW_V9_I7     0x78
-
-#define RW_L0     0x00
-#define RW_L1     0x04
-#define RW_L2     0x08
-#define RW_L3     0x0c
-#define RW_L4     0x10
-#define RW_L5     0x14
-#define RW_L6     0x18
-#define RW_L7     0x1c
-#define RW_I0     0x20
-#define RW_I1     0x24
-#define RW_I2     0x28
-#define RW_I3     0x2c
-#define RW_I4     0x30
-#define RW_I5     0x34
-#define RW_I6     0x38
-#define RW_I7     0x3c
-
-/* Stack_frame offsets */
-#define SF_V9_L0     0x00
-#define SF_V9_L1     0x08
-#define SF_V9_L2     0x10
-#define SF_V9_L3     0x18
-#define SF_V9_L4     0x20
-#define SF_V9_L5     0x28
-#define SF_V9_L6     0x30
-#define SF_V9_L7     0x38
-#define SF_V9_I0     0x40
-#define SF_V9_I1     0x48
-#define SF_V9_I2     0x50
-#define SF_V9_I3     0x58
-#define SF_V9_I4     0x60
-#define SF_V9_I5     0x68
-#define SF_V9_FP     0x70
-#define SF_V9_PC     0x78
-#define SF_V9_RETP   0x80
-#define SF_V9_XARG0  0x88
-#define SF_V9_XARG1  0x90
-#define SF_V9_XARG2  0x98
-#define SF_V9_XARG3  0xa0
-#define SF_V9_XARG4  0xa8
-#define SF_V9_XARG5  0xb0
-#define SF_V9_XXARG  0xb8
-
-#define SF_L0     0x00
-#define SF_L1     0x04
-#define SF_L2     0x08
-#define SF_L3     0x0c
-#define SF_L4     0x10
-#define SF_L5     0x14
-#define SF_L6     0x18
-#define SF_L7     0x1c
-#define SF_I0     0x20
-#define SF_I1     0x24
-#define SF_I2     0x28
-#define SF_I3     0x2c
-#define SF_I4     0x30
-#define SF_I5     0x34
-#define SF_FP     0x38
-#define SF_PC     0x3c
-#define SF_RETP   0x40
-#define SF_XARG0  0x44
-#define SF_XARG1  0x48
-#define SF_XARG2  0x4c
-#define SF_XARG3  0x50
-#define SF_XARG4  0x54
-#define SF_XARG5  0x58
-#define SF_XXARG  0x5c
-
-#ifdef __KERNEL__
 
 /* global_reg_snapshot offsets */
 #define GR_SNAP_TSTATE 0x00
@@ -428,29 +108,4 @@ unsigned long profile_pc(struct pt_regs *);
 #define GR_SNAP_THREAD 0x30
 #define GR_SNAP_PAD1   0x38
 
-#endif  /*  __KERNEL__  */
-
-/* Stuff for the ptrace system call */
-#define PTRACE_SPARC_DETACH       11
-#define PTRACE_GETREGS            12
-#define PTRACE_SETREGS            13
-#define PTRACE_GETFPREGS          14
-#define PTRACE_SETFPREGS          15
-#define PTRACE_READDATA           16
-#define PTRACE_WRITEDATA          17
-#define PTRACE_READTEXT           18
-#define PTRACE_WRITETEXT          19
-#define PTRACE_GETFPAREGS         20
-#define PTRACE_SETFPAREGS         21
-
-/* There are for debugging 64-bit processes, either from a 32 or 64 bit
- * parent.  Thus their complements are for debugging 32-bit processes only.
- */
-
-#define PTRACE_GETREGS64         22
-#define PTRACE_SETREGS64         23
-/* PTRACE_SYSCALL is 24 */
-#define PTRACE_GETFPREGS64       25
-#define PTRACE_SETFPREGS64       26
-
 #endif /* !(__SPARC_PTRACE_H) */
index 8a83699a55072848d7f72854c69a5d7144362223..5e35e051731887c3e284b2b7e92c254365ac36be 100644 (file)
@@ -1,17 +1,11 @@
 /*
  *     Just a place holder. 
  */
-
 #ifndef _SPARC_SETUP_H
 #define _SPARC_SETUP_H
 
-#if defined(__sparc__) && defined(__arch64__)
-# define COMMAND_LINE_SIZE 2048
-#else
-# define COMMAND_LINE_SIZE 256
-#endif
+#include <uapi/asm/setup.h>
 
-#ifdef __KERNEL__
 
 extern char reboot_command[];
 
@@ -34,6 +28,4 @@ extern void sun_do_break(void);
 extern int stop_a_enabled;
 extern int scons_pwroff;
 
-#endif /* __KERNEL__ */
-
 #endif /* _SPARC_SETUP_H */
index 69914d748130a9b151d4f4c8f17a496fe2d5d39e..fc2df1e892cbb196d7c62fd3695d65837d3a97cc 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef __SPARC_SIGCONTEXT_H
 #define __SPARC_SIGCONTEXT_H
 
-#ifdef __KERNEL__
 #include <asm/ptrace.h>
+#include <uapi/asm/sigcontext.h>
 
 #ifndef __ASSEMBLY__
 
@@ -105,6 +105,4 @@ typedef struct {
 
 #endif /* !(__ASSEMBLY__) */
 
-#endif /* (__KERNEL__) */
-
 #endif /* !(__SPARC_SIGCONTEXT_H) */
index dbc182c438b494052d2f2aa51a9b001199472f10..48c34c19f81017c1f930c788efbea10246016c6b 100644 (file)
@@ -1,19 +1,8 @@
 #ifndef __SPARC_SIGINFO_H
 #define __SPARC_SIGINFO_H
 
-#if defined(__sparc__) && defined(__arch64__)
+#include <uapi/asm/siginfo.h>
 
-#define __ARCH_SI_PREAMBLE_SIZE        (4 * sizeof(int))
-#define __ARCH_SI_BAND_T int
-
-#endif /* defined(__sparc__) && defined(__arch64__) */
-
-
-#define __ARCH_SI_TRAPNO
-
-#include <asm-generic/siginfo.h>
-
-#ifdef __KERNEL__
 
 #ifdef CONFIG_COMPAT
 
@@ -21,14 +10,4 @@ struct compat_siginfo;
 
 #endif /* CONFIG_COMPAT */
 
-#endif /* __KERNEL__ */
-
-#define SI_NOINFO      32767           /* no information in siginfo_t */
-
-/*
- * SIGEMT si_codes
- */
-#define EMT_TAGOVF     (__SI_FAULT|1)  /* tag overflow */
-#define NSIGEMT                1
-
 #endif /* !(__SPARC_SIGINFO_H) */
index aa42fe30d5b96f0c3f1029274932d7bbbbd3da4d..d243c2ae02d297d40303b237f9c9e1d53842adfd 100644 (file)
 #ifndef __SPARC_SIGNAL_H
 #define __SPARC_SIGNAL_H
 
-#include <asm/sigcontext.h>
-#include <linux/compiler.h>
-
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 #include <linux/personality.h>
 #include <linux/types.h>
 #endif
-#endif
-
-/* On the Sparc the signal handlers get passed a 'sub-signal' code
- * for certain signal types, which we document here.
- */
-#define SIGHUP          1
-#define SIGINT          2
-#define SIGQUIT                 3
-#define SIGILL          4
-#define    SUBSIG_STACK       0
-#define    SUBSIG_ILLINST     2
-#define    SUBSIG_PRIVINST    3
-#define    SUBSIG_BADTRAP(t)  (0x80 + (t))
-
-#define SIGTRAP                 5
-#define SIGABRT                 6
-#define SIGIOT          6
-
-#define SIGEMT           7
-#define    SUBSIG_TAG    10
-
-#define SIGFPE          8
-#define    SUBSIG_FPDISABLED     0x400
-#define    SUBSIG_FPERROR        0x404
-#define    SUBSIG_FPINTOVFL      0x001
-#define    SUBSIG_FPSTSIG        0x002
-#define    SUBSIG_IDIVZERO       0x014
-#define    SUBSIG_FPINEXACT      0x0c4
-#define    SUBSIG_FPDIVZERO      0x0c8
-#define    SUBSIG_FPUNFLOW       0x0cc
-#define    SUBSIG_FPOPERROR      0x0d0
-#define    SUBSIG_FPOVFLOW       0x0d4
-
-#define SIGKILL                 9
-#define SIGBUS          10
-#define    SUBSIG_BUSTIMEOUT    1
-#define    SUBSIG_ALIGNMENT     2
-#define    SUBSIG_MISCERROR     5
-
-#define SIGSEGV                11
-#define    SUBSIG_NOMAPPING     3
-#define    SUBSIG_PROTECTION    4
-#define    SUBSIG_SEGERROR      5
-
-#define SIGSYS         12
-
-#define SIGPIPE                13
-#define SIGALRM                14
-#define SIGTERM                15
-#define SIGURG          16
-
-/* SunOS values which deviate from the Linux/i386 ones */
-#define SIGSTOP                17
-#define SIGTSTP                18
-#define SIGCONT                19
-#define SIGCHLD                20
-#define SIGTTIN                21
-#define SIGTTOU                22
-#define SIGIO          23
-#define SIGPOLL                SIGIO   /* SysV name for SIGIO */
-#define SIGXCPU                24
-#define SIGXFSZ                25
-#define SIGVTALRM      26
-#define SIGPROF                27
-#define SIGWINCH       28
-#define SIGLOST                29
-#define SIGPWR         SIGLOST
-#define SIGUSR1                30
-#define SIGUSR2                31
-
-/* Most things should be clean enough to redefine this at will, if care
-   is taken to make libc match.  */
-
-#define __OLD_NSIG     32
-#define __NEW_NSIG      64
-#ifdef __arch64__
-#define _NSIG_BPW       64
-#else
-#define _NSIG_BPW       32
-#endif
-#define _NSIG_WORDS     (__NEW_NSIG / _NSIG_BPW)
-
-#define SIGRTMIN       32
-#define SIGRTMAX       __NEW_NSIG
-
-#if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__)
-#define _NSIG                  __NEW_NSIG
-#define __new_sigset_t         sigset_t
-#define __new_sigaction                sigaction
-#define __new_sigaction32      sigaction32
-#define __old_sigset_t         old_sigset_t
-#define __old_sigaction                old_sigaction
-#define __old_sigaction32      old_sigaction32
-#else
-#define _NSIG                  __OLD_NSIG
-#define NSIG                   _NSIG
-#define __old_sigset_t         sigset_t
-#define __old_sigaction                sigaction
-#define __old_sigaction32      sigaction32
-#endif
+#include <uapi/asm/signal.h>
 
 #ifndef __ASSEMBLY__
-
-typedef unsigned long __old_sigset_t;            /* at least 32 bits */
-
-typedef struct {
-       unsigned long sig[_NSIG_WORDS];
-} __new_sigset_t;
-
-/* A SunOS sigstack */
-struct sigstack {
-       /* XXX 32-bit pointers pinhead XXX */
-       char *the_stack;
-       int   cur_status;
-};
-
-/* Sigvec flags */
-#define _SV_SSTACK    1u    /* This signal handler should use sig-stack */
-#define _SV_INTR      2u    /* Sig return should not restart system call */
-#define _SV_RESET     4u    /* Set handler to SIG_DFL upon taken signal */
-#define _SV_IGNCHILD  8u    /* Do not send SIGCHLD */
-
-/*
- * sa_flags values: SA_STACK is not currently supported, but will allow the
- * usage of signal stacks by using the (now obsolete) sa_restorer field in
- * the sigaction structure as a stack pointer. This is now possible due to
- * the changes in signal handling. LBT 010493.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- */
-#define SA_NOCLDSTOP   _SV_IGNCHILD
-#define SA_STACK       _SV_SSTACK
-#define SA_ONSTACK     _SV_SSTACK
-#define SA_RESTART     _SV_INTR
-#define SA_ONESHOT     _SV_RESET
-#define SA_NODEFER     0x20u
-#define SA_NOCLDWAIT    0x100u
-#define SA_SIGINFO      0x200u
-
-#define SA_NOMASK      SA_NODEFER
-
-#define SIG_BLOCK          0x01        /* for blocking signals */
-#define SIG_UNBLOCK        0x02        /* for unblocking signals */
-#define SIG_SETMASK        0x04        /* for setting the signal mask */
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
-#define MINSIGSTKSZ    4096
-#define SIGSTKSZ       16384
-
-#ifdef __KERNEL__
 /*
  * DJHR
  * SA_STATIC_ALLOC is used for the sparc32 system to indicate that this
@@ -175,31 +20,6 @@ struct sigstack {
  *
  */
 #define SA_STATIC_ALLOC         0x8000
-#endif
-
-#include <asm-generic/signal-defs.h>
-
-struct __new_sigaction {
-       __sighandler_t          sa_handler;
-       unsigned long           sa_flags;
-       __sigrestore_t          sa_restorer;  /* not used by Linux/SPARC yet */
-       __new_sigset_t          sa_mask;
-};
-
-struct __old_sigaction {
-       __sighandler_t          sa_handler;
-       __old_sigset_t          sa_mask;
-       unsigned long           sa_flags;
-       void                    (*sa_restorer)(void);  /* not used by Linux/SPARC yet */
-};
-
-typedef struct sigaltstack {
-       void                    __user *ss_sp;
-       int                     ss_flags;
-       size_t                  ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
 
 struct k_sigaction {
        struct                  __new_sigaction sa;
@@ -208,8 +28,5 @@ struct k_sigaction {
 
 #define ptrace_signal_deliver(regs, cookie) do { } while (0)
 
-#endif /* !(__KERNEL__) */
-
 #endif /* !(__ASSEMBLY__) */
-
 #endif /* !(__SPARC_SIGNAL_H) */
index 23b10ff08df2c0196b4fe1d9717faff30ddbb0d5..948067065ac5f96c19b1e9977ece8b3bac8851eb 100644 (file)
@@ -1,266 +1,8 @@
 #ifndef _SPARC_TERMBITS_H
 #define _SPARC_TERMBITS_H
 
-#include <linux/posix_types.h>
+#include <uapi/asm/termbits.h>
 
-typedef unsigned char   cc_t;
-typedef unsigned int    speed_t;
-
-#if defined(__sparc__) && defined(__arch64__)
-typedef unsigned int    tcflag_t;
-#else
-typedef unsigned long   tcflag_t;
-#endif
-
-#define NCC 8
-struct termio {
-       unsigned short c_iflag;         /* input mode flags */
-       unsigned short c_oflag;         /* output mode flags */
-       unsigned short c_cflag;         /* control mode flags */
-       unsigned short c_lflag;         /* local mode flags */
-       unsigned char c_line;           /* line discipline */
-       unsigned char c_cc[NCC];        /* control characters */
-};
-
-#define NCCS 17
-struct termios {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-#ifndef __KERNEL__
-       cc_t c_cc[NCCS];                /* control characters */
-#else
-       cc_t c_cc[NCCS+2];      /* kernel needs 2 more to hold vmin/vtime */
-#define SIZEOF_USER_TERMIOS sizeof (struct termios) - (2*sizeof (cc_t))
-#endif
-};
-
-struct termios2 {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS+2];              /* control characters */
-       speed_t c_ispeed;               /* input speed */
-       speed_t c_ospeed;               /* output speed */
-};
-
-struct ktermios {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS+2];              /* control characters */
-       speed_t c_ispeed;               /* input speed */
-       speed_t c_ospeed;               /* output speed */
-};
-
-/* c_cc characters */
-#define VINTR    0
-#define VQUIT    1
-#define VERASE   2
-#define VKILL    3
-#define VEOF     4
-#define VEOL     5
-#define VEOL2    6
-#define VSWTC    7
-#define VSTART   8
-#define VSTOP    9
-
-
-
-#define VSUSP    10
-#define VDSUSP   11  /* SunOS POSIX nicety I do believe... */
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE  14
-#define VLNEXT   15
-
-/* Kernel keeps vmin/vtime separated, user apps assume vmin/vtime is
- * shared with eof/eol
- */
-#ifdef __KERNEL__
 #define VMIN     16
 #define VTIME    17
-#else
-#define VMIN     VEOF
-#define VTIME    VEOL
-#endif
-
-/* c_iflag bits */
-#define IGNBRK 0x00000001
-#define BRKINT 0x00000002
-#define IGNPAR 0x00000004
-#define PARMRK 0x00000008
-#define INPCK  0x00000010
-#define ISTRIP 0x00000020
-#define INLCR  0x00000040
-#define IGNCR  0x00000080
-#define ICRNL  0x00000100
-#define IUCLC  0x00000200
-#define IXON   0x00000400
-#define IXANY  0x00000800
-#define IXOFF  0x00001000
-#define IMAXBEL        0x00002000
-#define IUTF8   0x00004000
-
-/* c_oflag bits */
-#define OPOST  0x00000001
-#define OLCUC  0x00000002
-#define ONLCR  0x00000004
-#define OCRNL  0x00000008
-#define ONOCR  0x00000010
-#define ONLRET 0x00000020
-#define OFILL  0x00000040
-#define OFDEL  0x00000080
-#define NLDLY  0x00000100
-#define   NL0  0x00000000
-#define   NL1  0x00000100
-#define CRDLY  0x00000600
-#define   CR0  0x00000000
-#define   CR1  0x00000200
-#define   CR2  0x00000400
-#define   CR3  0x00000600
-#define TABDLY 0x00001800
-#define   TAB0 0x00000000
-#define   TAB1 0x00000800
-#define   TAB2 0x00001000
-#define   TAB3 0x00001800
-#define   XTABS        0x00001800
-#define BSDLY  0x00002000
-#define   BS0  0x00000000
-#define   BS1  0x00002000
-#define VTDLY  0x00004000
-#define   VT0  0x00000000
-#define   VT1  0x00004000
-#define FFDLY  0x00008000
-#define   FF0  0x00000000
-#define   FF1  0x00008000
-#define PAGEOUT 0x00010000  /* SUNOS specific */
-#define WRAP    0x00020000  /* SUNOS specific */
-
-/* c_cflag bit meaning */
-#define CBAUD    0x0000100f
-#define  B0      0x00000000   /* hang up */
-#define  B50     0x00000001
-#define  B75     0x00000002
-#define  B110    0x00000003
-#define  B134    0x00000004
-#define  B150    0x00000005
-#define  B200    0x00000006
-#define  B300    0x00000007
-#define  B600    0x00000008
-#define  B1200   0x00000009
-#define  B1800   0x0000000a
-#define  B2400   0x0000000b
-#define  B4800   0x0000000c
-#define  B9600   0x0000000d
-#define  B19200          0x0000000e
-#define  B38400          0x0000000f
-#define EXTA      B19200
-#define EXTB      B38400
-#define  CSIZE    0x00000030
-#define   CS5    0x00000000
-#define   CS6    0x00000010
-#define   CS7    0x00000020
-#define   CS8    0x00000030
-#define CSTOPB   0x00000040
-#define CREAD    0x00000080
-#define PARENB   0x00000100
-#define PARODD   0x00000200
-#define HUPCL    0x00000400
-#define CLOCAL   0x00000800
-#define CBAUDEX   0x00001000
-/* We'll never see these speeds with the Zilogs, but for completeness... */
-#define  BOTHER   0x00001000
-#define  B57600   0x00001001
-#define  B115200  0x00001002
-#define  B230400  0x00001003
-#define  B460800  0x00001004
-/* This is what we can do with the Zilogs. */
-#define  B76800   0x00001005
-/* This is what we can do with the SAB82532. */
-#define  B153600  0x00001006
-#define  B307200  0x00001007
-#define  B614400  0x00001008
-#define  B921600  0x00001009
-/* And these are the rest... */
-#define  B500000  0x0000100a
-#define  B576000  0x0000100b
-#define B1000000  0x0000100c
-#define B1152000  0x0000100d
-#define B1500000  0x0000100e
-#define B2000000  0x0000100f
-/* These have totally bogus values and nobody uses them
-   so far. Later on we'd have to use say 0x10000x and
-   adjust CBAUD constant and drivers accordingly.
-#define B2500000  0x00001010
-#define B3000000  0x00001011
-#define B3500000  0x00001012
-#define B4000000  0x00001013  */
-#define CIBAUD   0x100f0000  /* input baud rate (not used) */
-#define CMSPAR   0x40000000  /* mark or space (stick) parity */
-#define CRTSCTS          0x80000000  /* flow control */
-
-#define IBSHIFT          16            /* Shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-#define ISIG   0x00000001
-#define ICANON 0x00000002
-#define XCASE  0x00000004
-#define ECHO   0x00000008
-#define ECHOE  0x00000010
-#define ECHOK  0x00000020
-#define ECHONL 0x00000040
-#define NOFLSH 0x00000080
-#define TOSTOP 0x00000100
-#define ECHOCTL        0x00000200
-#define ECHOPRT        0x00000400
-#define ECHOKE 0x00000800
-#define DEFECHO 0x00001000  /* SUNOS thing, what is it? */
-#define FLUSHO 0x00002000
-#define PENDIN 0x00004000
-#define IEXTEN 0x00008000
-#define EXTPROC        0x00010000
-
-/* modem lines */
-#define TIOCM_LE       0x001
-#define TIOCM_DTR      0x002
-#define TIOCM_RTS      0x004
-#define TIOCM_ST       0x008
-#define TIOCM_SR       0x010
-#define TIOCM_CTS      0x020
-#define TIOCM_CAR      0x040
-#define TIOCM_RNG      0x080
-#define TIOCM_DSR      0x100
-#define TIOCM_CD       TIOCM_CAR
-#define TIOCM_RI       TIOCM_RNG
-#define TIOCM_OUT1     0x2000
-#define TIOCM_OUT2     0x4000
-#define TIOCM_LOOP     0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
-
-
-/* tcflow() and TCXONC use these */
-#define        TCOOFF          0
-#define        TCOON           1
-#define        TCIOFF          2
-#define        TCION           3
-
-/* tcflush() and TCFLSH use these */
-#define        TCIFLUSH        0
-#define        TCOFLUSH        1
-#define        TCIOFLUSH       2
-
-/* tcsetattr uses these */
-#define        TCSANOW         0
-#define        TCSADRAIN       1
-#define        TCSAFLUSH       2
-
 #endif /* !(_SPARC_TERMBITS_H) */
index e2f46705a21032dc36ae35b59c0c5f5893e1d958..0c2414ddd52c336e244789283b72067cc06ed365 100644 (file)
@@ -1,45 +1,8 @@
 #ifndef _SPARC_TERMIOS_H
 #define _SPARC_TERMIOS_H
 
-#include <asm/ioctls.h>
-#include <asm/termbits.h>
+#include <uapi/asm/termios.h>
 
-#if defined(__KERNEL__) || defined(__DEFINE_BSD_TERMIOS)
-struct sgttyb {
-       char    sg_ispeed;
-       char    sg_ospeed;
-       char    sg_erase;
-       char    sg_kill;
-       short   sg_flags;
-};
-
-struct tchars {
-       char    t_intrc;
-       char    t_quitc;
-       char    t_startc;
-       char    t_stopc;
-       char    t_eofc;
-       char    t_brkc;
-};
-
-struct ltchars {
-       char    t_suspc;
-       char    t_dsuspc;
-       char    t_rprntc;
-       char    t_flushc;
-       char    t_werasc;
-       char    t_lnextc;
-};
-#endif /* __KERNEL__ */
-
-struct winsize {
-       unsigned short ws_row;
-       unsigned short ws_col;
-       unsigned short ws_xpixel;
-       unsigned short ws_ypixel;
-};
-
-#ifdef __KERNEL__
 
 /*
  * c_cc characters in the termio structure.  Oh, how I love being
@@ -180,6 +143,4 @@ struct winsize {
        err; \
 })
 
-#endif /* __KERNEL__ */
-
 #endif /* _SPARC_TERMIOS_H */
index e6cd224506a9355168ebea0c5ed0be8c3b625120..25849ae3e900305e86a138fabebb6b2484a1a07f 100644 (file)
@@ -126,13 +126,14 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
-#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU           (1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 
 #define _TIF_DO_NOTIFY_RESUME_MASK     (_TIF_NOTIFY_RESUME | \
                                         _TIF_SIGPENDING)
 
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_THREAD_INFO_H */
index cfa8c38fb9c8511d51cfbe17e3d8792584d8b241..4e227663108181b45700b0cb879d5043ee1da64b 100644 (file)
@@ -256,6 +256,9 @@ static inline bool test_and_clear_restore_sigmask(void)
        ti->status &= ~TS_RESTORE_SIGMASK;
        return true;
 }
+
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
index 3aa62dde343fcd7129de54ae95248ad253bf8a4e..51abcb1f9b3bb7fd6948d2ee8fd6cbc82a7c0cbb 100644 (file)
@@ -3,14 +3,12 @@
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
-
 #ifndef _SPARC_TRAPS_H
 #define _SPARC_TRAPS_H
 
-#define NUM_SPARC_TRAPS  255
+#include <uapi/asm/traps.h>
 
 #ifndef __ASSEMBLY__
-#ifdef __KERNEL__
 /* This is for V8 compliant Sparc CPUS */
 struct tt_entry {
        unsigned long inst_one;
@@ -22,112 +20,5 @@ struct tt_entry {
 /* We set this to _start in system setup. */
 extern struct tt_entry *sparc_ttable;
 
-#endif /* (__KERNEL__) */
 #endif /* !(__ASSEMBLY__) */
-
-/* For patching the trap table at boot time, we need to know how to
- * form various common Sparc instructions.  Thus these macros...
- */
-
-#define SPARC_MOV_CONST_L3(const) (0xa6102000 | (const&0xfff))
-
-/* The following assumes that the branch lies before the place we
- * are branching to.  This is the case for a trap vector...
- * You have been warned.
- */
-#define SPARC_BRANCH(dest_addr, inst_addr) \
-          (0x10800000 | (((dest_addr-inst_addr)>>2)&0x3fffff))
-
-#define SPARC_RD_PSR_L0  (0xa1480000)
-#define SPARC_RD_WIM_L3  (0xa7500000)
-#define SPARC_NOP (0x01000000)
-
-/* Various interesting trap levels. */
-/* First, hardware traps. */
-#define SP_TRAP_TFLT    0x1          /* Text fault */
-#define SP_TRAP_II      0x2          /* Illegal Instruction */
-#define SP_TRAP_PI      0x3          /* Privileged Instruction */
-#define SP_TRAP_FPD     0x4          /* Floating Point Disabled */
-#define SP_TRAP_WOVF    0x5          /* Window Overflow */
-#define SP_TRAP_WUNF    0x6          /* Window Underflow */
-#define SP_TRAP_MNA     0x7          /* Memory Address Unaligned */
-#define SP_TRAP_FPE     0x8          /* Floating Point Exception */
-#define SP_TRAP_DFLT    0x9          /* Data Fault */
-#define SP_TRAP_TOF     0xa          /* Tag Overflow */
-#define SP_TRAP_WDOG    0xb          /* Watchpoint Detected */
-#define SP_TRAP_IRQ1    0x11         /* IRQ level 1 */
-#define SP_TRAP_IRQ2    0x12         /* IRQ level 2 */
-#define SP_TRAP_IRQ3    0x13         /* IRQ level 3 */
-#define SP_TRAP_IRQ4    0x14         /* IRQ level 4 */
-#define SP_TRAP_IRQ5    0x15         /* IRQ level 5 */
-#define SP_TRAP_IRQ6    0x16         /* IRQ level 6 */
-#define SP_TRAP_IRQ7    0x17         /* IRQ level 7 */
-#define SP_TRAP_IRQ8    0x18         /* IRQ level 8 */
-#define SP_TRAP_IRQ9    0x19         /* IRQ level 9 */
-#define SP_TRAP_IRQ10   0x1a         /* IRQ level 10 */
-#define SP_TRAP_IRQ11   0x1b         /* IRQ level 11 */
-#define SP_TRAP_IRQ12   0x1c         /* IRQ level 12 */
-#define SP_TRAP_IRQ13   0x1d         /* IRQ level 13 */
-#define SP_TRAP_IRQ14   0x1e         /* IRQ level 14 */
-#define SP_TRAP_IRQ15   0x1f         /* IRQ level 15 Non-maskable */
-#define SP_TRAP_RACC    0x20         /* Register Access Error ??? */
-#define SP_TRAP_IACC    0x21         /* Instruction Access Error */
-#define SP_TRAP_CPDIS   0x24         /* Co-Processor Disabled */
-#define SP_TRAP_BADFL   0x25         /* Unimplemented Flush Instruction */
-#define SP_TRAP_CPEXP   0x28         /* Co-Processor Exception */
-#define SP_TRAP_DACC    0x29         /* Data Access Error */
-#define SP_TRAP_DIVZ    0x2a         /* Divide By Zero */
-#define SP_TRAP_DSTORE  0x2b         /* Data Store Error ??? */
-#define SP_TRAP_DMM     0x2c         /* Data Access MMU Miss ??? */
-#define SP_TRAP_IMM     0x3c         /* Instruction Access MMU Miss ??? */
-
-/* Now the Software Traps... */
-#define SP_TRAP_SUNOS   0x80         /* SunOS System Call */
-#define SP_TRAP_SBPT    0x81         /* Software Breakpoint */
-#define SP_TRAP_SDIVZ   0x82         /* Software Divide-by-Zero trap */
-#define SP_TRAP_FWIN    0x83         /* Flush Windows */
-#define SP_TRAP_CWIN    0x84         /* Clean Windows */
-#define SP_TRAP_RCHK    0x85         /* Range Check */
-#define SP_TRAP_FUNA    0x86         /* Fix Unaligned Access */
-#define SP_TRAP_IOWFL   0x87         /* Integer Overflow */
-#define SP_TRAP_SOLARIS 0x88         /* Solaris System Call */
-#define SP_TRAP_NETBSD  0x89         /* NetBSD System Call */
-#define SP_TRAP_LINUX   0x90         /* Linux System Call */
-
-/* Names used for compatibility with SunOS */
-#define ST_SYSCALL              0x00
-#define ST_BREAKPOINT           0x01
-#define ST_DIV0                 0x02
-#define ST_FLUSH_WINDOWS        0x03
-#define ST_CLEAN_WINDOWS        0x04
-#define ST_RANGE_CHECK          0x05
-#define ST_FIX_ALIGN            0x06
-#define ST_INT_OVERFLOW         0x07
-
-/* Special traps... */
-#define SP_TRAP_KBPT1   0xfe         /* KADB/PROM Breakpoint one */
-#define SP_TRAP_KBPT2   0xff         /* KADB/PROM Breakpoint two */
-
-/* Handy Macros */
-/* Is this a trap we never expect to get? */
-#define BAD_TRAP_P(level) \
-        ((level > SP_TRAP_WDOG && level < SP_TRAP_IRQ1) || \
-        (level > SP_TRAP_IACC && level < SP_TRAP_CPDIS) || \
-        (level > SP_TRAP_BADFL && level < SP_TRAP_CPEXP) || \
-        (level > SP_TRAP_DMM && level < SP_TRAP_IMM) || \
-        (level > SP_TRAP_IMM && level < SP_TRAP_SUNOS) || \
-        (level > SP_TRAP_LINUX && level < SP_TRAP_KBPT1))
-
-/* Is this a Hardware trap? */
-#define HW_TRAP_P(level) ((level > 0) && (level < SP_TRAP_SUNOS))
-
-/* Is this a Software trap? */
-#define SW_TRAP_P(level) ((level >= SP_TRAP_SUNOS) && (level <= SP_TRAP_KBPT2))
-
-/* Is this a system call for some OS we know about? */
-#define SCALL_TRAP_P(level) ((level == SP_TRAP_SUNOS) || \
-                            (level == SP_TRAP_SOLARIS) || \
-                            (level == SP_TRAP_NETBSD) || \
-                            (level == SP_TRAP_LINUX))
-
 #endif /* !(_SPARC_TRAPS_H) */
index 7c831d848b4e10b93737d619f2789fe00ba5fe13..73083e1d38d9b9cd5e4a032183f3367765b88add 100644 (file)
@@ -265,6 +265,11 @@ extern __must_check long strnlen_user(const char __user *str, long n);
 #define __copy_to_user_inatomic ___copy_to_user
 #define __copy_from_user_inatomic ___copy_from_user
 
+struct pt_regs;
+extern unsigned long compute_effective_address(struct pt_regs *,
+                                              unsigned int insn,
+                                              unsigned int rd);
+
 #endif  /* __ASSEMBLY__ */
 
 #endif /* _ASM_UACCESS_H */
index d9a677c51926815865d3db306ac4e6cd1c5b90d5..0ecea6ed943e3a5b525e90711ef80a5cdbc16f57 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef _SPARC_UNISTD_H
-#define _SPARC_UNISTD_H
-
 /*
  * System calls under the Sparc.
  *
  *
  * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
  */
-#ifndef __32bit_syscall_numbers__
-#ifndef __arch64__
-#define __32bit_syscall_numbers__
-#endif
-#endif
+#ifndef _SPARC_UNISTD_H
+#define _SPARC_UNISTD_H
+
+#include <uapi/asm/unistd.h>
 
-#define __NR_restart_syscall      0 /* Linux Specific                             */
-#define __NR_exit                 1 /* Common                                      */
-#define __NR_fork                 2 /* Common                                      */
-#define __NR_read                 3 /* Common                                      */
-#define __NR_write                4 /* Common                                      */
-#define __NR_open                 5 /* Common                                      */
-#define __NR_close                6 /* Common                                      */
-#define __NR_wait4                7 /* Common                                      */
-#define __NR_creat                8 /* Common                                      */
-#define __NR_link                 9 /* Common                                      */
-#define __NR_unlink              10 /* Common                                      */
-#define __NR_execv               11 /* SunOS Specific                              */
-#define __NR_chdir               12 /* Common                                      */
-#define __NR_chown              13 /* Common                                      */
-#define __NR_mknod               14 /* Common                                      */
-#define __NR_chmod               15 /* Common                                      */
-#define __NR_lchown              16 /* Common                                      */
-#define __NR_brk                 17 /* Common                                      */
-#define __NR_perfctr             18 /* Performance counter operations              */
-#define __NR_lseek               19 /* Common                                      */
-#define __NR_getpid              20 /* Common                                      */
-#define __NR_capget             21 /* Linux Specific                              */
-#define __NR_capset             22 /* Linux Specific                              */
-#define __NR_setuid              23 /* Implemented via setreuid in SunOS           */
-#define __NR_getuid              24 /* Common                                      */
-#define __NR_vmsplice           25 /* ENOSYS under SunOS                          */
-#define __NR_ptrace              26 /* Common                                      */
-#define __NR_alarm               27 /* Implemented via setitimer in SunOS          */
-#define __NR_sigaltstack        28 /* Common                                      */
-#define __NR_pause               29 /* Is sigblock(0)->sigpause() in SunOS         */
-#define __NR_utime               30 /* Implemented via utimes() under SunOS        */
-#ifdef __32bit_syscall_numbers__
-#define __NR_lchown32            31 /* Linux sparc32 specific                      */
-#define __NR_fchown32            32 /* Linux sparc32 specific                      */
-#endif
-#define __NR_access              33 /* Common                                      */
-#define __NR_nice                34 /* Implemented via get/setpriority() in SunOS  */
-#ifdef __32bit_syscall_numbers__
-#define __NR_chown32             35 /* Linux sparc32 specific                      */
-#endif
-#define __NR_sync                36 /* Common                                      */
-#define __NR_kill                37 /* Common                                      */
-#define __NR_stat                38 /* Common                                      */
-#define __NR_sendfile           39 /* Linux Specific                              */
-#define __NR_lstat               40 /* Common                                      */
-#define __NR_dup                 41 /* Common                                      */
-#define __NR_pipe                42 /* Common                                      */
-#define __NR_times               43 /* Implemented via getrusage() in SunOS        */
-#ifdef __32bit_syscall_numbers__
-#define __NR_getuid32            44 /* Linux sparc32 specific                      */
-#endif
-#define __NR_umount2             45 /* Linux Specific                              */
-#define __NR_setgid              46 /* Implemented via setregid() in SunOS         */
-#define __NR_getgid              47 /* Common                                      */
-#define __NR_signal              48 /* Implemented via sigvec() in SunOS           */
-#define __NR_geteuid             49 /* SunOS calls getuid()                        */
-#define __NR_getegid             50 /* SunOS calls getgid()                        */
-#define __NR_acct                51 /* Common                                      */
-#ifdef __32bit_syscall_numbers__
-#define __NR_getgid32            53 /* Linux sparc32 specific                      */
-#else
-#define __NR_memory_ordering    52 /* Linux Specific                              */
-#endif
-#define __NR_ioctl               54 /* Common                                      */
-#define __NR_reboot              55 /* Common                                      */
-#ifdef __32bit_syscall_numbers__
-#define __NR_mmap2              56 /* Linux sparc32 Specific                      */
-#endif
-#define __NR_symlink             57 /* Common                                      */
-#define __NR_readlink            58 /* Common                                      */
-#define __NR_execve              59 /* Common                                      */
-#define __NR_umask               60 /* Common                                      */
-#define __NR_chroot              61 /* Common                                      */
-#define __NR_fstat               62 /* Common                                      */
-#define __NR_fstat64            63 /* Linux Specific                              */
-#define __NR_getpagesize         64 /* Common                                      */
-#define __NR_msync               65 /* Common in newer 1.3.x revs...               */
-#define __NR_vfork               66 /* Common                                      */
-#define __NR_pread64             67 /* Linux Specific                              */
-#define __NR_pwrite64            68 /* Linux Specific                              */
-#ifdef __32bit_syscall_numbers__
-#define __NR_geteuid32           69 /* Linux sparc32, sbrk under SunOS             */
-#define __NR_getegid32           70 /* Linux sparc32, sstk under SunOS             */
-#endif
-#define __NR_mmap                71 /* Common                                      */
-#ifdef __32bit_syscall_numbers__
-#define __NR_setreuid32          72 /* Linux sparc32, vadvise under SunOS          */
-#endif
-#define __NR_munmap              73 /* Common                                      */
-#define __NR_mprotect            74 /* Common                                      */
-#define __NR_madvise             75 /* Common                                      */
-#define __NR_vhangup             76 /* Common                                      */
-#ifdef __32bit_syscall_numbers__
-#define __NR_truncate64                 77 /* Linux sparc32 Specific                      */
-#endif
-#define __NR_mincore             78 /* Common                                      */
-#define __NR_getgroups           79 /* Common                                      */
-#define __NR_setgroups           80 /* Common                                      */
-#define __NR_getpgrp             81 /* Common                                      */
-#ifdef __32bit_syscall_numbers__
-#define __NR_setgroups32         82 /* Linux sparc32, setpgrp under SunOS          */
-#endif
-#define __NR_setitimer           83 /* Common                                      */
-#ifdef __32bit_syscall_numbers__
-#define __NR_ftruncate64        84 /* Linux sparc32 Specific                      */
-#endif
-#define __NR_swapon              85 /* Common                                      */
-#define __NR_getitimer           86 /* Common                                      */
-#ifdef __32bit_syscall_numbers__
-#define __NR_setuid32            87 /* Linux sparc32, gethostname under SunOS      */
-#endif
-#define __NR_sethostname         88 /* Common                                      */
-#ifdef __32bit_syscall_numbers__
-#define __NR_setgid32            89 /* Linux sparc32, getdtablesize under SunOS    */
-#endif
-#define __NR_dup2                90 /* Common                                      */
-#ifdef __32bit_syscall_numbers__
-#define __NR_setfsuid32          91 /* Linux sparc32, getdopt under SunOS          */
-#endif
-#define __NR_fcntl               92 /* Common                                      */
-#define __NR_select              93 /* Common                                      */
-#ifdef __32bit_syscall_numbers__
-#define __NR_setfsgid32          94 /* Linux sparc32, setdopt under SunOS          */
-#endif
-#define __NR_fsync               95 /* Common                                      */
-#define __NR_setpriority         96 /* Common                                      */
-#define __NR_socket              97 /* Common                                      */
-#define __NR_connect             98 /* Common                                      */
-#define __NR_accept              99 /* Common                                      */
-#define __NR_getpriority        100 /* Common                                      */
-#define __NR_rt_sigreturn       101 /* Linux Specific                              */
-#define __NR_rt_sigaction       102 /* Linux Specific                              */
-#define __NR_rt_sigprocmask     103 /* Linux Specific                              */
-#define __NR_rt_sigpending      104 /* Linux Specific                              */
-#define __NR_rt_sigtimedwait    105 /* Linux Specific                              */
-#define __NR_rt_sigqueueinfo    106 /* Linux Specific                              */
-#define __NR_rt_sigsuspend      107 /* Linux Specific                              */
-#ifdef __32bit_syscall_numbers__
-#define __NR_setresuid32        108 /* Linux Specific, sigvec under SunOS         */
-#define __NR_getresuid32        109 /* Linux Specific, sigblock under SunOS       */
-#define __NR_setresgid32        110 /* Linux Specific, sigsetmask under SunOS     */
-#define __NR_getresgid32        111 /* Linux Specific, sigpause under SunOS       */
-#define __NR_setregid32         112 /* Linux sparc32, sigstack under SunOS         */
-#else
-#define __NR_setresuid          108 /* Linux Specific, sigvec under SunOS         */
-#define __NR_getresuid          109 /* Linux Specific, sigblock under SunOS       */
-#define __NR_setresgid          110 /* Linux Specific, sigsetmask under SunOS     */
-#define __NR_getresgid          111 /* Linux Specific, sigpause under SunOS       */
-#endif
-#define __NR_recvmsg            113 /* Common                                      */
-#define __NR_sendmsg            114 /* Common                                      */
-#ifdef __32bit_syscall_numbers__
-#define __NR_getgroups32        115 /* Linux sparc32, vtrace under SunOS           */
-#endif
-#define __NR_gettimeofday       116 /* Common                                      */
-#define __NR_getrusage          117 /* Common                                      */
-#define __NR_getsockopt         118 /* Common                                      */
-#define __NR_getcwd            119 /* Linux Specific                              */
-#define __NR_readv              120 /* Common                                      */
-#define __NR_writev             121 /* Common                                      */
-#define __NR_settimeofday       122 /* Common                                      */
-#define __NR_fchown             123 /* Common                                      */
-#define __NR_fchmod             124 /* Common                                      */
-#define __NR_recvfrom           125 /* Common                                      */
-#define __NR_setreuid           126 /* Common                                      */
-#define __NR_setregid           127 /* Common                                      */
-#define __NR_rename             128 /* Common                                      */
-#define __NR_truncate           129 /* Common                                      */
-#define __NR_ftruncate          130 /* Common                                      */
-#define __NR_flock              131 /* Common                                      */
-#define __NR_lstat64           132 /* Linux Specific                              */
-#define __NR_sendto             133 /* Common                                      */
-#define __NR_shutdown           134 /* Common                                      */
-#define __NR_socketpair         135 /* Common                                      */
-#define __NR_mkdir              136 /* Common                                      */
-#define __NR_rmdir              137 /* Common                                      */
-#define __NR_utimes             138 /* SunOS Specific                              */
-#define __NR_stat64            139 /* Linux Specific                              */
-#define __NR_sendfile64         140 /* adjtime under SunOS                         */
-#define __NR_getpeername        141 /* Common                                      */
-#define __NR_futex              142 /* gethostid under SunOS                       */
-#define __NR_gettid             143 /* ENOSYS under SunOS                          */
-#define __NR_getrlimit         144 /* Common                                      */
-#define __NR_setrlimit          145 /* Common                                      */
-#define __NR_pivot_root                146 /* Linux Specific, killpg under SunOS          */
-#define __NR_prctl             147 /* ENOSYS under SunOS                          */
-#define __NR_pciconfig_read    148 /* ENOSYS under SunOS                          */
-#define __NR_pciconfig_write   149 /* ENOSYS under SunOS                          */
-#define __NR_getsockname        150 /* Common                                      */
-#define __NR_inotify_init       151 /* Linux specific                              */
-#define __NR_inotify_add_watch  152 /* Linux specific                              */
-#define __NR_poll               153 /* Common                                      */
-#define __NR_getdents64                154 /* Linux specific                              */
-#ifdef __32bit_syscall_numbers__
-#define __NR_fcntl64           155 /* Linux sparc32 Specific                      */
-#endif
-#define __NR_inotify_rm_watch   156 /* Linux specific                             */
-#define __NR_statfs             157 /* Common                                      */
-#define __NR_fstatfs            158 /* Common                                      */
-#define __NR_umount             159 /* Common                                      */
-#define __NR_sched_set_affinity 160 /* Linux specific, async_daemon under SunOS    */
-#define __NR_sched_get_affinity 161 /* Linux specific, getfh under SunOS           */
-#define __NR_getdomainname      162 /* SunOS Specific                              */
-#define __NR_setdomainname      163 /* Common                                      */
-#ifndef __32bit_syscall_numbers__
-#define __NR_utrap_install     164 /* SYSV ABI/v9 required                        */
-#endif
-#define __NR_quotactl           165 /* Common                                      */
-#define __NR_set_tid_address    166 /* Linux specific, exportfs under SunOS        */
-#define __NR_mount              167 /* Common                                      */
-#define __NR_ustat              168 /* Common                                      */
-#define __NR_setxattr           169 /* SunOS: semsys                               */
-#define __NR_lsetxattr          170 /* SunOS: msgsys                               */
-#define __NR_fsetxattr          171 /* SunOS: shmsys                               */
-#define __NR_getxattr           172 /* SunOS: auditsys                             */
-#define __NR_lgetxattr          173 /* SunOS: rfssys                               */
-#define __NR_getdents           174 /* Common                                      */
-#define __NR_setsid             175 /* Common                                      */
-#define __NR_fchdir             176 /* Common                                      */
-#define __NR_fgetxattr          177 /* SunOS: fchroot                              */
-#define __NR_listxattr          178 /* SunOS: vpixsys                              */
-#define __NR_llistxattr         179 /* SunOS: aioread                              */
-#define __NR_flistxattr         180 /* SunOS: aiowrite                             */
-#define __NR_removexattr        181 /* SunOS: aiowait                              */
-#define __NR_lremovexattr       182 /* SunOS: aiocancel                            */
-#define __NR_sigpending         183 /* Common                                      */
-#define __NR_query_module      184 /* Linux Specific                              */
-#define __NR_setpgid            185 /* Common                                      */
-#define __NR_fremovexattr       186 /* SunOS: pathconf                             */
-#define __NR_tkill              187 /* SunOS: fpathconf                            */
-#define __NR_exit_group                188 /* Linux specific, sysconf undef SunOS         */
-#define __NR_uname              189 /* Linux Specific                              */
-#define __NR_init_module        190 /* Linux Specific                              */
-#define __NR_personality        191 /* Linux Specific                              */
-#define __NR_remap_file_pages   192 /* Linux Specific                              */
-#define __NR_epoll_create       193 /* Linux Specific                              */
-#define __NR_epoll_ctl          194 /* Linux Specific                              */
-#define __NR_epoll_wait         195 /* Linux Specific                              */
-#define __NR_ioprio_set         196 /* Linux Specific                              */
-#define __NR_getppid            197 /* Linux Specific                              */
-#define __NR_sigaction          198 /* Linux Specific                              */
-#define __NR_sgetmask           199 /* Linux Specific                              */
-#define __NR_ssetmask           200 /* Linux Specific                              */
-#define __NR_sigsuspend         201 /* Linux Specific                              */
-#define __NR_oldlstat           202 /* Linux Specific                              */
-#define __NR_uselib             203 /* Linux Specific                              */
-#define __NR_readdir            204 /* Linux Specific                              */
-#define __NR_readahead          205 /* Linux Specific                              */
-#define __NR_socketcall         206 /* Linux Specific                              */
-#define __NR_syslog             207 /* Linux Specific                              */
-#define __NR_lookup_dcookie     208 /* Linux Specific                              */
-#define __NR_fadvise64          209 /* Linux Specific                              */
-#define __NR_fadvise64_64       210 /* Linux Specific                              */
-#define __NR_tgkill             211 /* Linux Specific                              */
-#define __NR_waitpid            212 /* Linux Specific                              */
-#define __NR_swapoff            213 /* Linux Specific                              */
-#define __NR_sysinfo            214 /* Linux Specific                              */
-#define __NR_ipc                215 /* Linux Specific                              */
-#define __NR_sigreturn          216 /* Linux Specific                              */
-#define __NR_clone              217 /* Linux Specific                              */
-#define __NR_ioprio_get         218 /* Linux Specific                              */
-#define __NR_adjtimex           219 /* Linux Specific                              */
-#define __NR_sigprocmask        220 /* Linux Specific                              */
-#define __NR_create_module      221 /* Linux Specific                              */
-#define __NR_delete_module      222 /* Linux Specific                              */
-#define __NR_get_kernel_syms    223 /* Linux Specific                              */
-#define __NR_getpgid            224 /* Linux Specific                              */
-#define __NR_bdflush            225 /* Linux Specific                              */
-#define __NR_sysfs              226 /* Linux Specific                              */
-#define __NR_afs_syscall        227 /* Linux Specific                              */
-#define __NR_setfsuid           228 /* Linux Specific                              */
-#define __NR_setfsgid           229 /* Linux Specific                              */
-#define __NR__newselect         230 /* Linux Specific                              */
 #ifdef __32bit_syscall_numbers__
-#define __NR_time               231 /* Linux Specific                              */
 #else
-#ifdef __KERNEL__
 #define __NR_time              231 /* Linux sparc32                               */
 #endif
-#endif
-#define __NR_splice             232 /* Linux Specific                              */
-#define __NR_stime              233 /* Linux Specific                              */
-#define __NR_statfs64           234 /* Linux Specific                              */
-#define __NR_fstatfs64          235 /* Linux Specific                              */
-#define __NR__llseek            236 /* Linux Specific                              */
-#define __NR_mlock              237
-#define __NR_munlock            238
-#define __NR_mlockall           239
-#define __NR_munlockall         240
-#define __NR_sched_setparam     241
-#define __NR_sched_getparam     242
-#define __NR_sched_setscheduler 243
-#define __NR_sched_getscheduler 244
-#define __NR_sched_yield        245
-#define __NR_sched_get_priority_max 246
-#define __NR_sched_get_priority_min 247
-#define __NR_sched_rr_get_interval  248
-#define __NR_nanosleep          249
-#define __NR_mremap             250
-#define __NR__sysctl            251
-#define __NR_getsid             252
-#define __NR_fdatasync          253
-#define __NR_nfsservctl         254
-#define __NR_sync_file_range   255
-#define __NR_clock_settime     256
-#define __NR_clock_gettime     257
-#define __NR_clock_getres      258
-#define __NR_clock_nanosleep   259
-#define __NR_sched_getaffinity 260
-#define __NR_sched_setaffinity 261
-#define __NR_timer_settime     262
-#define __NR_timer_gettime     263
-#define __NR_timer_getoverrun  264
-#define __NR_timer_delete      265
-#define __NR_timer_create      266
-/* #define __NR_vserver                267 Reserved for VSERVER */
-#define __NR_io_setup          268
-#define __NR_io_destroy                269
-#define __NR_io_submit         270
-#define __NR_io_cancel         271
-#define __NR_io_getevents      272
-#define __NR_mq_open           273
-#define __NR_mq_unlink         274
-#define __NR_mq_timedsend      275
-#define __NR_mq_timedreceive   276
-#define __NR_mq_notify         277
-#define __NR_mq_getsetattr     278
-#define __NR_waitid            279
-#define __NR_tee               280
-#define __NR_add_key           281
-#define __NR_request_key       282
-#define __NR_keyctl            283
-#define __NR_openat            284
-#define __NR_mkdirat           285
-#define __NR_mknodat           286
-#define __NR_fchownat          287
-#define __NR_futimesat         288
-#define __NR_fstatat64         289
-#define __NR_unlinkat          290
-#define __NR_renameat          291
-#define __NR_linkat            292
-#define __NR_symlinkat         293
-#define __NR_readlinkat                294
-#define __NR_fchmodat          295
-#define __NR_faccessat         296
-#define __NR_pselect6          297
-#define __NR_ppoll             298
-#define __NR_unshare           299
-#define __NR_set_robust_list   300
-#define __NR_get_robust_list   301
-#define __NR_migrate_pages     302
-#define __NR_mbind             303
-#define __NR_get_mempolicy     304
-#define __NR_set_mempolicy     305
-#define __NR_kexec_load                306
-#define __NR_move_pages                307
-#define __NR_getcpu            308
-#define __NR_epoll_pwait       309
-#define __NR_utimensat         310
-#define __NR_signalfd          311
-#define __NR_timerfd_create    312
-#define __NR_eventfd           313
-#define __NR_fallocate         314
-#define __NR_timerfd_settime   315
-#define __NR_timerfd_gettime   316
-#define __NR_signalfd4         317
-#define __NR_eventfd2          318
-#define __NR_epoll_create1     319
-#define __NR_dup3              320
-#define __NR_pipe2             321
-#define __NR_inotify_init1     322
-#define __NR_accept4           323
-#define __NR_preadv            324
-#define __NR_pwritev           325
-#define __NR_rt_tgsigqueueinfo 326
-#define __NR_perf_event_open   327
-#define __NR_recvmmsg          328
-#define __NR_fanotify_init     329
-#define __NR_fanotify_mark     330
-#define __NR_prlimit64         331
-#define __NR_name_to_handle_at 332
-#define __NR_open_by_handle_at 333
-#define __NR_clock_adjtime     334
-#define __NR_syncfs            335
-#define __NR_sendmmsg          336
-#define __NR_setns             337
-#define __NR_process_vm_readv  338
-#define __NR_process_vm_writev 339
-
-#define NR_syscalls            340
-
-#ifdef __32bit_syscall_numbers__
-/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
- * it never had the plain ones and there is no value to adding those
- * old versions into the syscall table.
- */
-#define __IGNORE_setresuid
-#define __IGNORE_getresuid
-#define __IGNORE_setresgid
-#define __IGNORE_getresgid
-#endif
-
-#ifdef __KERNEL__
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
-#endif /* __KERNEL__ */
 #endif /* _SPARC_UNISTD_H */
index 7518ad2869632e9111da777faca465db9dcf2909..ce175aff71b75e29fdf65cf70d8a17f2a07c5d2a 100644 (file)
@@ -3,3 +3,49 @@
 
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += apc.h
+header-y += asi.h
+header-y += auxvec.h
+header-y += bitsperlong.h
+header-y += byteorder.h
+header-y += display7seg.h
+header-y += envctrl.h
+header-y += errno.h
+header-y += fbio.h
+header-y += fcntl.h
+header-y += ioctl.h
+header-y += ioctls.h
+header-y += ipcbuf.h
+header-y += jsflash.h
+header-y += kvm_para.h
+header-y += mman.h
+header-y += msgbuf.h
+header-y += openpromio.h
+header-y += param.h
+header-y += perfctr.h
+header-y += poll.h
+header-y += posix_types.h
+header-y += psr.h
+header-y += psrcompat.h
+header-y += pstate.h
+header-y += ptrace.h
+header-y += resource.h
+header-y += sembuf.h
+header-y += setup.h
+header-y += shmbuf.h
+header-y += sigcontext.h
+header-y += siginfo.h
+header-y += signal.h
+header-y += socket.h
+header-y += sockios.h
+header-y += stat.h
+header-y += statfs.h
+header-y += swab.h
+header-y += termbits.h
+header-y += termios.h
+header-y += traps.h
+header-y += types.h
+header-y += uctx.h
+header-y += unistd.h
+header-y += utrap.h
+header-y += watchdog.h
diff --git a/arch/sparc/include/uapi/asm/fbio.h b/arch/sparc/include/uapi/asm/fbio.h
new file mode 100644 (file)
index 0000000..d6cea07
--- /dev/null
@@ -0,0 +1,259 @@
+#ifndef _UAPI__LINUX_FBIO_H
+#define _UAPI__LINUX_FBIO_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+/* Constants used for fbio SunOS compatibility */
+/* (C) 1996 Miguel de Icaza */
+
+/* Frame buffer types */
+#define FBTYPE_NOTYPE           -1
+#define FBTYPE_SUN1BW           0   /* mono */
+#define FBTYPE_SUN1COLOR        1 
+#define FBTYPE_SUN2BW           2 
+#define FBTYPE_SUN2COLOR        3 
+#define FBTYPE_SUN2GP           4 
+#define FBTYPE_SUN5COLOR        5 
+#define FBTYPE_SUN3COLOR        6 
+#define FBTYPE_MEMCOLOR         7 
+#define FBTYPE_SUN4COLOR        8 
+#define FBTYPE_NOTSUN1          9 
+#define FBTYPE_NOTSUN2          10
+#define FBTYPE_NOTSUN3          11
+#define FBTYPE_SUNFAST_COLOR    12  /* cg6 */
+#define FBTYPE_SUNROP_COLOR     13
+#define FBTYPE_SUNFB_VIDEO      14
+#define FBTYPE_SUNGIFB          15
+#define FBTYPE_SUNGPLAS         16
+#define FBTYPE_SUNGP3           17
+#define FBTYPE_SUNGT            18
+#define FBTYPE_SUNLEO           19      /* zx Leo card */
+#define FBTYPE_MDICOLOR         20      /* cg14 */
+#define FBTYPE_TCXCOLOR                21      /* SUNW,tcx card */
+
+#define FBTYPE_LASTPLUSONE      21     /* This is not last + 1 in fact... */
+
+/* Does not seem to be listed in the Sun file either */
+#define FBTYPE_CREATOR          22
+#define FBTYPE_PCI_IGA1682     23
+#define FBTYPE_P9100COLOR      24
+
+#define FBTYPE_PCI_GENERIC     1000
+#define FBTYPE_PCI_MACH64      1001
+
+/* fbio ioctls */
+/* Returned by FBIOGTYPE */
+struct  fbtype {
+        int     fb_type;        /* fb type, see above */
+        int     fb_height;      /* pixels */
+        int     fb_width;       /* pixels */
+        int     fb_depth;
+        int     fb_cmsize;      /* color map entries */
+        int     fb_size;        /* fb size in bytes */
+};
+#define FBIOGTYPE _IOR('F', 0, struct fbtype)
+
+struct  fbcmap {
+        int             index;          /* first element (0 origin) */
+        int             count;
+        unsigned char   __user *red;
+        unsigned char   __user *green;
+        unsigned char   __user *blue;
+};
+
+#ifndef __KERNEL__
+#define FBIOPUTCMAP _IOW('F', 3, struct fbcmap)
+#define FBIOGETCMAP _IOW('F', 4, struct fbcmap)
+#endif
+
+/* # of device specific values */
+#define FB_ATTR_NDEVSPECIFIC    8
+/* # of possible emulations */
+#define FB_ATTR_NEMUTYPES       4
+struct fbsattr {
+        int     flags;
+        int     emu_type;      /* -1 if none */
+        int     dev_specific[FB_ATTR_NDEVSPECIFIC];
+};
+struct fbgattr {
+        int     real_type;     /* real frame buffer type */
+        int     owner;         /* unknown */
+        struct fbtype fbtype;  /* real frame buffer fbtype */
+        struct fbsattr sattr;   
+        int     emu_types[FB_ATTR_NEMUTYPES]; /* supported emulations */
+};
+#define FBIOSATTR  _IOW('F', 5, struct fbgattr) /* Unsupported: */
+#define FBIOGATTR  _IOR('F', 6, struct fbgattr)        /* supported */
+
+#define FBIOSVIDEO _IOW('F', 7, int)
+#define FBIOGVIDEO _IOR('F', 8, int)
+
+struct fbcursor {
+        short set;              /* what to set, choose from the list above */
+        short enable;           /* cursor on/off */
+        struct fbcurpos pos;    /* cursor position */
+        struct fbcurpos hot;    /* cursor hot spot */
+        struct fbcmap cmap;     /* color map info */
+        struct fbcurpos size;   /* cursor bit map size */
+        char __user *image;     /* cursor image bits */
+        char __user *mask;      /* cursor mask bits */
+};
+
+/* set/get cursor attributes/shape */
+#define FBIOSCURSOR     _IOW('F', 24, struct fbcursor)
+#define FBIOGCURSOR     _IOWR('F', 25, struct fbcursor)
+/* set/get cursor position */
+#define FBIOSCURPOS     _IOW('F', 26, struct fbcurpos)
+#define FBIOGCURPOS     _IOW('F', 27, struct fbcurpos)
+/* get max cursor size */
+#define FBIOGCURMAX     _IOR('F', 28, struct fbcurpos)
+
+/* wid manipulation */
+struct fb_wid_alloc {
+#define FB_WID_SHARED_8                0
+#define FB_WID_SHARED_24       1
+#define FB_WID_DBL_8           2
+#define FB_WID_DBL_24          3
+       __u32   wa_type;
+       __s32   wa_index;       /* Set on return */
+       __u32   wa_count;       
+};
+struct fb_wid_item {
+       __u32   wi_type;
+       __s32   wi_index;
+       __u32   wi_attrs;
+       __u32   wi_values[32];
+};
+struct fb_wid_list {
+       __u32   wl_flags;
+       __u32   wl_count;
+       struct fb_wid_item      *wl_list;
+};
+
+#define FBIO_WID_ALLOC _IOWR('F', 30, struct fb_wid_alloc)
+#define FBIO_WID_FREE  _IOW('F', 31, struct fb_wid_alloc)
+#define FBIO_WID_PUT   _IOW('F', 32, struct fb_wid_list)
+#define FBIO_WID_GET   _IOWR('F', 33, struct fb_wid_list)
+
+/* Creator ioctls */
+#define FFB_IOCTL      ('F'<<8)
+#define FFB_SYS_INFO           (FFB_IOCTL|80)
+#define FFB_CLUTREAD           (FFB_IOCTL|81)
+#define FFB_CLUTPOST           (FFB_IOCTL|82)
+#define FFB_SETDIAGMODE                (FFB_IOCTL|83)
+#define FFB_GETMONITORID       (FFB_IOCTL|84)
+#define FFB_GETVIDEOMODE       (FFB_IOCTL|85)
+#define FFB_SETVIDEOMODE       (FFB_IOCTL|86)
+#define FFB_SETSERVER          (FFB_IOCTL|87)
+#define FFB_SETOVCTL           (FFB_IOCTL|88)
+#define FFB_GETOVCTL           (FFB_IOCTL|89)
+#define FFB_GETSAXNUM          (FFB_IOCTL|90)
+#define FFB_FBDEBUG            (FFB_IOCTL|91)
+
+/* Cg14 ioctls */
+#define MDI_IOCTL          ('M'<<8)
+#define MDI_RESET          (MDI_IOCTL|1)
+#define MDI_GET_CFGINFO    (MDI_IOCTL|2)
+#define MDI_SET_PIXELMODE  (MDI_IOCTL|3)
+#    define MDI_32_PIX     32
+#    define MDI_16_PIX     16
+#    define MDI_8_PIX      8
+
+struct mdi_cfginfo {
+       int     mdi_ncluts;     /* Number of implemented CLUTs in this MDI */
+        int     mdi_type;       /* FBTYPE name */
+        int     mdi_height;     /* height */
+        int     mdi_width;      /* width */
+        int     mdi_size;       /* available ram */
+        int     mdi_mode;       /* 8bpp, 16bpp or 32bpp */
+        int     mdi_pixfreq;    /* pixel clock (from PROM) */
+};
+
+/* SparcLinux specific ioctl for the MDI, should be replaced for
+ * the SET_XLUT/SET_CLUTn ioctls instead
+ */
+#define MDI_CLEAR_XLUT       (MDI_IOCTL|9)
+
+/* leo & ffb ioctls */
+struct fb_clut_alloc {
+       __u32   clutid; /* Set on return */
+       __u32   flag;
+       __u32   index;
+};
+
+struct fb_clut {
+#define FB_CLUT_WAIT   0x00000001      /* Not yet implemented */
+       __u32   flag;
+       __u32   clutid;
+       __u32   offset;
+       __u32   count;
+       char *  red;
+       char *  green;
+       char *  blue;
+};
+
+struct fb_clut32 {
+       __u32   flag;
+       __u32   clutid;
+       __u32   offset;
+       __u32   count;
+       __u32   red;
+       __u32   green;
+       __u32   blue;
+};
+
+#define LEO_CLUTALLOC  _IOWR('L', 53, struct fb_clut_alloc)
+#define LEO_CLUTFREE   _IOW('L', 54, struct fb_clut_alloc)
+#define LEO_CLUTREAD   _IOW('L', 55, struct fb_clut)
+#define LEO_CLUTPOST   _IOW('L', 56, struct fb_clut)
+#define LEO_SETGAMMA   _IOW('L', 68, int) /* Not yet implemented */
+#define LEO_GETGAMMA   _IOR('L', 69, int) /* Not yet implemented */
+
+
+/* These are exported to userland for applications to use */
+/* Mappable offsets for the cg14: control registers */
+#define MDI_DIRECT_MAP 0x10000000
+#define MDI_CTLREG_MAP 0x20000000
+#define MDI_CURSOR_MAP 0x30000000
+#define MDI_SHDW_VRT_MAP 0x40000000
+
+/* Mappable offsets for the cg14: frame buffer resolutions */
+/* 32 bits */
+#define MDI_CHUNKY_XBGR_MAP 0x50000000
+#define MDI_CHUNKY_BGR_MAP 0x60000000
+
+/* 16 bits */
+#define MDI_PLANAR_X16_MAP 0x70000000
+#define MDI_PLANAR_C16_MAP 0x80000000
+
+/* 8 bit is done as CG3 MMAP offset */
+/* 32 bits, planar */
+#define MDI_PLANAR_X32_MAP 0x90000000
+#define MDI_PLANAR_B32_MAP 0xa0000000
+#define MDI_PLANAR_G32_MAP 0xb0000000
+#define MDI_PLANAR_R32_MAP 0xc0000000
+
+/* Mappable offsets on leo */
+#define LEO_SS0_MAP            0x00000000
+#define LEO_LC_SS0_USR_MAP     0x00800000
+#define LEO_LD_SS0_MAP         0x00801000
+#define LEO_LX_CURSOR_MAP      0x00802000
+#define LEO_SS1_MAP            0x00803000
+#define LEO_LC_SS1_USR_MAP     0x01003000
+#define LEO_LD_SS1_MAP         0x01004000
+#define LEO_UNK_MAP            0x01005000
+#define LEO_LX_KRN_MAP         0x01006000
+#define LEO_LC_SS0_KRN_MAP     0x01007000
+#define LEO_LC_SS1_KRN_MAP     0x01008000
+#define LEO_LD_GBL_MAP         0x01009000
+#define LEO_UNK2_MAP           0x0100a000
+
+
+#endif /* _UAPI__LINUX_FBIO_H */
diff --git a/arch/sparc/include/uapi/asm/ioctls.h b/arch/sparc/include/uapi/asm/ioctls.h
new file mode 100644 (file)
index 0000000..9155f70
--- /dev/null
@@ -0,0 +1,131 @@
+#ifndef _UAPI_ASM_SPARC_IOCTLS_H
+#define _UAPI_ASM_SPARC_IOCTLS_H
+
+#include <asm/ioctl.h>
+
+/* Big T */
+#define TCGETA         _IOR('T', 1, struct termio)
+#define TCSETA         _IOW('T', 2, struct termio)
+#define TCSETAW                _IOW('T', 3, struct termio)
+#define TCSETAF                _IOW('T', 4, struct termio)
+#define TCSBRK         _IO('T', 5)
+#define TCXONC         _IO('T', 6)
+#define TCFLSH         _IO('T', 7)
+#define TCGETS         _IOR('T', 8, struct termios)
+#define TCSETS         _IOW('T', 9, struct termios)
+#define TCSETSW                _IOW('T', 10, struct termios)
+#define TCSETSF                _IOW('T', 11, struct termios)
+#define TCGETS2                _IOR('T', 12, struct termios2)
+#define TCSETS2                _IOW('T', 13, struct termios2)
+#define TCSETSW2       _IOW('T', 14, struct termios2)
+#define TCSETSF2       _IOW('T', 15, struct termios2)
+#define TIOCGDEV       _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
+#define TIOCVHANGUP    _IO('T', 0x37)
+
+/* Note that all the ioctls that are not available in Linux have a 
+ * double underscore on the front to: a) avoid some programs to
+ * think we support some ioctls under Linux (autoconfiguration stuff)
+ */
+/* Little t */
+#define TIOCGETD       _IOR('t', 0, int)
+#define TIOCSETD       _IOW('t', 1, int)
+#define __TIOCHPCL        _IO('t', 2) /* SunOS Specific */
+#define __TIOCMODG        _IOR('t', 3, int) /* SunOS Specific */
+#define __TIOCMODS        _IOW('t', 4, int) /* SunOS Specific */
+#define __TIOCGETP        _IOR('t', 8, struct sgttyb) /* SunOS Specific */
+#define __TIOCSETP        _IOW('t', 9, struct sgttyb) /* SunOS Specific */
+#define __TIOCSETN        _IOW('t', 10, struct sgttyb) /* SunOS Specific */
+#define TIOCEXCL       _IO('t', 13)
+#define TIOCNXCL       _IO('t', 14)
+#define __TIOCFLUSH       _IOW('t', 16, int) /* SunOS Specific */
+#define __TIOCSETC        _IOW('t', 17, struct tchars) /* SunOS Specific */
+#define __TIOCGETC        _IOR('t', 18, struct tchars) /* SunOS Specific */
+#define __TIOCTCNTL       _IOW('t', 32, int) /* SunOS Specific */
+#define __TIOCSIGNAL      _IOW('t', 33, int) /* SunOS Specific */
+#define __TIOCSETX        _IOW('t', 34, int) /* SunOS Specific */
+#define __TIOCGETX        _IOR('t', 35, int) /* SunOS Specific */
+#define TIOCCONS       _IO('t', 36)
+#define TIOCGSOFTCAR   _IOR('t', 100, int)
+#define TIOCSSOFTCAR   _IOW('t', 101, int)
+#define __TIOCUCNTL       _IOW('t', 102, int) /* SunOS Specific */
+#define TIOCSWINSZ     _IOW('t', 103, struct winsize)
+#define TIOCGWINSZ     _IOR('t', 104, struct winsize)
+#define __TIOCREMOTE      _IOW('t', 105, int) /* SunOS Specific */
+#define TIOCMGET       _IOR('t', 106, int)
+#define TIOCMBIC       _IOW('t', 107, int)
+#define TIOCMBIS       _IOW('t', 108, int)
+#define TIOCMSET       _IOW('t', 109, int)
+#define TIOCSTART       _IO('t', 110)
+#define TIOCSTOP        _IO('t', 111)
+#define TIOCPKT                _IOW('t', 112, int)
+#define TIOCNOTTY      _IO('t', 113)
+#define TIOCSTI                _IOW('t', 114, char)
+#define TIOCOUTQ       _IOR('t', 115, int)
+#define __TIOCGLTC        _IOR('t', 116, struct ltchars) /* SunOS Specific */
+#define __TIOCSLTC        _IOW('t', 117, struct ltchars) /* SunOS Specific */
+/* 118 is the non-posix setpgrp tty ioctl */
+/* 119 is the non-posix getpgrp tty ioctl */
+#define __TIOCCDTR        _IO('t', 120) /* SunOS Specific */
+#define __TIOCSDTR        _IO('t', 121) /* SunOS Specific */
+#define TIOCCBRK        _IO('t', 122)
+#define TIOCSBRK        _IO('t', 123)
+#define __TIOCLGET        _IOW('t', 124, int) /* SunOS Specific */
+#define __TIOCLSET        _IOW('t', 125, int) /* SunOS Specific */
+#define __TIOCLBIC        _IOW('t', 126, int) /* SunOS Specific */
+#define __TIOCLBIS        _IOW('t', 127, int) /* SunOS Specific */
+#define __TIOCISPACE      _IOR('t', 128, int) /* SunOS Specific */
+#define __TIOCISIZE       _IOR('t', 129, int) /* SunOS Specific */
+#define TIOCSPGRP      _IOW('t', 130, int)
+#define TIOCGPGRP      _IOR('t', 131, int)
+#define TIOCSCTTY      _IO('t', 132)
+#define TIOCGSID       _IOR('t', 133, int)
+/* Get minor device of a pty master's FD -- Solaris equiv is ISPTM */
+#define TIOCGPTN       _IOR('t', 134, unsigned int) /* Get Pty Number */
+#define TIOCSPTLCK     _IOW('t', 135, int) /* Lock/unlock PTY */
+#define TIOCSIG                _IOW('t', 136, int) /* Generate signal on Pty slave */
+
+/* Little f */
+#define FIOCLEX                _IO('f', 1)
+#define FIONCLEX       _IO('f', 2)
+#define FIOASYNC       _IOW('f', 125, int)
+#define FIONBIO                _IOW('f', 126, int)
+#define FIONREAD       _IOR('f', 127, int)
+#define TIOCINQ                FIONREAD
+#define FIOQSIZE       _IOR('f', 128, loff_t)
+
+/* SCARY Rutgers local SunOS kernel hackery, perhaps I will support it
+ * someday.  This is completely bogus, I know...
+ */
+#define __TCGETSTAT       _IO('T', 200) /* Rutgers specific */
+#define __TCSETSTAT       _IO('T', 201) /* Rutgers specific */
+
+/* Linux specific, no SunOS equivalent. */
+#define TIOCLINUX      0x541C
+#define TIOCGSERIAL    0x541E
+#define TIOCSSERIAL    0x541F
+#define TCSBRKP                0x5425
+#define TIOCSERCONFIG  0x5453
+#define TIOCSERGWILD   0x5454
+#define TIOCSERSWILD   0x5455
+#define TIOCGLCKTRMIOS 0x5456
+#define TIOCSLCKTRMIOS 0x5457
+#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
+#define TIOCSERGETLSR   0x5459 /* Get line status register */
+#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
+#define TIOCSERSETMULTI 0x545B /* Set multiport config */
+#define TIOCMIWAIT     0x545C /* Wait for change on serial input line(s) */
+#define TIOCGICOUNT    0x545D /* Read serial port inline interrupt counts */
+
+/* Kernel definitions */
+
+/* Used for packet mode */
+#define TIOCPKT_DATA            0
+#define TIOCPKT_FLUSHREAD       1
+#define TIOCPKT_FLUSHWRITE      2
+#define TIOCPKT_STOP            4
+#define TIOCPKT_START           8
+#define TIOCPKT_NOSTOP         16
+#define TIOCPKT_DOSTOP         32
+#define TIOCPKT_IOCTL          64
+
+#endif /* _UAPI_ASM_SPARC_IOCTLS_H */
diff --git a/arch/sparc/include/uapi/asm/mman.h b/arch/sparc/include/uapi/asm/mman.h
new file mode 100644 (file)
index 0000000..0b14df3
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _UAPI__SPARC_MMAN_H__
+#define _UAPI__SPARC_MMAN_H__
+
+#include <asm-generic/mman-common.h>
+
+/* SunOS'ified... */
+
+#define MAP_RENAME      MAP_ANONYMOUS   /* In SunOS terminology */
+#define MAP_NORESERVE   0x40            /* don't reserve swap pages */
+#define MAP_INHERIT     0x80            /* SunOS doesn't do this, but... */
+#define MAP_LOCKED      0x100           /* lock the mapping */
+#define _MAP_NEW        0x80000000      /* Binary compatibility is fun... */
+
+#define MAP_GROWSDOWN  0x0200          /* stack-like segment */
+#define MAP_DENYWRITE  0x0800          /* ETXTBSY */
+#define MAP_EXECUTABLE 0x1000          /* mark it as an executable */
+
+#define MCL_CURRENT     0x2000          /* lock all currently mapped pages */
+#define MCL_FUTURE      0x4000          /* lock all additions to address space */
+
+#define MAP_POPULATE   0x8000          /* populate (prefault) pagetables */
+#define MAP_NONBLOCK   0x10000         /* do not block on IO */
+#define MAP_STACK      0x20000         /* give out an address that is best suited for process/thread stacks */
+#define MAP_HUGETLB    0x40000         /* create a huge page mapping */
+
+
+#endif /* _UAPI__SPARC_MMAN_H__ */
diff --git a/arch/sparc/include/uapi/asm/psr.h b/arch/sparc/include/uapi/asm/psr.h
new file mode 100644 (file)
index 0000000..2f0ed85
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * psr.h: This file holds the macros for masking off various parts of
+ *        the processor status register on the Sparc. This is valid
+ *        for Version 8. On the V9 this is renamed to the PSTATE
+ *        register and its members are accessed as fields like
+ *        PSTATE.PRIV for the current CPU privilege level.
+ *
+ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _UAPI__LINUX_SPARC_PSR_H
+#define _UAPI__LINUX_SPARC_PSR_H
+
+/* The Sparc PSR fields are laid out as the following:
+ *
+ *  ------------------------------------------------------------------------
+ *  | impl  | vers  | icc   | resv  | EC | EF | PIL  | S | PS | ET |  CWP  |
+ *  | 31-28 | 27-24 | 23-20 | 19-14 | 13 | 12 | 11-8 | 7 | 6  | 5  |  4-0  |
+ *  ------------------------------------------------------------------------
+ */
+#define PSR_CWP     0x0000001f         /* current window pointer     */
+#define PSR_ET      0x00000020         /* enable traps field         */
+#define PSR_PS      0x00000040         /* previous privilege level   */
+#define PSR_S       0x00000080         /* current privilege level    */
+#define PSR_PIL     0x00000f00         /* processor interrupt level  */
+#define PSR_EF      0x00001000         /* enable floating point      */
+#define PSR_EC      0x00002000         /* enable co-processor        */
+#define PSR_SYSCALL 0x00004000         /* inside of a syscall        */
+#define PSR_LE      0x00008000         /* SuperSparcII little-endian */
+#define PSR_ICC     0x00f00000         /* integer condition codes    */
+#define PSR_C       0x00100000         /* carry bit                  */
+#define PSR_V       0x00200000         /* overflow bit               */
+#define PSR_Z       0x00400000         /* zero bit                   */
+#define PSR_N       0x00800000         /* negative bit               */
+#define PSR_VERS    0x0f000000         /* cpu-version field          */
+#define PSR_IMPL    0xf0000000         /* cpu-implementation field   */
+
+#define PSR_VERS_SHIFT         24
+#define PSR_IMPL_SHIFT         28
+#define PSR_VERS_SHIFTED_MASK  0xf
+#define PSR_IMPL_SHIFTED_MASK  0xf
+
+#define PSR_IMPL_TI            0x4
+#define PSR_IMPL_LEON          0xf
+
+
+#endif /* _UAPI__LINUX_SPARC_PSR_H */
diff --git a/arch/sparc/include/uapi/asm/ptrace.h b/arch/sparc/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..56fe4ea
--- /dev/null
@@ -0,0 +1,352 @@
+#ifndef _UAPI__SPARC_PTRACE_H
+#define _UAPI__SPARC_PTRACE_H
+
+#if defined(__sparc__) && defined(__arch64__)
+/* 64 bit sparc */
+#include <asm/pstate.h>
+
+/* This struct defines the way the registers are stored on the
+ * stack during a system call and basically all traps.
+ */
+
+/* This magic value must have the low 9 bits clear,
+ * as that is where we encode the %tt value, see below.
+ */
+#define PT_REGS_MAGIC 0x57ac6c00
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct pt_regs {
+       unsigned long u_regs[16]; /* globals and ins */
+       unsigned long tstate;
+       unsigned long tpc;
+       unsigned long tnpc;
+       unsigned int y;
+
+       /* We encode a magic number, PT_REGS_MAGIC, along
+        * with the %tt (trap type) register value at trap
+        * entry time.  The magic number allows us to identify
+        * accurately a trap stack frame in the stack
+        * unwinder, and the %tt value allows us to test
+        * things like "in a system call" etc. for an arbitray
+        * process.
+        *
+        * The PT_REGS_MAGIC is chosen such that it can be
+        * loaded completely using just a sethi instruction.
+        */
+       unsigned int magic;
+};
+
+struct pt_regs32 {
+       unsigned int psr;
+       unsigned int pc;
+       unsigned int npc;
+       unsigned int y;
+       unsigned int u_regs[16]; /* globals and ins */
+};
+
+/* A V9 register window */
+struct reg_window {
+       unsigned long locals[8];
+       unsigned long ins[8];
+};
+
+/* A 32-bit register window. */
+struct reg_window32 {
+       unsigned int locals[8];
+       unsigned int ins[8];
+};
+
+/* A V9 Sparc stack frame */
+struct sparc_stackf {
+       unsigned long locals[8];
+        unsigned long ins[6];
+       struct sparc_stackf *fp;
+       unsigned long callers_pc;
+       char *structptr;
+       unsigned long xargs[6];
+       unsigned long xxargs[1];
+};
+
+/* A 32-bit Sparc stack frame */
+struct sparc_stackf32 {
+       unsigned int locals[8];
+        unsigned int ins[6];
+       unsigned int fp;
+       unsigned int callers_pc;
+       unsigned int structptr;
+       unsigned int xargs[6];
+       unsigned int xxargs[1];
+};
+
+struct sparc_trapf {
+       unsigned long locals[8];
+       unsigned long ins[8];
+       unsigned long _unused;
+       struct pt_regs *regs;
+};
+#endif /* (!__ASSEMBLY__) */
+#else
+/* 32 bit sparc */
+
+#include <asm/psr.h>
+
+/* This struct defines the way the registers are stored on the
+ * stack during a system call and basically all traps.
+ */
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct pt_regs {
+       unsigned long psr;
+       unsigned long pc;
+       unsigned long npc;
+       unsigned long y;
+       unsigned long u_regs[16]; /* globals and ins */
+};
+
+/* A 32-bit register window. */
+struct reg_window32 {
+       unsigned long locals[8];
+       unsigned long ins[8];
+};
+
+/* A Sparc stack frame */
+struct sparc_stackf {
+       unsigned long locals[8];
+        unsigned long ins[6];
+       struct sparc_stackf *fp;
+       unsigned long callers_pc;
+       char *structptr;
+       unsigned long xargs[6];
+       unsigned long xxargs[1];
+};
+#endif /* (!__ASSEMBLY__) */
+
+#endif /* (defined(__sparc__) && defined(__arch64__))*/
+
+#ifndef __ASSEMBLY__
+
+#define TRACEREG_SZ    sizeof(struct pt_regs)
+#define STACKFRAME_SZ  sizeof(struct sparc_stackf)
+
+#define TRACEREG32_SZ  sizeof(struct pt_regs32)
+#define STACKFRAME32_SZ        sizeof(struct sparc_stackf32)
+
+#endif /* (!__ASSEMBLY__) */
+
+#define UREG_G0        0
+#define UREG_G1        1
+#define UREG_G2        2
+#define UREG_G3        3
+#define UREG_G4        4
+#define UREG_G5        5
+#define UREG_G6        6
+#define UREG_G7        7
+#define UREG_I0        8
+#define UREG_I1        9
+#define UREG_I2        10
+#define UREG_I3        11
+#define UREG_I4        12
+#define UREG_I5        13
+#define UREG_I6        14
+#define UREG_I7        15
+#define UREG_FP        UREG_I6
+#define UREG_RETPC     UREG_I7
+
+#if defined(__sparc__) && defined(__arch64__)
+/* 64 bit sparc */
+
+#ifndef __ASSEMBLY__
+
+
+#else /* __ASSEMBLY__ */
+/* For assembly code. */
+#define TRACEREG_SZ            0xa0
+#define STACKFRAME_SZ          0xc0
+
+#define TRACEREG32_SZ          0x50
+#define STACKFRAME32_SZ                0x60
+#endif /* __ASSEMBLY__ */
+
+#else /* (defined(__sparc__) && defined(__arch64__)) */
+
+/* 32 bit sparc */
+
+#ifndef __ASSEMBLY__
+
+
+#else /* (!__ASSEMBLY__) */
+/* For assembly code. */
+#define TRACEREG_SZ       0x50
+#define STACKFRAME_SZ     0x60
+#endif /* (!__ASSEMBLY__) */
+
+#endif /* (defined(__sparc__) && defined(__arch64__)) */
+
+
+/* These are for pt_regs. */
+#define PT_V9_G0     0x00
+#define PT_V9_G1     0x08
+#define PT_V9_G2     0x10
+#define PT_V9_G3     0x18
+#define PT_V9_G4     0x20
+#define PT_V9_G5     0x28
+#define PT_V9_G6     0x30
+#define PT_V9_G7     0x38
+#define PT_V9_I0     0x40
+#define PT_V9_I1     0x48
+#define PT_V9_I2     0x50
+#define PT_V9_I3     0x58
+#define PT_V9_I4     0x60
+#define PT_V9_I5     0x68
+#define PT_V9_I6     0x70
+#define PT_V9_FP     PT_V9_I6
+#define PT_V9_I7     0x78
+#define PT_V9_TSTATE 0x80
+#define PT_V9_TPC    0x88
+#define PT_V9_TNPC   0x90
+#define PT_V9_Y      0x98
+#define PT_V9_MAGIC  0x9c
+#define PT_TSTATE      PT_V9_TSTATE
+#define PT_TPC         PT_V9_TPC
+#define PT_TNPC                PT_V9_TNPC
+
+/* These for pt_regs32. */
+#define PT_PSR    0x0
+#define PT_PC     0x4
+#define PT_NPC    0x8
+#define PT_Y      0xc
+#define PT_G0     0x10
+#define PT_WIM    PT_G0
+#define PT_G1     0x14
+#define PT_G2     0x18
+#define PT_G3     0x1c
+#define PT_G4     0x20
+#define PT_G5     0x24
+#define PT_G6     0x28
+#define PT_G7     0x2c
+#define PT_I0     0x30
+#define PT_I1     0x34
+#define PT_I2     0x38
+#define PT_I3     0x3c
+#define PT_I4     0x40
+#define PT_I5     0x44
+#define PT_I6     0x48
+#define PT_FP     PT_I6
+#define PT_I7     0x4c
+
+/* Reg_window offsets */
+#define RW_V9_L0     0x00
+#define RW_V9_L1     0x08
+#define RW_V9_L2     0x10
+#define RW_V9_L3     0x18
+#define RW_V9_L4     0x20
+#define RW_V9_L5     0x28
+#define RW_V9_L6     0x30
+#define RW_V9_L7     0x38
+#define RW_V9_I0     0x40
+#define RW_V9_I1     0x48
+#define RW_V9_I2     0x50
+#define RW_V9_I3     0x58
+#define RW_V9_I4     0x60
+#define RW_V9_I5     0x68
+#define RW_V9_I6     0x70
+#define RW_V9_I7     0x78
+
+#define RW_L0     0x00
+#define RW_L1     0x04
+#define RW_L2     0x08
+#define RW_L3     0x0c
+#define RW_L4     0x10
+#define RW_L5     0x14
+#define RW_L6     0x18
+#define RW_L7     0x1c
+#define RW_I0     0x20
+#define RW_I1     0x24
+#define RW_I2     0x28
+#define RW_I3     0x2c
+#define RW_I4     0x30
+#define RW_I5     0x34
+#define RW_I6     0x38
+#define RW_I7     0x3c
+
+/* Stack_frame offsets */
+#define SF_V9_L0     0x00
+#define SF_V9_L1     0x08
+#define SF_V9_L2     0x10
+#define SF_V9_L3     0x18
+#define SF_V9_L4     0x20
+#define SF_V9_L5     0x28
+#define SF_V9_L6     0x30
+#define SF_V9_L7     0x38
+#define SF_V9_I0     0x40
+#define SF_V9_I1     0x48
+#define SF_V9_I2     0x50
+#define SF_V9_I3     0x58
+#define SF_V9_I4     0x60
+#define SF_V9_I5     0x68
+#define SF_V9_FP     0x70
+#define SF_V9_PC     0x78
+#define SF_V9_RETP   0x80
+#define SF_V9_XARG0  0x88
+#define SF_V9_XARG1  0x90
+#define SF_V9_XARG2  0x98
+#define SF_V9_XARG3  0xa0
+#define SF_V9_XARG4  0xa8
+#define SF_V9_XARG5  0xb0
+#define SF_V9_XXARG  0xb8
+
+#define SF_L0     0x00
+#define SF_L1     0x04
+#define SF_L2     0x08
+#define SF_L3     0x0c
+#define SF_L4     0x10
+#define SF_L5     0x14
+#define SF_L6     0x18
+#define SF_L7     0x1c
+#define SF_I0     0x20
+#define SF_I1     0x24
+#define SF_I2     0x28
+#define SF_I3     0x2c
+#define SF_I4     0x30
+#define SF_I5     0x34
+#define SF_FP     0x38
+#define SF_PC     0x3c
+#define SF_RETP   0x40
+#define SF_XARG0  0x44
+#define SF_XARG1  0x48
+#define SF_XARG2  0x4c
+#define SF_XARG3  0x50
+#define SF_XARG4  0x54
+#define SF_XARG5  0x58
+#define SF_XXARG  0x5c
+
+
+/* Stuff for the ptrace system call */
+#define PTRACE_SPARC_DETACH       11
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+#define PTRACE_READDATA           16
+#define PTRACE_WRITEDATA          17
+#define PTRACE_READTEXT           18
+#define PTRACE_WRITETEXT          19
+#define PTRACE_GETFPAREGS         20
+#define PTRACE_SETFPAREGS         21
+
+/* There are for debugging 64-bit processes, either from a 32 or 64 bit
+ * parent.  Thus their complements are for debugging 32-bit processes only.
+ */
+
+#define PTRACE_GETREGS64         22
+#define PTRACE_SETREGS64         23
+/* PTRACE_SYSCALL is 24 */
+#define PTRACE_GETFPREGS64       25
+#define PTRACE_SETFPREGS64       26
+
+#endif /* _UAPI__SPARC_PTRACE_H */
diff --git a/arch/sparc/include/uapi/asm/setup.h b/arch/sparc/include/uapi/asm/setup.h
new file mode 100644 (file)
index 0000000..5337684
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ *     Just a place holder. 
+ */
+
+#ifndef _UAPI_SPARC_SETUP_H
+#define _UAPI_SPARC_SETUP_H
+
+#if defined(__sparc__) && defined(__arch64__)
+# define COMMAND_LINE_SIZE 2048
+#else
+# define COMMAND_LINE_SIZE 256
+#endif
+
+
+#endif /* _UAPI_SPARC_SETUP_H */
diff --git a/arch/sparc/include/uapi/asm/sigcontext.h b/arch/sparc/include/uapi/asm/sigcontext.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/arch/sparc/include/uapi/asm/siginfo.h b/arch/sparc/include/uapi/asm/siginfo.h
new file mode 100644 (file)
index 0000000..2d9b79c
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _UAPI__SPARC_SIGINFO_H
+#define _UAPI__SPARC_SIGINFO_H
+
+#if defined(__sparc__) && defined(__arch64__)
+
+#define __ARCH_SI_PREAMBLE_SIZE        (4 * sizeof(int))
+#define __ARCH_SI_BAND_T int
+
+#endif /* defined(__sparc__) && defined(__arch64__) */
+
+
+#define __ARCH_SI_TRAPNO
+
+#include <asm-generic/siginfo.h>
+
+
+#define SI_NOINFO      32767           /* no information in siginfo_t */
+
+/*
+ * SIGEMT si_codes
+ */
+#define EMT_TAGOVF     (__SI_FAULT|1)  /* tag overflow */
+#define NSIGEMT                1
+
+#endif /* _UAPI__SPARC_SIGINFO_H */
diff --git a/arch/sparc/include/uapi/asm/signal.h b/arch/sparc/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..1a04189
--- /dev/null
@@ -0,0 +1,185 @@
+#ifndef _UAPI__SPARC_SIGNAL_H
+#define _UAPI__SPARC_SIGNAL_H
+
+#include <asm/sigcontext.h>
+#include <linux/compiler.h>
+
+
+/* On the Sparc the signal handlers get passed a 'sub-signal' code
+ * for certain signal types, which we document here.
+ */
+#define SIGHUP          1
+#define SIGINT          2
+#define SIGQUIT                 3
+#define SIGILL          4
+#define    SUBSIG_STACK       0
+#define    SUBSIG_ILLINST     2
+#define    SUBSIG_PRIVINST    3
+#define    SUBSIG_BADTRAP(t)  (0x80 + (t))
+
+#define SIGTRAP                 5
+#define SIGABRT                 6
+#define SIGIOT          6
+
+#define SIGEMT           7
+#define    SUBSIG_TAG    10
+
+#define SIGFPE          8
+#define    SUBSIG_FPDISABLED     0x400
+#define    SUBSIG_FPERROR        0x404
+#define    SUBSIG_FPINTOVFL      0x001
+#define    SUBSIG_FPSTSIG        0x002
+#define    SUBSIG_IDIVZERO       0x014
+#define    SUBSIG_FPINEXACT      0x0c4
+#define    SUBSIG_FPDIVZERO      0x0c8
+#define    SUBSIG_FPUNFLOW       0x0cc
+#define    SUBSIG_FPOPERROR      0x0d0
+#define    SUBSIG_FPOVFLOW       0x0d4
+
+#define SIGKILL                 9
+#define SIGBUS          10
+#define    SUBSIG_BUSTIMEOUT    1
+#define    SUBSIG_ALIGNMENT     2
+#define    SUBSIG_MISCERROR     5
+
+#define SIGSEGV                11
+#define    SUBSIG_NOMAPPING     3
+#define    SUBSIG_PROTECTION    4
+#define    SUBSIG_SEGERROR      5
+
+#define SIGSYS         12
+
+#define SIGPIPE                13
+#define SIGALRM                14
+#define SIGTERM                15
+#define SIGURG          16
+
+/* SunOS values which deviate from the Linux/i386 ones */
+#define SIGSTOP                17
+#define SIGTSTP                18
+#define SIGCONT                19
+#define SIGCHLD                20
+#define SIGTTIN                21
+#define SIGTTOU                22
+#define SIGIO          23
+#define SIGPOLL                SIGIO   /* SysV name for SIGIO */
+#define SIGXCPU                24
+#define SIGXFSZ                25
+#define SIGVTALRM      26
+#define SIGPROF                27
+#define SIGWINCH       28
+#define SIGLOST                29
+#define SIGPWR         SIGLOST
+#define SIGUSR1                30
+#define SIGUSR2                31
+
+/* Most things should be clean enough to redefine this at will, if care
+   is taken to make libc match.  */
+
+#define __OLD_NSIG     32
+#define __NEW_NSIG      64
+#ifdef __arch64__
+#define _NSIG_BPW       64
+#else
+#define _NSIG_BPW       32
+#endif
+#define _NSIG_WORDS     (__NEW_NSIG / _NSIG_BPW)
+
+#define SIGRTMIN       32
+#define SIGRTMAX       __NEW_NSIG
+
+#if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__)
+#define _NSIG                  __NEW_NSIG
+#define __new_sigset_t         sigset_t
+#define __new_sigaction                sigaction
+#define __new_sigaction32      sigaction32
+#define __old_sigset_t         old_sigset_t
+#define __old_sigaction                old_sigaction
+#define __old_sigaction32      old_sigaction32
+#else
+#define _NSIG                  __OLD_NSIG
+#define NSIG                   _NSIG
+#define __old_sigset_t         sigset_t
+#define __old_sigaction                sigaction
+#define __old_sigaction32      sigaction32
+#endif
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long __old_sigset_t;            /* at least 32 bits */
+
+typedef struct {
+       unsigned long sig[_NSIG_WORDS];
+} __new_sigset_t;
+
+/* A SunOS sigstack */
+struct sigstack {
+       /* XXX 32-bit pointers pinhead XXX */
+       char *the_stack;
+       int   cur_status;
+};
+
+/* Sigvec flags */
+#define _SV_SSTACK    1u    /* This signal handler should use sig-stack */
+#define _SV_INTR      2u    /* Sig return should not restart system call */
+#define _SV_RESET     4u    /* Set handler to SIG_DFL upon taken signal */
+#define _SV_IGNCHILD  8u    /* Do not send SIGCHLD */
+
+/*
+ * sa_flags values: SA_STACK is not currently supported, but will allow the
+ * usage of signal stacks by using the (now obsolete) sa_restorer field in
+ * the sigaction structure as a stack pointer. This is now possible due to
+ * the changes in signal handling. LBT 010493.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ */
+#define SA_NOCLDSTOP   _SV_IGNCHILD
+#define SA_STACK       _SV_SSTACK
+#define SA_ONSTACK     _SV_SSTACK
+#define SA_RESTART     _SV_INTR
+#define SA_ONESHOT     _SV_RESET
+#define SA_NODEFER     0x20u
+#define SA_NOCLDWAIT    0x100u
+#define SA_SIGINFO      0x200u
+
+#define SA_NOMASK      SA_NODEFER
+
+#define SIG_BLOCK          0x01        /* for blocking signals */
+#define SIG_UNBLOCK        0x02        /* for unblocking signals */
+#define SIG_SETMASK        0x04        /* for setting the signal mask */
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK     1
+#define SS_DISABLE     2
+
+#define MINSIGSTKSZ    4096
+#define SIGSTKSZ       16384
+
+
+#include <asm-generic/signal-defs.h>
+
+struct __new_sigaction {
+       __sighandler_t          sa_handler;
+       unsigned long           sa_flags;
+       __sigrestore_t          sa_restorer;  /* not used by Linux/SPARC yet */
+       __new_sigset_t          sa_mask;
+};
+
+struct __old_sigaction {
+       __sighandler_t          sa_handler;
+       __old_sigset_t          sa_mask;
+       unsigned long           sa_flags;
+       void                    (*sa_restorer)(void);  /* not used by Linux/SPARC yet */
+};
+
+typedef struct sigaltstack {
+       void                    __user *ss_sp;
+       int                     ss_flags;
+       size_t                  ss_size;
+} stack_t;
+
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* _UAPI__SPARC_SIGNAL_H */
diff --git a/arch/sparc/include/uapi/asm/termbits.h b/arch/sparc/include/uapi/asm/termbits.h
new file mode 100644 (file)
index 0000000..dd91642
--- /dev/null
@@ -0,0 +1,263 @@
+#ifndef _UAPI_SPARC_TERMBITS_H
+#define _UAPI_SPARC_TERMBITS_H
+
+#include <linux/posix_types.h>
+
+typedef unsigned char   cc_t;
+typedef unsigned int    speed_t;
+
+#if defined(__sparc__) && defined(__arch64__)
+typedef unsigned int    tcflag_t;
+#else
+typedef unsigned long   tcflag_t;
+#endif
+
+#define NCC 8
+struct termio {
+       unsigned short c_iflag;         /* input mode flags */
+       unsigned short c_oflag;         /* output mode flags */
+       unsigned short c_cflag;         /* control mode flags */
+       unsigned short c_lflag;         /* local mode flags */
+       unsigned char c_line;           /* line discipline */
+       unsigned char c_cc[NCC];        /* control characters */
+};
+
+#define NCCS 17
+struct termios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+#ifndef __KERNEL__
+       cc_t c_cc[NCCS];                /* control characters */
+#else
+       cc_t c_cc[NCCS+2];      /* kernel needs 2 more to hold vmin/vtime */
+#define SIZEOF_USER_TERMIOS sizeof (struct termios) - (2*sizeof (cc_t))
+#endif
+};
+
+struct termios2 {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS+2];              /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS+2];              /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
+/* c_cc characters */
+#define VINTR    0
+#define VQUIT    1
+#define VERASE   2
+#define VKILL    3
+#define VEOF     4
+#define VEOL     5
+#define VEOL2    6
+#define VSWTC    7
+#define VSTART   8
+#define VSTOP    9
+
+
+
+#define VSUSP    10
+#define VDSUSP   11  /* SunOS POSIX nicety I do believe... */
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE  14
+#define VLNEXT   15
+
+/* Kernel keeps vmin/vtime separated, user apps assume vmin/vtime is
+ * shared with eof/eol
+ */
+#ifndef __KERNEL__
+#define VMIN     VEOF
+#define VTIME    VEOL
+#endif
+
+/* c_iflag bits */
+#define IGNBRK 0x00000001
+#define BRKINT 0x00000002
+#define IGNPAR 0x00000004
+#define PARMRK 0x00000008
+#define INPCK  0x00000010
+#define ISTRIP 0x00000020
+#define INLCR  0x00000040
+#define IGNCR  0x00000080
+#define ICRNL  0x00000100
+#define IUCLC  0x00000200
+#define IXON   0x00000400
+#define IXANY  0x00000800
+#define IXOFF  0x00001000
+#define IMAXBEL        0x00002000
+#define IUTF8   0x00004000
+
+/* c_oflag bits */
+#define OPOST  0x00000001
+#define OLCUC  0x00000002
+#define ONLCR  0x00000004
+#define OCRNL  0x00000008
+#define ONOCR  0x00000010
+#define ONLRET 0x00000020
+#define OFILL  0x00000040
+#define OFDEL  0x00000080
+#define NLDLY  0x00000100
+#define   NL0  0x00000000
+#define   NL1  0x00000100
+#define CRDLY  0x00000600
+#define   CR0  0x00000000
+#define   CR1  0x00000200
+#define   CR2  0x00000400
+#define   CR3  0x00000600
+#define TABDLY 0x00001800
+#define   TAB0 0x00000000
+#define   TAB1 0x00000800
+#define   TAB2 0x00001000
+#define   TAB3 0x00001800
+#define   XTABS        0x00001800
+#define BSDLY  0x00002000
+#define   BS0  0x00000000
+#define   BS1  0x00002000
+#define VTDLY  0x00004000
+#define   VT0  0x00000000
+#define   VT1  0x00004000
+#define FFDLY  0x00008000
+#define   FF0  0x00000000
+#define   FF1  0x00008000
+#define PAGEOUT 0x00010000  /* SUNOS specific */
+#define WRAP    0x00020000  /* SUNOS specific */
+
+/* c_cflag bit meaning */
+#define CBAUD    0x0000100f
+#define  B0      0x00000000   /* hang up */
+#define  B50     0x00000001
+#define  B75     0x00000002
+#define  B110    0x00000003
+#define  B134    0x00000004
+#define  B150    0x00000005
+#define  B200    0x00000006
+#define  B300    0x00000007
+#define  B600    0x00000008
+#define  B1200   0x00000009
+#define  B1800   0x0000000a
+#define  B2400   0x0000000b
+#define  B4800   0x0000000c
+#define  B9600   0x0000000d
+#define  B19200          0x0000000e
+#define  B38400          0x0000000f
+#define EXTA      B19200
+#define EXTB      B38400
+#define  CSIZE    0x00000030
+#define   CS5    0x00000000
+#define   CS6    0x00000010
+#define   CS7    0x00000020
+#define   CS8    0x00000030
+#define CSTOPB   0x00000040
+#define CREAD    0x00000080
+#define PARENB   0x00000100
+#define PARODD   0x00000200
+#define HUPCL    0x00000400
+#define CLOCAL   0x00000800
+#define CBAUDEX   0x00001000
+/* We'll never see these speeds with the Zilogs, but for completeness... */
+#define  BOTHER   0x00001000
+#define  B57600   0x00001001
+#define  B115200  0x00001002
+#define  B230400  0x00001003
+#define  B460800  0x00001004
+/* This is what we can do with the Zilogs. */
+#define  B76800   0x00001005
+/* This is what we can do with the SAB82532. */
+#define  B153600  0x00001006
+#define  B307200  0x00001007
+#define  B614400  0x00001008
+#define  B921600  0x00001009
+/* And these are the rest... */
+#define  B500000  0x0000100a
+#define  B576000  0x0000100b
+#define B1000000  0x0000100c
+#define B1152000  0x0000100d
+#define B1500000  0x0000100e
+#define B2000000  0x0000100f
+/* These have totally bogus values and nobody uses them
+   so far. Later on we'd have to use say 0x10000x and
+   adjust CBAUD constant and drivers accordingly.
+#define B2500000  0x00001010
+#define B3000000  0x00001011
+#define B3500000  0x00001012
+#define B4000000  0x00001013  */
+#define CIBAUD   0x100f0000  /* input baud rate (not used) */
+#define CMSPAR   0x40000000  /* mark or space (stick) parity */
+#define CRTSCTS          0x80000000  /* flow control */
+
+#define IBSHIFT          16            /* Shift from CBAUD to CIBAUD */
+
+/* c_lflag bits */
+#define ISIG   0x00000001
+#define ICANON 0x00000002
+#define XCASE  0x00000004
+#define ECHO   0x00000008
+#define ECHOE  0x00000010
+#define ECHOK  0x00000020
+#define ECHONL 0x00000040
+#define NOFLSH 0x00000080
+#define TOSTOP 0x00000100
+#define ECHOCTL        0x00000200
+#define ECHOPRT        0x00000400
+#define ECHOKE 0x00000800
+#define DEFECHO 0x00001000  /* SUNOS thing, what is it? */
+#define FLUSHO 0x00002000
+#define PENDIN 0x00004000
+#define IEXTEN 0x00008000
+#define EXTPROC        0x00010000
+
+/* modem lines */
+#define TIOCM_LE       0x001
+#define TIOCM_DTR      0x002
+#define TIOCM_RTS      0x004
+#define TIOCM_ST       0x008
+#define TIOCM_SR       0x010
+#define TIOCM_CTS      0x020
+#define TIOCM_CAR      0x040
+#define TIOCM_RNG      0x080
+#define TIOCM_DSR      0x100
+#define TIOCM_CD       TIOCM_CAR
+#define TIOCM_RI       TIOCM_RNG
+#define TIOCM_OUT1     0x2000
+#define TIOCM_OUT2     0x4000
+#define TIOCM_LOOP     0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
+
+
+/* tcflow() and TCXONC use these */
+#define        TCOOFF          0
+#define        TCOON           1
+#define        TCIOFF          2
+#define        TCION           3
+
+/* tcflush() and TCFLSH use these */
+#define        TCIFLUSH        0
+#define        TCOFLUSH        1
+#define        TCIOFLUSH       2
+
+/* tcsetattr uses these */
+#define        TCSANOW         0
+#define        TCSADRAIN       1
+#define        TCSAFLUSH       2
+
+#endif /* _UAPI_SPARC_TERMBITS_H */
diff --git a/arch/sparc/include/uapi/asm/termios.h b/arch/sparc/include/uapi/asm/termios.h
new file mode 100644 (file)
index 0000000..ea6f09e
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef _UAPI_SPARC_TERMIOS_H
+#define _UAPI_SPARC_TERMIOS_H
+
+#include <asm/ioctls.h>
+#include <asm/termbits.h>
+
+#if defined(__KERNEL__) || defined(__DEFINE_BSD_TERMIOS)
+struct sgttyb {
+       char    sg_ispeed;
+       char    sg_ospeed;
+       char    sg_erase;
+       char    sg_kill;
+       short   sg_flags;
+};
+
+struct tchars {
+       char    t_intrc;
+       char    t_quitc;
+       char    t_startc;
+       char    t_stopc;
+       char    t_eofc;
+       char    t_brkc;
+};
+
+struct ltchars {
+       char    t_suspc;
+       char    t_dsuspc;
+       char    t_rprntc;
+       char    t_flushc;
+       char    t_werasc;
+       char    t_lnextc;
+};
+#endif /* __KERNEL__ */
+
+struct winsize {
+       unsigned short ws_row;
+       unsigned short ws_col;
+       unsigned short ws_xpixel;
+       unsigned short ws_ypixel;
+};
+
+
+#endif /* _UAPI_SPARC_TERMIOS_H */
diff --git a/arch/sparc/include/uapi/asm/traps.h b/arch/sparc/include/uapi/asm/traps.h
new file mode 100644 (file)
index 0000000..a4eceac
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * traps.h:  Format of entries for the Sparc trap table.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _UAPI_SPARC_TRAPS_H
+#define _UAPI_SPARC_TRAPS_H
+
+#define NUM_SPARC_TRAPS  255
+
+#ifndef __ASSEMBLY__
+#endif /* !(__ASSEMBLY__) */
+
+/* For patching the trap table at boot time, we need to know how to
+ * form various common Sparc instructions.  Thus these macros...
+ */
+
+#define SPARC_MOV_CONST_L3(const) (0xa6102000 | (const&0xfff))
+
+/* The following assumes that the branch lies before the place we
+ * are branching to.  This is the case for a trap vector...
+ * You have been warned.
+ */
+#define SPARC_BRANCH(dest_addr, inst_addr) \
+          (0x10800000 | (((dest_addr-inst_addr)>>2)&0x3fffff))
+
+#define SPARC_RD_PSR_L0  (0xa1480000)
+#define SPARC_RD_WIM_L3  (0xa7500000)
+#define SPARC_NOP (0x01000000)
+
+/* Various interesting trap levels. */
+/* First, hardware traps. */
+#define SP_TRAP_TFLT    0x1          /* Text fault */
+#define SP_TRAP_II      0x2          /* Illegal Instruction */
+#define SP_TRAP_PI      0x3          /* Privileged Instruction */
+#define SP_TRAP_FPD     0x4          /* Floating Point Disabled */
+#define SP_TRAP_WOVF    0x5          /* Window Overflow */
+#define SP_TRAP_WUNF    0x6          /* Window Underflow */
+#define SP_TRAP_MNA     0x7          /* Memory Address Unaligned */
+#define SP_TRAP_FPE     0x8          /* Floating Point Exception */
+#define SP_TRAP_DFLT    0x9          /* Data Fault */
+#define SP_TRAP_TOF     0xa          /* Tag Overflow */
+#define SP_TRAP_WDOG    0xb          /* Watchpoint Detected */
+#define SP_TRAP_IRQ1    0x11         /* IRQ level 1 */
+#define SP_TRAP_IRQ2    0x12         /* IRQ level 2 */
+#define SP_TRAP_IRQ3    0x13         /* IRQ level 3 */
+#define SP_TRAP_IRQ4    0x14         /* IRQ level 4 */
+#define SP_TRAP_IRQ5    0x15         /* IRQ level 5 */
+#define SP_TRAP_IRQ6    0x16         /* IRQ level 6 */
+#define SP_TRAP_IRQ7    0x17         /* IRQ level 7 */
+#define SP_TRAP_IRQ8    0x18         /* IRQ level 8 */
+#define SP_TRAP_IRQ9    0x19         /* IRQ level 9 */
+#define SP_TRAP_IRQ10   0x1a         /* IRQ level 10 */
+#define SP_TRAP_IRQ11   0x1b         /* IRQ level 11 */
+#define SP_TRAP_IRQ12   0x1c         /* IRQ level 12 */
+#define SP_TRAP_IRQ13   0x1d         /* IRQ level 13 */
+#define SP_TRAP_IRQ14   0x1e         /* IRQ level 14 */
+#define SP_TRAP_IRQ15   0x1f         /* IRQ level 15 Non-maskable */
+#define SP_TRAP_RACC    0x20         /* Register Access Error ??? */
+#define SP_TRAP_IACC    0x21         /* Instruction Access Error */
+#define SP_TRAP_CPDIS   0x24         /* Co-Processor Disabled */
+#define SP_TRAP_BADFL   0x25         /* Unimplemented Flush Instruction */
+#define SP_TRAP_CPEXP   0x28         /* Co-Processor Exception */
+#define SP_TRAP_DACC    0x29         /* Data Access Error */
+#define SP_TRAP_DIVZ    0x2a         /* Divide By Zero */
+#define SP_TRAP_DSTORE  0x2b         /* Data Store Error ??? */
+#define SP_TRAP_DMM     0x2c         /* Data Access MMU Miss ??? */
+#define SP_TRAP_IMM     0x3c         /* Instruction Access MMU Miss ??? */
+
+/* Now the Software Traps... */
+#define SP_TRAP_SUNOS   0x80         /* SunOS System Call */
+#define SP_TRAP_SBPT    0x81         /* Software Breakpoint */
+#define SP_TRAP_SDIVZ   0x82         /* Software Divide-by-Zero trap */
+#define SP_TRAP_FWIN    0x83         /* Flush Windows */
+#define SP_TRAP_CWIN    0x84         /* Clean Windows */
+#define SP_TRAP_RCHK    0x85         /* Range Check */
+#define SP_TRAP_FUNA    0x86         /* Fix Unaligned Access */
+#define SP_TRAP_IOWFL   0x87         /* Integer Overflow */
+#define SP_TRAP_SOLARIS 0x88         /* Solaris System Call */
+#define SP_TRAP_NETBSD  0x89         /* NetBSD System Call */
+#define SP_TRAP_LINUX   0x90         /* Linux System Call */
+
+/* Names used for compatibility with SunOS */
+#define ST_SYSCALL              0x00
+#define ST_BREAKPOINT           0x01
+#define ST_DIV0                 0x02
+#define ST_FLUSH_WINDOWS        0x03
+#define ST_CLEAN_WINDOWS        0x04
+#define ST_RANGE_CHECK          0x05
+#define ST_FIX_ALIGN            0x06
+#define ST_INT_OVERFLOW         0x07
+
+/* Special traps... */
+#define SP_TRAP_KBPT1   0xfe         /* KADB/PROM Breakpoint one */
+#define SP_TRAP_KBPT2   0xff         /* KADB/PROM Breakpoint two */
+
+/* Handy Macros */
+/* Is this a trap we never expect to get? */
+#define BAD_TRAP_P(level) \
+        ((level > SP_TRAP_WDOG && level < SP_TRAP_IRQ1) || \
+        (level > SP_TRAP_IACC && level < SP_TRAP_CPDIS) || \
+        (level > SP_TRAP_BADFL && level < SP_TRAP_CPEXP) || \
+        (level > SP_TRAP_DMM && level < SP_TRAP_IMM) || \
+        (level > SP_TRAP_IMM && level < SP_TRAP_SUNOS) || \
+        (level > SP_TRAP_LINUX && level < SP_TRAP_KBPT1))
+
+/* Is this a Hardware trap? */
+#define HW_TRAP_P(level) ((level > 0) && (level < SP_TRAP_SUNOS))
+
+/* Is this a Software trap? */
+#define SW_TRAP_P(level) ((level >= SP_TRAP_SUNOS) && (level <= SP_TRAP_KBPT2))
+
+/* Is this a system call for some OS we know about? */
+#define SCALL_TRAP_P(level) ((level == SP_TRAP_SUNOS) || \
+                            (level == SP_TRAP_SOLARIS) || \
+                            (level == SP_TRAP_NETBSD) || \
+                            (level == SP_TRAP_LINUX))
+
+#endif /* _UAPI_SPARC_TRAPS_H */
diff --git a/arch/sparc/include/uapi/asm/unistd.h b/arch/sparc/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..8974ef7
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+ * System calls under the Sparc.
+ *
+ * Don't be scared by the ugly clobbers, it is the only way I can
+ * think of right now to force the arguments into fixed registers
+ * before the trap into the system call with gcc 'asm' statements.
+ *
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
+ *
+ * SunOS compatibility based upon preliminary work which is:
+ *
+ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
+ */
+#ifndef _UAPI_SPARC_UNISTD_H
+#define _UAPI_SPARC_UNISTD_H
+
+#ifndef __32bit_syscall_numbers__
+#ifndef __arch64__
+#define __32bit_syscall_numbers__
+#endif
+#endif
+
+#define __NR_restart_syscall      0 /* Linux Specific                             */
+#define __NR_exit                 1 /* Common                                      */
+#define __NR_fork                 2 /* Common                                      */
+#define __NR_read                 3 /* Common                                      */
+#define __NR_write                4 /* Common                                      */
+#define __NR_open                 5 /* Common                                      */
+#define __NR_close                6 /* Common                                      */
+#define __NR_wait4                7 /* Common                                      */
+#define __NR_creat                8 /* Common                                      */
+#define __NR_link                 9 /* Common                                      */
+#define __NR_unlink              10 /* Common                                      */
+#define __NR_execv               11 /* SunOS Specific                              */
+#define __NR_chdir               12 /* Common                                      */
+#define __NR_chown              13 /* Common                                      */
+#define __NR_mknod               14 /* Common                                      */
+#define __NR_chmod               15 /* Common                                      */
+#define __NR_lchown              16 /* Common                                      */
+#define __NR_brk                 17 /* Common                                      */
+#define __NR_perfctr             18 /* Performance counter operations              */
+#define __NR_lseek               19 /* Common                                      */
+#define __NR_getpid              20 /* Common                                      */
+#define __NR_capget             21 /* Linux Specific                              */
+#define __NR_capset             22 /* Linux Specific                              */
+#define __NR_setuid              23 /* Implemented via setreuid in SunOS           */
+#define __NR_getuid              24 /* Common                                      */
+#define __NR_vmsplice           25 /* ENOSYS under SunOS                          */
+#define __NR_ptrace              26 /* Common                                      */
+#define __NR_alarm               27 /* Implemented via setitimer in SunOS          */
+#define __NR_sigaltstack        28 /* Common                                      */
+#define __NR_pause               29 /* Is sigblock(0)->sigpause() in SunOS         */
+#define __NR_utime               30 /* Implemented via utimes() under SunOS        */
+#ifdef __32bit_syscall_numbers__
+#define __NR_lchown32            31 /* Linux sparc32 specific                      */
+#define __NR_fchown32            32 /* Linux sparc32 specific                      */
+#endif
+#define __NR_access              33 /* Common                                      */
+#define __NR_nice                34 /* Implemented via get/setpriority() in SunOS  */
+#ifdef __32bit_syscall_numbers__
+#define __NR_chown32             35 /* Linux sparc32 specific                      */
+#endif
+#define __NR_sync                36 /* Common                                      */
+#define __NR_kill                37 /* Common                                      */
+#define __NR_stat                38 /* Common                                      */
+#define __NR_sendfile           39 /* Linux Specific                              */
+#define __NR_lstat               40 /* Common                                      */
+#define __NR_dup                 41 /* Common                                      */
+#define __NR_pipe                42 /* Common                                      */
+#define __NR_times               43 /* Implemented via getrusage() in SunOS        */
+#ifdef __32bit_syscall_numbers__
+#define __NR_getuid32            44 /* Linux sparc32 specific                      */
+#endif
+#define __NR_umount2             45 /* Linux Specific                              */
+#define __NR_setgid              46 /* Implemented via setregid() in SunOS         */
+#define __NR_getgid              47 /* Common                                      */
+#define __NR_signal              48 /* Implemented via sigvec() in SunOS           */
+#define __NR_geteuid             49 /* SunOS calls getuid()                        */
+#define __NR_getegid             50 /* SunOS calls getgid()                        */
+#define __NR_acct                51 /* Common                                      */
+#ifdef __32bit_syscall_numbers__
+#define __NR_getgid32            53 /* Linux sparc32 specific                      */
+#else
+#define __NR_memory_ordering    52 /* Linux Specific                              */
+#endif
+#define __NR_ioctl               54 /* Common                                      */
+#define __NR_reboot              55 /* Common                                      */
+#ifdef __32bit_syscall_numbers__
+#define __NR_mmap2              56 /* Linux sparc32 Specific                      */
+#endif
+#define __NR_symlink             57 /* Common                                      */
+#define __NR_readlink            58 /* Common                                      */
+#define __NR_execve              59 /* Common                                      */
+#define __NR_umask               60 /* Common                                      */
+#define __NR_chroot              61 /* Common                                      */
+#define __NR_fstat               62 /* Common                                      */
+#define __NR_fstat64            63 /* Linux Specific                              */
+#define __NR_getpagesize         64 /* Common                                      */
+#define __NR_msync               65 /* Common in newer 1.3.x revs...               */
+#define __NR_vfork               66 /* Common                                      */
+#define __NR_pread64             67 /* Linux Specific                              */
+#define __NR_pwrite64            68 /* Linux Specific                              */
+#ifdef __32bit_syscall_numbers__
+#define __NR_geteuid32           69 /* Linux sparc32, sbrk under SunOS             */
+#define __NR_getegid32           70 /* Linux sparc32, sstk under SunOS             */
+#endif
+#define __NR_mmap                71 /* Common                                      */
+#ifdef __32bit_syscall_numbers__
+#define __NR_setreuid32          72 /* Linux sparc32, vadvise under SunOS          */
+#endif
+#define __NR_munmap              73 /* Common                                      */
+#define __NR_mprotect            74 /* Common                                      */
+#define __NR_madvise             75 /* Common                                      */
+#define __NR_vhangup             76 /* Common                                      */
+#ifdef __32bit_syscall_numbers__
+#define __NR_truncate64                 77 /* Linux sparc32 Specific                      */
+#endif
+#define __NR_mincore             78 /* Common                                      */
+#define __NR_getgroups           79 /* Common                                      */
+#define __NR_setgroups           80 /* Common                                      */
+#define __NR_getpgrp             81 /* Common                                      */
+#ifdef __32bit_syscall_numbers__
+#define __NR_setgroups32         82 /* Linux sparc32, setpgrp under SunOS          */
+#endif
+#define __NR_setitimer           83 /* Common                                      */
+#ifdef __32bit_syscall_numbers__
+#define __NR_ftruncate64        84 /* Linux sparc32 Specific                      */
+#endif
+#define __NR_swapon              85 /* Common                                      */
+#define __NR_getitimer           86 /* Common                                      */
+#ifdef __32bit_syscall_numbers__
+#define __NR_setuid32            87 /* Linux sparc32, gethostname under SunOS      */
+#endif
+#define __NR_sethostname         88 /* Common                                      */
+#ifdef __32bit_syscall_numbers__
+#define __NR_setgid32            89 /* Linux sparc32, getdtablesize under SunOS    */
+#endif
+#define __NR_dup2                90 /* Common                                      */
+#ifdef __32bit_syscall_numbers__
+#define __NR_setfsuid32          91 /* Linux sparc32, getdopt under SunOS          */
+#endif
+#define __NR_fcntl               92 /* Common                                      */
+#define __NR_select              93 /* Common                                      */
+#ifdef __32bit_syscall_numbers__
+#define __NR_setfsgid32          94 /* Linux sparc32, setdopt under SunOS          */
+#endif
+#define __NR_fsync               95 /* Common                                      */
+#define __NR_setpriority         96 /* Common                                      */
+#define __NR_socket              97 /* Common                                      */
+#define __NR_connect             98 /* Common                                      */
+#define __NR_accept              99 /* Common                                      */
+#define __NR_getpriority        100 /* Common                                      */
+#define __NR_rt_sigreturn       101 /* Linux Specific                              */
+#define __NR_rt_sigaction       102 /* Linux Specific                              */
+#define __NR_rt_sigprocmask     103 /* Linux Specific                              */
+#define __NR_rt_sigpending      104 /* Linux Specific                              */
+#define __NR_rt_sigtimedwait    105 /* Linux Specific                              */
+#define __NR_rt_sigqueueinfo    106 /* Linux Specific                              */
+#define __NR_rt_sigsuspend      107 /* Linux Specific                              */
+#ifdef __32bit_syscall_numbers__
+#define __NR_setresuid32        108 /* Linux Specific, sigvec under SunOS         */
+#define __NR_getresuid32        109 /* Linux Specific, sigblock under SunOS       */
+#define __NR_setresgid32        110 /* Linux Specific, sigsetmask under SunOS     */
+#define __NR_getresgid32        111 /* Linux Specific, sigpause under SunOS       */
+#define __NR_setregid32         112 /* Linux sparc32, sigstack under SunOS         */
+#else
+#define __NR_setresuid          108 /* Linux Specific, sigvec under SunOS         */
+#define __NR_getresuid          109 /* Linux Specific, sigblock under SunOS       */
+#define __NR_setresgid          110 /* Linux Specific, sigsetmask under SunOS     */
+#define __NR_getresgid          111 /* Linux Specific, sigpause under SunOS       */
+#endif
+#define __NR_recvmsg            113 /* Common                                      */
+#define __NR_sendmsg            114 /* Common                                      */
+#ifdef __32bit_syscall_numbers__
+#define __NR_getgroups32        115 /* Linux sparc32, vtrace under SunOS           */
+#endif
+#define __NR_gettimeofday       116 /* Common                                      */
+#define __NR_getrusage          117 /* Common                                      */
+#define __NR_getsockopt         118 /* Common                                      */
+#define __NR_getcwd            119 /* Linux Specific                              */
+#define __NR_readv              120 /* Common                                      */
+#define __NR_writev             121 /* Common                                      */
+#define __NR_settimeofday       122 /* Common                                      */
+#define __NR_fchown             123 /* Common                                      */
+#define __NR_fchmod             124 /* Common                                      */
+#define __NR_recvfrom           125 /* Common                                      */
+#define __NR_setreuid           126 /* Common                                      */
+#define __NR_setregid           127 /* Common                                      */
+#define __NR_rename             128 /* Common                                      */
+#define __NR_truncate           129 /* Common                                      */
+#define __NR_ftruncate          130 /* Common                                      */
+#define __NR_flock              131 /* Common                                      */
+#define __NR_lstat64           132 /* Linux Specific                              */
+#define __NR_sendto             133 /* Common                                      */
+#define __NR_shutdown           134 /* Common                                      */
+#define __NR_socketpair         135 /* Common                                      */
+#define __NR_mkdir              136 /* Common                                      */
+#define __NR_rmdir              137 /* Common                                      */
+#define __NR_utimes             138 /* SunOS Specific                              */
+#define __NR_stat64            139 /* Linux Specific                              */
+#define __NR_sendfile64         140 /* adjtime under SunOS                         */
+#define __NR_getpeername        141 /* Common                                      */
+#define __NR_futex              142 /* gethostid under SunOS                       */
+#define __NR_gettid             143 /* ENOSYS under SunOS                          */
+#define __NR_getrlimit         144 /* Common                                      */
+#define __NR_setrlimit          145 /* Common                                      */
+#define __NR_pivot_root                146 /* Linux Specific, killpg under SunOS          */
+#define __NR_prctl             147 /* ENOSYS under SunOS                          */
+#define __NR_pciconfig_read    148 /* ENOSYS under SunOS                          */
+#define __NR_pciconfig_write   149 /* ENOSYS under SunOS                          */
+#define __NR_getsockname        150 /* Common                                      */
+#define __NR_inotify_init       151 /* Linux specific                              */
+#define __NR_inotify_add_watch  152 /* Linux specific                              */
+#define __NR_poll               153 /* Common                                      */
+#define __NR_getdents64                154 /* Linux specific                              */
+#ifdef __32bit_syscall_numbers__
+#define __NR_fcntl64           155 /* Linux sparc32 Specific                      */
+#endif
+#define __NR_inotify_rm_watch   156 /* Linux specific                             */
+#define __NR_statfs             157 /* Common                                      */
+#define __NR_fstatfs            158 /* Common                                      */
+#define __NR_umount             159 /* Common                                      */
+#define __NR_sched_set_affinity 160 /* Linux specific, async_daemon under SunOS    */
+#define __NR_sched_get_affinity 161 /* Linux specific, getfh under SunOS           */
+#define __NR_getdomainname      162 /* SunOS Specific                              */
+#define __NR_setdomainname      163 /* Common                                      */
+#ifndef __32bit_syscall_numbers__
+#define __NR_utrap_install     164 /* SYSV ABI/v9 required                        */
+#endif
+#define __NR_quotactl           165 /* Common                                      */
+#define __NR_set_tid_address    166 /* Linux specific, exportfs under SunOS        */
+#define __NR_mount              167 /* Common                                      */
+#define __NR_ustat              168 /* Common                                      */
+#define __NR_setxattr           169 /* SunOS: semsys                               */
+#define __NR_lsetxattr          170 /* SunOS: msgsys                               */
+#define __NR_fsetxattr          171 /* SunOS: shmsys                               */
+#define __NR_getxattr           172 /* SunOS: auditsys                             */
+#define __NR_lgetxattr          173 /* SunOS: rfssys                               */
+#define __NR_getdents           174 /* Common                                      */
+#define __NR_setsid             175 /* Common                                      */
+#define __NR_fchdir             176 /* Common                                      */
+#define __NR_fgetxattr          177 /* SunOS: fchroot                              */
+#define __NR_listxattr          178 /* SunOS: vpixsys                              */
+#define __NR_llistxattr         179 /* SunOS: aioread                              */
+#define __NR_flistxattr         180 /* SunOS: aiowrite                             */
+#define __NR_removexattr        181 /* SunOS: aiowait                              */
+#define __NR_lremovexattr       182 /* SunOS: aiocancel                            */
+#define __NR_sigpending         183 /* Common                                      */
+#define __NR_query_module      184 /* Linux Specific                              */
+#define __NR_setpgid            185 /* Common                                      */
+#define __NR_fremovexattr       186 /* SunOS: pathconf                             */
+#define __NR_tkill              187 /* SunOS: fpathconf                            */
+#define __NR_exit_group                188 /* Linux specific, sysconf undef SunOS         */
+#define __NR_uname              189 /* Linux Specific                              */
+#define __NR_init_module        190 /* Linux Specific                              */
+#define __NR_personality        191 /* Linux Specific                              */
+#define __NR_remap_file_pages   192 /* Linux Specific                              */
+#define __NR_epoll_create       193 /* Linux Specific                              */
+#define __NR_epoll_ctl          194 /* Linux Specific                              */
+#define __NR_epoll_wait         195 /* Linux Specific                              */
+#define __NR_ioprio_set         196 /* Linux Specific                              */
+#define __NR_getppid            197 /* Linux Specific                              */
+#define __NR_sigaction          198 /* Linux Specific                              */
+#define __NR_sgetmask           199 /* Linux Specific                              */
+#define __NR_ssetmask           200 /* Linux Specific                              */
+#define __NR_sigsuspend         201 /* Linux Specific                              */
+#define __NR_oldlstat           202 /* Linux Specific                              */
+#define __NR_uselib             203 /* Linux Specific                              */
+#define __NR_readdir            204 /* Linux Specific                              */
+#define __NR_readahead          205 /* Linux Specific                              */
+#define __NR_socketcall         206 /* Linux Specific                              */
+#define __NR_syslog             207 /* Linux Specific                              */
+#define __NR_lookup_dcookie     208 /* Linux Specific                              */
+#define __NR_fadvise64          209 /* Linux Specific                              */
+#define __NR_fadvise64_64       210 /* Linux Specific                              */
+#define __NR_tgkill             211 /* Linux Specific                              */
+#define __NR_waitpid            212 /* Linux Specific                              */
+#define __NR_swapoff            213 /* Linux Specific                              */
+#define __NR_sysinfo            214 /* Linux Specific                              */
+#define __NR_ipc                215 /* Linux Specific                              */
+#define __NR_sigreturn          216 /* Linux Specific                              */
+#define __NR_clone              217 /* Linux Specific                              */
+#define __NR_ioprio_get         218 /* Linux Specific                              */
+#define __NR_adjtimex           219 /* Linux Specific                              */
+#define __NR_sigprocmask        220 /* Linux Specific                              */
+#define __NR_create_module      221 /* Linux Specific                              */
+#define __NR_delete_module      222 /* Linux Specific                              */
+#define __NR_get_kernel_syms    223 /* Linux Specific                              */
+#define __NR_getpgid            224 /* Linux Specific                              */
+#define __NR_bdflush            225 /* Linux Specific                              */
+#define __NR_sysfs              226 /* Linux Specific                              */
+#define __NR_afs_syscall        227 /* Linux Specific                              */
+#define __NR_setfsuid           228 /* Linux Specific                              */
+#define __NR_setfsgid           229 /* Linux Specific                              */
+#define __NR__newselect         230 /* Linux Specific                              */
+#ifdef __32bit_syscall_numbers__
+#define __NR_time               231 /* Linux Specific                              */
+#else
+#endif
+#define __NR_splice             232 /* Linux Specific                              */
+#define __NR_stime              233 /* Linux Specific                              */
+#define __NR_statfs64           234 /* Linux Specific                              */
+#define __NR_fstatfs64          235 /* Linux Specific                              */
+#define __NR__llseek            236 /* Linux Specific                              */
+#define __NR_mlock              237
+#define __NR_munlock            238
+#define __NR_mlockall           239
+#define __NR_munlockall         240
+#define __NR_sched_setparam     241
+#define __NR_sched_getparam     242
+#define __NR_sched_setscheduler 243
+#define __NR_sched_getscheduler 244
+#define __NR_sched_yield        245
+#define __NR_sched_get_priority_max 246
+#define __NR_sched_get_priority_min 247
+#define __NR_sched_rr_get_interval  248
+#define __NR_nanosleep          249
+#define __NR_mremap             250
+#define __NR__sysctl            251
+#define __NR_getsid             252
+#define __NR_fdatasync          253
+#define __NR_nfsservctl         254
+#define __NR_sync_file_range   255
+#define __NR_clock_settime     256
+#define __NR_clock_gettime     257
+#define __NR_clock_getres      258
+#define __NR_clock_nanosleep   259
+#define __NR_sched_getaffinity 260
+#define __NR_sched_setaffinity 261
+#define __NR_timer_settime     262
+#define __NR_timer_gettime     263
+#define __NR_timer_getoverrun  264
+#define __NR_timer_delete      265
+#define __NR_timer_create      266
+/* #define __NR_vserver                267 Reserved for VSERVER */
+#define __NR_io_setup          268
+#define __NR_io_destroy                269
+#define __NR_io_submit         270
+#define __NR_io_cancel         271
+#define __NR_io_getevents      272
+#define __NR_mq_open           273
+#define __NR_mq_unlink         274
+#define __NR_mq_timedsend      275
+#define __NR_mq_timedreceive   276
+#define __NR_mq_notify         277
+#define __NR_mq_getsetattr     278
+#define __NR_waitid            279
+#define __NR_tee               280
+#define __NR_add_key           281
+#define __NR_request_key       282
+#define __NR_keyctl            283
+#define __NR_openat            284
+#define __NR_mkdirat           285
+#define __NR_mknodat           286
+#define __NR_fchownat          287
+#define __NR_futimesat         288
+#define __NR_fstatat64         289
+#define __NR_unlinkat          290
+#define __NR_renameat          291
+#define __NR_linkat            292
+#define __NR_symlinkat         293
+#define __NR_readlinkat                294
+#define __NR_fchmodat          295
+#define __NR_faccessat         296
+#define __NR_pselect6          297
+#define __NR_ppoll             298
+#define __NR_unshare           299
+#define __NR_set_robust_list   300
+#define __NR_get_robust_list   301
+#define __NR_migrate_pages     302
+#define __NR_mbind             303
+#define __NR_get_mempolicy     304
+#define __NR_set_mempolicy     305
+#define __NR_kexec_load                306
+#define __NR_move_pages                307
+#define __NR_getcpu            308
+#define __NR_epoll_pwait       309
+#define __NR_utimensat         310
+#define __NR_signalfd          311
+#define __NR_timerfd_create    312
+#define __NR_eventfd           313
+#define __NR_fallocate         314
+#define __NR_timerfd_settime   315
+#define __NR_timerfd_gettime   316
+#define __NR_signalfd4         317
+#define __NR_eventfd2          318
+#define __NR_epoll_create1     319
+#define __NR_dup3              320
+#define __NR_pipe2             321
+#define __NR_inotify_init1     322
+#define __NR_accept4           323
+#define __NR_preadv            324
+#define __NR_pwritev           325
+#define __NR_rt_tgsigqueueinfo 326
+#define __NR_perf_event_open   327
+#define __NR_recvmmsg          328
+#define __NR_fanotify_init     329
+#define __NR_fanotify_mark     330
+#define __NR_prlimit64         331
+#define __NR_name_to_handle_at 332
+#define __NR_open_by_handle_at 333
+#define __NR_clock_adjtime     334
+#define __NR_syncfs            335
+#define __NR_sendmmsg          336
+#define __NR_setns             337
+#define __NR_process_vm_readv  338
+#define __NR_process_vm_writev 339
+
+#define NR_syscalls            340
+
+#ifdef __32bit_syscall_numbers__
+/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
+ * it never had the plain ones and there is no value to adding those
+ * old versions into the syscall table.
+ */
+#define __IGNORE_setresuid
+#define __IGNORE_getresuid
+#define __IGNORE_setresgid
+#define __IGNORE_getresgid
+#endif
+
+#endif /* _UAPI_SPARC_UNISTD_H */
index 14006d8aca2849899d2ce1821f70f42d8ac50633..487bffb36f5eb4a2792808e317e845cdaa8553d1 100644 (file)
@@ -482,7 +482,7 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
 asmlinkage int sparc_execve(struct pt_regs *regs)
 {
        int error, base = 0;
-       char *filename;
+       struct filename *filename;
 
        /* Check for indirect call. */
        if(regs->u_regs[UREG_G1] == 0)
@@ -492,7 +492,7 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
        error = PTR_ERR(filename);
        if(IS_ERR(filename))
                goto out;
-       error = do_execve(filename,
+       error = do_execve(filename->name,
                          (const char __user *const  __user *)
                          regs->u_regs[base + UREG_I1],
                          (const char __user *const  __user *)
index aff0c72fac0999b70a4407179aad99eebfe84c29..fcaa59421126edf297d4e14dbbf2b90239d5d406 100644 (file)
@@ -722,7 +722,7 @@ EXPORT_SYMBOL(dump_fpu);
 asmlinkage int sparc_execve(struct pt_regs *regs)
 {
        int error, base = 0;
-       char *filename;
+       struct filename *filename;
 
        /* User register window flush is done by entry.S */
 
@@ -734,7 +734,7 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename,
+       error = do_execve(filename->name,
                          (const char __user *const __user *)
                          regs->u_regs[base + UREG_I1],
                          (const char __user *const __user *)
index d862499eb01ccfe298b7101190dfc29f3ebcf44d..c3239811a1b5775903c77e64057e78d01130fdd0 100644 (file)
@@ -403,7 +403,7 @@ asmlinkage long compat_sys_rt_sigaction(int sig,
 asmlinkage long sparc32_execve(struct pt_regs *regs)
 {
        int error, base = 0;
-       char *filename;
+       struct filename *filename;
 
        /* User register window flush is done by entry.S */
 
@@ -416,7 +416,7 @@ asmlinkage long sparc32_execve(struct pt_regs *regs)
        if (IS_ERR(filename))
                goto out;
 
-       error = compat_do_execve(filename,
+       error = compat_do_execve(filename->name,
                                 compat_ptr(regs->u_regs[base + UREG_I1]),
                                 compat_ptr(regs->u_regs[base + UREG_I2]), regs);
 
index 1d7e274f3f2b42bfac80354f1745c7ad48cd9e27..7f5f65d0b3fde92235c838bd976916bc863d0315 100644 (file)
@@ -212,24 +212,20 @@ linux_sparc_syscall:
 3:     stx     %o0, [%sp + PTREGS_OFF + PT_V9_I0]
 ret_sys_call:
        ldx     [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
-       ldx     [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
        sra     %o0, 0, %o0
        mov     %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
        sllx    %g2, 32, %g2
 
-       /* Check if force_successful_syscall_return()
-        * was invoked.
-        */
-       ldub    [%g6 + TI_SYS_NOERROR], %l2
-       brnz,a,pn %l2, 80f
-        stb    %g0, [%g6 + TI_SYS_NOERROR]
-
        cmp     %o0, -ERESTART_RESTARTBLOCK
        bgeu,pn %xcc, 1f
-        andcc  %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6
-80:
+        andcc  %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0
+       ldx     [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
+
+2:
+       stb     %g0, [%g6 + TI_SYS_NOERROR]
        /* System call success, clear Carry condition code. */
        andn    %g3, %g2, %g3
+3:
        stx     %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]  
        bne,pn  %icc, linux_syscall_trace2
         add    %l1, 0x4, %l2                   ! npc = npc+4
@@ -238,20 +234,20 @@ ret_sys_call:
         stx    %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
 
 1:
+       /* Check if force_successful_syscall_return()
+        * was invoked.
+        */
+       ldub    [%g6 + TI_SYS_NOERROR], %l2
+       brnz,pn %l2, 2b
+        ldx    [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
        /* System call failure, set Carry condition code.
         * Also, get abs(errno) to return to the process.
         */
-       andcc   %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6  
        sub     %g0, %o0, %o0
-       or      %g3, %g2, %g3
        stx     %o0, [%sp + PTREGS_OFF + PT_V9_I0]
-       stx     %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
-       bne,pn  %icc, linux_syscall_trace2
-        add    %l1, 0x4, %l2                   ! npc = npc+4
-       stx     %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
+       ba,pt   %xcc, 3b
+        or     %g3, %g2, %g3
 
-       b,pt    %xcc, rtrap
-        stx    %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
 linux_syscall_trace2:
        call    syscall_trace_leave
         add    %sp, PTREGS_OFF, %o0
index fa1f1d375ffc263571ab3b75e4dd0477284d583b..b66a77968f35ccd188a1c82ee956720248661706 100644 (file)
@@ -1,6 +1,6 @@
 /* arch/sparc64/kernel/traps.c
  *
- * Copyright (C) 1995,1997,2008,2009 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1995,1997,2008,2009,2012 David S. Miller (davem@davemloft.net)
  * Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com)
  */
 
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/kdebug.h>
 #include <linux/ftrace.h>
+#include <linux/reboot.h>
 #include <linux/gfp.h>
 
 #include <asm/smp.h>
@@ -1760,85 +1761,223 @@ void cheetah_plus_parity_error(int type, struct pt_regs *regs)
 }
 
 struct sun4v_error_entry {
-       u64             err_handle;
-       u64             err_stick;
+       /* Unique error handle */
+/*0x00*/u64            err_handle;
 
-       u32             err_type;
+       /* %stick value at the time of the error */
+/*0x08*/u64            err_stick;
+
+/*0x10*/u8             reserved_1[3];
+
+       /* Error type */
+/*0x13*/u8             err_type;
 #define SUN4V_ERR_TYPE_UNDEFINED       0
 #define SUN4V_ERR_TYPE_UNCORRECTED_RES 1
 #define SUN4V_ERR_TYPE_PRECISE_NONRES  2
 #define SUN4V_ERR_TYPE_DEFERRED_NONRES 3
-#define SUN4V_ERR_TYPE_WARNING_RES     4
+#define SUN4V_ERR_TYPE_SHUTDOWN_RQST   4
+#define SUN4V_ERR_TYPE_DUMP_CORE       5
+#define SUN4V_ERR_TYPE_SP_STATE_CHANGE 6
+#define SUN4V_ERR_TYPE_NUM             7
 
-       u32             err_attrs;
+       /* Error attributes */
+/*0x14*/u32            err_attrs;
 #define SUN4V_ERR_ATTRS_PROCESSOR      0x00000001
 #define SUN4V_ERR_ATTRS_MEMORY         0x00000002
 #define SUN4V_ERR_ATTRS_PIO            0x00000004
 #define SUN4V_ERR_ATTRS_INT_REGISTERS  0x00000008
 #define SUN4V_ERR_ATTRS_FPU_REGISTERS  0x00000010
-#define SUN4V_ERR_ATTRS_USER_MODE      0x01000000
-#define SUN4V_ERR_ATTRS_PRIV_MODE      0x02000000
+#define SUN4V_ERR_ATTRS_SHUTDOWN_RQST  0x00000020
+#define SUN4V_ERR_ATTRS_ASR            0x00000040
+#define SUN4V_ERR_ATTRS_ASI            0x00000080
+#define SUN4V_ERR_ATTRS_PRIV_REG       0x00000100
+#define SUN4V_ERR_ATTRS_SPSTATE_MSK    0x00000600
+#define SUN4V_ERR_ATTRS_SPSTATE_SHFT   9
+#define SUN4V_ERR_ATTRS_MODE_MSK       0x03000000
+#define SUN4V_ERR_ATTRS_MODE_SHFT      24
 #define SUN4V_ERR_ATTRS_RES_QUEUE_FULL 0x80000000
 
-       u64             err_raddr;
-       u32             err_size;
-       u16             err_cpu;
-       u16             err_pad;
+#define SUN4V_ERR_SPSTATE_FAULTED      0
+#define SUN4V_ERR_SPSTATE_AVAILABLE    1
+#define SUN4V_ERR_SPSTATE_NOT_PRESENT  2
+
+#define SUN4V_ERR_MODE_USER            1
+#define SUN4V_ERR_MODE_PRIV            2
+
+       /* Real address of the memory region or PIO transaction */
+/*0x18*/u64            err_raddr;
+
+       /* Size of the operation triggering the error, in bytes */
+/*0x20*/u32            err_size;
+
+       /* ID of the CPU */
+/*0x24*/u16            err_cpu;
+
+       /* Grace periof for shutdown, in seconds */
+/*0x26*/u16            err_secs;
+
+       /* Value of the %asi register */
+/*0x28*/u8             err_asi;
+
+/*0x29*/u8             reserved_2;
+
+       /* Value of the ASR register number */
+/*0x2a*/u16            err_asr;
+#define SUN4V_ERR_ASR_VALID            0x8000
+
+/*0x2c*/u32            reserved_3;
+/*0x30*/u64            reserved_4;
+/*0x38*/u64            reserved_5;
 };
 
 static atomic_t sun4v_resum_oflow_cnt = ATOMIC_INIT(0);
 static atomic_t sun4v_nonresum_oflow_cnt = ATOMIC_INIT(0);
 
-static const char *sun4v_err_type_to_str(u32 type)
-{
-       switch (type) {
-       case SUN4V_ERR_TYPE_UNDEFINED:
-               return "undefined";
-       case SUN4V_ERR_TYPE_UNCORRECTED_RES:
-               return "uncorrected resumable";
-       case SUN4V_ERR_TYPE_PRECISE_NONRES:
-               return "precise nonresumable";
-       case SUN4V_ERR_TYPE_DEFERRED_NONRES:
-               return "deferred nonresumable";
-       case SUN4V_ERR_TYPE_WARNING_RES:
-               return "warning resumable";
-       default:
-               return "unknown";
+static const char *sun4v_err_type_to_str(u8 type)
+{
+       static const char *types[SUN4V_ERR_TYPE_NUM] = {
+               "undefined",
+               "uncorrected resumable",
+               "precise nonresumable",
+               "deferred nonresumable",
+               "shutdown request",
+               "dump core",
+               "SP state change",
+       };
+
+       if (type < SUN4V_ERR_TYPE_NUM)
+               return types[type];
+
+       return "unknown";
+}
+
+static void sun4v_emit_err_attr_strings(u32 attrs)
+{
+       static const char *attr_names[] = {
+               "processor",
+               "memory",
+               "PIO",
+               "int-registers",
+               "fpu-registers",
+               "shutdown-request",
+               "ASR",
+               "ASI",
+               "priv-reg",
+       };
+       static const char *sp_states[] = {
+               "sp-faulted",
+               "sp-available",
+               "sp-not-present",
+               "sp-state-reserved",
+       };
+       static const char *modes[] = {
+               "mode-reserved0",
+               "user",
+               "priv",
+               "mode-reserved1",
+       };
+       u32 sp_state, mode;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
+               if (attrs & (1U << i)) {
+                       const char *s = attr_names[i];
+
+                       pr_cont("%s ", s);
+               }
        }
+
+       sp_state = ((attrs & SUN4V_ERR_ATTRS_SPSTATE_MSK) >>
+                   SUN4V_ERR_ATTRS_SPSTATE_SHFT);
+       pr_cont("%s ", sp_states[sp_state]);
+
+       mode = ((attrs & SUN4V_ERR_ATTRS_MODE_MSK) >>
+               SUN4V_ERR_ATTRS_MODE_SHFT);
+       pr_cont("%s ", modes[mode]);
+
+       if (attrs & SUN4V_ERR_ATTRS_RES_QUEUE_FULL)
+               pr_cont("res-queue-full ");
 }
 
-static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt)
+/* When the report contains a real-address of "-1" it means that the
+ * hardware did not provide the address.  So we compute the effective
+ * address of the load or store instruction at regs->tpc and report
+ * that.  Usually when this happens it's a PIO and in such a case we
+ * are using physical addresses with bypass ASIs anyways, so what we
+ * report here is exactly what we want.
+ */
+static void sun4v_report_real_raddr(const char *pfx, struct pt_regs *regs)
 {
+       unsigned int insn;
+       u64 addr;
+
+       if (!(regs->tstate & TSTATE_PRIV))
+               return;
+
+       insn = *(unsigned int *) regs->tpc;
+
+       addr = compute_effective_address(regs, insn, 0);
+
+       printk("%s: insn effective address [0x%016llx]\n",
+              pfx, addr);
+}
+
+static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent,
+                           int cpu, const char *pfx, atomic_t *ocnt)
+{
+       u64 *raw_ptr = (u64 *) ent;
+       u32 attrs;
        int cnt;
 
        printk("%s: Reporting on cpu %d\n", pfx, cpu);
-       printk("%s: err_handle[%llx] err_stick[%llx] err_type[%08x:%s]\n",
-              pfx,
-              ent->err_handle, ent->err_stick,
-              ent->err_type,
-              sun4v_err_type_to_str(ent->err_type));
-       printk("%s: err_attrs[%08x:%s %s %s %s %s %s %s %s]\n",
-              pfx,
-              ent->err_attrs,
-              ((ent->err_attrs & SUN4V_ERR_ATTRS_PROCESSOR) ?
-               "processor" : ""),
-              ((ent->err_attrs & SUN4V_ERR_ATTRS_MEMORY) ?
-               "memory" : ""),
-              ((ent->err_attrs & SUN4V_ERR_ATTRS_PIO) ?
-               "pio" : ""),
-              ((ent->err_attrs & SUN4V_ERR_ATTRS_INT_REGISTERS) ?
-               "integer-regs" : ""),
-              ((ent->err_attrs & SUN4V_ERR_ATTRS_FPU_REGISTERS) ?
-               "fpu-regs" : ""),
-              ((ent->err_attrs & SUN4V_ERR_ATTRS_USER_MODE) ?
-               "user" : ""),
-              ((ent->err_attrs & SUN4V_ERR_ATTRS_PRIV_MODE) ?
-               "privileged" : ""),
-              ((ent->err_attrs & SUN4V_ERR_ATTRS_RES_QUEUE_FULL) ?
-               "queue-full" : ""));
-       printk("%s: err_raddr[%016llx] err_size[%u] err_cpu[%u]\n",
-              pfx,
-              ent->err_raddr, ent->err_size, ent->err_cpu);
+       printk("%s: TPC [0x%016lx] <%pS>\n",
+              pfx, regs->tpc, (void *) regs->tpc);
+
+       printk("%s: RAW [%016llx:%016llx:%016llx:%016llx\n",
+              pfx, raw_ptr[0], raw_ptr[1], raw_ptr[2], raw_ptr[3]);
+       printk("%s:      %016llx:%016llx:%016llx:%016llx]\n",
+              pfx, raw_ptr[4], raw_ptr[5], raw_ptr[6], raw_ptr[7]);
+
+       printk("%s: handle [0x%016llx] stick [0x%016llx]\n",
+              pfx, ent->err_handle, ent->err_stick);
+
+       printk("%s: type [%s]\n", pfx, sun4v_err_type_to_str(ent->err_type));
+
+       attrs = ent->err_attrs;
+       printk("%s: attrs [0x%08x] < ", pfx, attrs);
+       sun4v_emit_err_attr_strings(attrs);
+       pr_cont(">\n");
+
+       /* Various fields in the error report are only valid if
+        * certain attribute bits are set.
+        */
+       if (attrs & (SUN4V_ERR_ATTRS_MEMORY |
+                    SUN4V_ERR_ATTRS_PIO |
+                    SUN4V_ERR_ATTRS_ASI)) {
+               printk("%s: raddr [0x%016llx]\n", pfx, ent->err_raddr);
+
+               if (ent->err_raddr == ~(u64)0)
+                       sun4v_report_real_raddr(pfx, regs);
+       }
+
+       if (attrs & (SUN4V_ERR_ATTRS_MEMORY | SUN4V_ERR_ATTRS_ASI))
+               printk("%s: size [0x%x]\n", pfx, ent->err_size);
+
+       if (attrs & (SUN4V_ERR_ATTRS_PROCESSOR |
+                    SUN4V_ERR_ATTRS_INT_REGISTERS |
+                    SUN4V_ERR_ATTRS_FPU_REGISTERS |
+                    SUN4V_ERR_ATTRS_PRIV_REG))
+               printk("%s: cpu[%u]\n", pfx, ent->err_cpu);
+
+       if (attrs & SUN4V_ERR_ATTRS_ASI)
+               printk("%s: asi [0x%02x]\n", pfx, ent->err_asi);
+
+       if ((attrs & (SUN4V_ERR_ATTRS_INT_REGISTERS |
+                     SUN4V_ERR_ATTRS_FPU_REGISTERS |
+                     SUN4V_ERR_ATTRS_PRIV_REG)) &&
+           (ent->err_asr & SUN4V_ERR_ASR_VALID) != 0)
+               printk("%s: reg [0x%04x]\n",
+                      pfx, ent->err_asr & ~SUN4V_ERR_ASR_VALID);
 
        show_regs(regs);
 
@@ -1874,13 +2013,15 @@ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset)
 
        put_cpu();
 
-       if (ent->err_type == SUN4V_ERR_TYPE_WARNING_RES) {
-               /* If err_type is 0x4, it's a powerdown request.  Do
-                * not do the usual resumable error log because that
-                * makes it look like some abnormal error.
+       if (local_copy.err_type == SUN4V_ERR_TYPE_SHUTDOWN_RQST) {
+               /* We should really take the seconds field of
+                * the error report and use it for the shutdown
+                * invocation, but for now do the same thing we
+                * do for a DS shutdown request.
                 */
-               printk(KERN_INFO "Power down request...\n");
-               kill_cad_pid(SIGINT, 1);
+               pr_info("Shutdown request, %u seconds...\n",
+                       local_copy.err_secs);
+               orderly_poweroff(true);
                return;
        }
 
index 2976dba1ebaf46ab02d8e35f06f830e4b0fae22a..097aee763af30a26dec9165425c7666f4ab67a88 100644 (file)
@@ -151,8 +151,6 @@ show_signal_msg(struct pt_regs *regs, int sig, int code,
        printk(KERN_CONT "\n");
 }
 
-extern unsigned long compute_effective_address(struct pt_regs *, unsigned int, unsigned int);
-
 static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
                             unsigned int insn, int fault_code)
 {
index 9c0ea24cc94888183ddbacd81f039769957c268b..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,17 +0,0 @@
-header-y += abi.h
-header-y += chip.h
-header-y += chip_tile64.h
-header-y += chip_tilegx.h
-header-y += chip_tilepro.h
-header-y += icache.h
-header-y += interrupts.h
-header-y += interrupts_32.h
-header-y += interrupts_64.h
-header-y += opcode.h
-header-y += opcode_tilegx.h
-header-y += opcode_tilepro.h
-header-y += sim.h
-header-y += sim_def.h
-header-y += spr_def.h
-header-y += spr_def_32.h
-header-y += spr_def_64.h
index d6ba449b5363f3318d094ece0f1bf455853da755..2de83e7aff3e4569aa93b37fa1858420f7c5924c 100644 (file)
  *   NON INFRINGEMENT.  See the GNU General Public License for
  *   more details.
  */
+#ifndef __ARCH_SPR_DEF_H__
+#define __ARCH_SPR_DEF_H__
 
-/* Include the proper base SPR definition file. */
-#ifdef __tilegx__
-#include <arch/spr_def_64.h>
-#else
-#include <arch/spr_def_32.h>
-#endif
+#include <uapi/arch/spr_def.h>
 
-#ifdef __KERNEL__
 
 /*
  * In addition to including the proper base SPR definition file, depending
 #define INT_INTCTRL_K \
        _concat4(INT_INTCTRL_, CONFIG_KERNEL_PL,,)
 
-#endif /* __KERNEL__ */
+#endif /* __ARCH_SPR_DEF_H__ */
index ea2e8ea3eb6135e181f6fd15b95e8c47701bf3b0..c68808a09da7732ccab05fd2415e449c1e46bb99 100644 (file)
@@ -1,10 +1,7 @@
-include include/asm-generic/Kbuild.asm
 
 header-y += ../arch/
 
-header-y += cachectl.h
 header-y += ucontext.h
-header-y += hardwall.h
 
 generic-y += bug.h
 generic-y += bugs.h
@@ -13,6 +10,7 @@ generic-y += cputime.h
 generic-y += div64.h
 generic-y += emergency-restart.h
 generic-y += errno.h
+generic-y += exec.h
 generic-y += fb.h
 generic-y += fcntl.h
 generic-y += ioctl.h
index 47514a58d68559a86fef6a0b7de1fa63c3fbc126..2f572b6b7bc2b6efd259ba6880da4bbf02f5bc79 100644 (file)
  * Provide methods for access control of per-cpu resources like
  * UDN, IDN, or IPI.
  */
-
 #ifndef _ASM_TILE_HARDWALL_H
 #define _ASM_TILE_HARDWALL_H
 
-#include <arch/chip.h>
-#include <linux/ioctl.h>
-
-#define HARDWALL_IOCTL_BASE 0xa2
-
-/*
- * The HARDWALL_CREATE() ioctl is a macro with a "size" argument.
- * The resulting ioctl value is passed to the kernel in conjunction
- * with a pointer to a standard kernel bitmask of cpus.
- * For network resources (UDN or IDN) the bitmask must physically
- * represent a rectangular configuration on the chip.
- * The "size" is the number of bytes of cpu mask data.
- */
-#define _HARDWALL_CREATE 1
-#define HARDWALL_CREATE(size) \
-  _IOC(_IOC_READ, HARDWALL_IOCTL_BASE, _HARDWALL_CREATE, (size))
-
-#define _HARDWALL_ACTIVATE 2
-#define HARDWALL_ACTIVATE \
-  _IO(HARDWALL_IOCTL_BASE, _HARDWALL_ACTIVATE)
-
-#define _HARDWALL_DEACTIVATE 3
-#define HARDWALL_DEACTIVATE \
- _IO(HARDWALL_IOCTL_BASE, _HARDWALL_DEACTIVATE)
-
-#define _HARDWALL_GET_ID 4
-#define HARDWALL_GET_ID \
- _IO(HARDWALL_IOCTL_BASE, _HARDWALL_GET_ID)
+#include <uapi/asm/hardwall.h>
 
-#ifdef __KERNEL__
 /* /proc hooks for hardwall. */
 struct proc_dir_entry;
 #ifdef CONFIG_HARDWALL
@@ -56,6 +27,4 @@ int proc_pid_hardwall(struct task_struct *task, char *buffer);
 #else
 static inline void proc_tile_hardwall_init(struct proc_dir_entry *root) {}
 #endif
-#endif
-
 #endif /* _ASM_TILE_HARDWALL_H */
index c6cddd7e8d517fd0b587075728eaab90ff6432c1..1a4fd9ab0ee1663ce4a4bdb86584be442c345dad 100644 (file)
  *   NON INFRINGEMENT.  See the GNU General Public License for
  *   more details.
  */
-
 #ifndef _ASM_TILE_PTRACE_H
 #define _ASM_TILE_PTRACE_H
 
-#include <arch/chip.h>
-#include <arch/abi.h>
-
-/* These must match struct pt_regs, below. */
-#if CHIP_WORD_SIZE() == 32
-#define PTREGS_OFFSET_REG(n)    ((n)*4)
-#else
-#define PTREGS_OFFSET_REG(n)    ((n)*8)
-#endif
-#define PTREGS_OFFSET_BASE      0
-#define PTREGS_OFFSET_TP        PTREGS_OFFSET_REG(53)
-#define PTREGS_OFFSET_SP        PTREGS_OFFSET_REG(54)
-#define PTREGS_OFFSET_LR        PTREGS_OFFSET_REG(55)
-#define PTREGS_NR_GPRS          56
-#define PTREGS_OFFSET_PC        PTREGS_OFFSET_REG(56)
-#define PTREGS_OFFSET_EX1       PTREGS_OFFSET_REG(57)
-#define PTREGS_OFFSET_FAULTNUM  PTREGS_OFFSET_REG(58)
-#define PTREGS_OFFSET_ORIG_R0   PTREGS_OFFSET_REG(59)
-#define PTREGS_OFFSET_FLAGS     PTREGS_OFFSET_REG(60)
-#if CHIP_HAS_CMPEXCH()
-#define PTREGS_OFFSET_CMPEXCH   PTREGS_OFFSET_REG(61)
-#endif
-#define PTREGS_SIZE             PTREGS_OFFSET_REG(64)
+#include <linux/compiler.h>
 
 #ifndef __ASSEMBLY__
-
-#ifdef __KERNEL__
 /* Benefit from consistent use of "long" on all chips. */
 typedef unsigned long pt_reg_t;
-#else
-/* Provide appropriate length type to userspace regardless of -m32/-m64. */
-typedef uint_reg_t pt_reg_t;
-#endif
-
-/*
- * This struct defines the way the registers are stored on the stack during a
- * system call or exception.  "struct sigcontext" has the same shape.
- */
-struct pt_regs {
-       /* Saved main processor registers; 56..63 are special. */
-       /* tp, sp, and lr must immediately follow regs[] for aliasing. */
-       pt_reg_t regs[53];
-       pt_reg_t tp;            /* aliases regs[TREG_TP] */
-       pt_reg_t sp;            /* aliases regs[TREG_SP] */
-       pt_reg_t lr;            /* aliases regs[TREG_LR] */
-
-       /* Saved special registers. */
-       pt_reg_t pc;            /* stored in EX_CONTEXT_K_0 */
-       pt_reg_t ex1;           /* stored in EX_CONTEXT_K_1 (PL and ICS bit) */
-       pt_reg_t faultnum;      /* fault number (INT_SWINT_1 for syscall) */
-       pt_reg_t orig_r0;       /* r0 at syscall entry, else zero */
-       pt_reg_t flags;         /* flags (see below) */
-#if !CHIP_HAS_CMPEXCH()
-       pt_reg_t pad[3];
-#else
-       pt_reg_t cmpexch;       /* value of CMPEXCH_VALUE SPR at interrupt */
-       pt_reg_t pad[2];
 #endif
-};
-
-#endif /* __ASSEMBLY__ */
 
-#define PTRACE_GETREGS         12
-#define PTRACE_SETREGS         13
-#define PTRACE_GETFPREGS       14
-#define PTRACE_SETFPREGS       15
+#include <uapi/asm/ptrace.h>
 
-/* Support TILE-specific ptrace options, with events starting at 16. */
-#define PTRACE_O_TRACEMIGRATE  0x00010000
-#define PTRACE_EVENT_MIGRATE   16
-#ifdef __KERNEL__
 #define PTRACE_O_MASK_TILE     (PTRACE_O_TRACEMIGRATE)
 #define PT_TRACE_MIGRATE       0x00080000
 #define PT_TRACE_MASK_TILE     (PT_TRACE_MIGRATE)
-#endif
-
-#ifdef __KERNEL__
 
 /* Flag bits in pt_regs.flags */
 #define PT_FLAGS_DISABLE_IRQ    1  /* on return to kernel, disable irqs */
@@ -159,6 +93,4 @@ extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
 #define SINGLESTEP_STATE_TARGET_LB              2
 #define SINGLESTEP_STATE_TARGET_UB              7
 
-#endif /* !__KERNEL__ */
-
 #endif /* _ASM_TILE_PTRACE_H */
index c67eb70ea78e94fb08410897630a96228a2e3456..d048888c5d9aa8427fdee84ba324c7f662c7b6e9 100644 (file)
  *   NON INFRINGEMENT.  See the GNU General Public License for
  *   more details.
  */
-
 #ifndef _ASM_TILE_SETUP_H
 #define _ASM_TILE_SETUP_H
 
-#define COMMAND_LINE_SIZE      2048
-
-#ifdef __KERNEL__
 
 #include <linux/pfn.h>
 #include <linux/init.h>
+#include <uapi/asm/setup.h>
 
 /*
  * Reserved space for vmalloc and iomap - defined in asm/page.h
@@ -53,6 +50,4 @@ int hardwall_ipi_valid(int cpu);
 } while (0)
 #endif
 
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_TILE_SETUP_H */
index 1e5e49aad54877e5664f5a0d56964845f8ad4b76..10e183de96d3af2b27c81919bfb4c85b7df4371e 100644 (file)
  *   NON INFRINGEMENT.  See the GNU General Public License for
  *   more details.
  */
-
 #ifndef _ASM_TILE_SIGNAL_H
 #define _ASM_TILE_SIGNAL_H
 
-/* Do not notify a ptracer when this signal is handled. */
-#define SA_NOPTRACE 0x02000000u
-
-/* Used in earlier Tilera releases, so keeping for binary compatibility. */
-#define SA_RESTORER 0x04000000u
-
-#include <asm-generic/signal.h>
+#include <uapi/asm/signal.h>
 
-#if defined(__KERNEL__)
 #if !defined(__ASSEMBLY__)
 struct pt_regs;
 int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
@@ -34,6 +26,4 @@ void signal_fault(const char *type, struct pt_regs *,
 void trace_unhandled_signal(const char *type, struct pt_regs *regs,
                            unsigned long address, int signo);
 #endif
-#endif
-
 #endif /* _ASM_TILE_SIGNAL_H */
index 0e1f3e66e492d01090313d634cef49c52da2e302..6e032a0a268eebeacb8c04b4fb1f17f1da0bbcd3 100644 (file)
  *   NON INFRINGEMENT.  See the GNU General Public License for
  *   more details.
  */
-
-#if !defined(__LP64__) || defined(__SYSCALL_COMPAT)
-/* Use the flavor of this syscall that matches the 32-bit API better. */
-#define __ARCH_WANT_SYNC_FILE_RANGE2
-#endif
-
-/* Use the standard ABI for syscalls. */
-#include <asm-generic/unistd.h>
-
-/* Additional Tilera-specific syscalls. */
-#define __NR_cacheflush        (__NR_arch_specific_syscall + 1)
-__SYSCALL(__NR_cacheflush, sys_cacheflush)
-
-#ifndef __tilegx__
-/* "Fast" syscalls provide atomic support for 32-bit chips. */
-#define __NR_FAST_cmpxchg      -1
-#define __NR_FAST_atomic_update        -2
-#define __NR_FAST_cmpxchg64    -3
-#define __NR_cmpxchg_badaddr   (__NR_arch_specific_syscall + 0)
-__SYSCALL(__NR_cmpxchg_badaddr, sys_cmpxchg_badaddr)
-#endif
-
-#ifdef __KERNEL__
 /* In compat mode, we use sys_llseek() for compat_sys_llseek(). */
 #ifdef CONFIG_COMPAT
 #define __ARCH_WANT_SYS_LLSEEK
 #endif
 #define __ARCH_WANT_SYS_NEWFSTATAT
-#endif
+#include <uapi/asm/unistd.h>
index aafaa5aa54d46bb9a93a8137a22344408298223f..4ebc34f4768dda009d5ed4213880174dd78231da 100644 (file)
@@ -1 +1,18 @@
 # UAPI Header export list
+header-y += abi.h
+header-y += chip.h
+header-y += chip_tile64.h
+header-y += chip_tilegx.h
+header-y += chip_tilepro.h
+header-y += icache.h
+header-y += interrupts.h
+header-y += interrupts_32.h
+header-y += interrupts_64.h
+header-y += opcode.h
+header-y += opcode_tilegx.h
+header-y += opcode_tilepro.h
+header-y += sim.h
+header-y += sim_def.h
+header-y += spr_def.h
+header-y += spr_def_32.h
+header-y += spr_def_64.h
diff --git a/arch/tile/include/uapi/arch/spr_def.h b/arch/tile/include/uapi/arch/spr_def.h
new file mode 100644 (file)
index 0000000..c250c5a
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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 _UAPI__ARCH_SPR_DEF_H__
+#define _UAPI__ARCH_SPR_DEF_H__
+
+/* Include the proper base SPR definition file. */
+#ifdef __tilegx__
+#include <arch/spr_def_64.h>
+#else
+#include <arch/spr_def_32.h>
+#endif
+
+
+#endif /* _UAPI__ARCH_SPR_DEF_H__ */
similarity index 98%
rename from arch/tile/include/arch/spr_def_32.h
rename to arch/tile/include/uapi/arch/spr_def_32.h
index 78bbce2fb19a6017ed6ea33459929f75d11fee34..c689446e62844e9e7e0b15d6f3d683f2b5719d08 100644 (file)
@@ -14,8 +14,8 @@
 
 #ifndef __DOXYGEN__
 
-#ifndef __ARCH_SPR_DEF_H__
-#define __ARCH_SPR_DEF_H__
+#ifndef __ARCH_SPR_DEF_32_H__
+#define __ARCH_SPR_DEF_32_H__
 
 #define SPR_AUX_PERF_COUNT_0 0x6005
 #define SPR_AUX_PERF_COUNT_1 0x6006
 #define SPR_WATCH_MASK 0x420a
 #define SPR_WATCH_VAL 0x420b
 
-#endif /* !defined(__ARCH_SPR_DEF_H__) */
+#endif /* !defined(__ARCH_SPR_DEF_32_H__) */
 
 #endif /* !defined(__DOXYGEN__) */
similarity index 98%
rename from arch/tile/include/arch/spr_def_64.h
rename to arch/tile/include/uapi/arch/spr_def_64.h
index 0da86faa33707e88d8a477eb373613a9ee2a1c18..67a6c1751e3b68f8b0c5cff6352cdd99dfb13291 100644 (file)
@@ -14,8 +14,8 @@
 
 #ifndef __DOXYGEN__
 
-#ifndef __ARCH_SPR_DEF_H__
-#define __ARCH_SPR_DEF_H__
+#ifndef __ARCH_SPR_DEF_64_H__
+#define __ARCH_SPR_DEF_64_H__
 
 #define SPR_AUX_PERF_COUNT_0 0x2105
 #define SPR_AUX_PERF_COUNT_1 0x2106
 #define SPR_WATCH_MASK 0x200a
 #define SPR_WATCH_VAL 0x200b
 
-#endif /* !defined(__ARCH_SPR_DEF_H__) */
+#endif /* !defined(__ARCH_SPR_DEF_64_H__) */
 
 #endif /* !defined(__DOXYGEN__) */
index baebb3da1d44160fc6f6f259886656e6f494b167..5c6915fd30b5c4397e12fe4e7662316320f0c68f 100644 (file)
@@ -1,3 +1,18 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += auxvec.h
+header-y += bitsperlong.h
+header-y += byteorder.h
+header-y += cachectl.h
+header-y += hardwall.h
+header-y += kvm_para.h
+header-y += mman.h
+header-y += ptrace.h
+header-y += setup.h
+header-y += sigcontext.h
+header-y += siginfo.h
+header-y += signal.h
+header-y += stat.h
+header-y += swab.h
+header-y += unistd.h
diff --git a/arch/tile/include/uapi/asm/hardwall.h b/arch/tile/include/uapi/asm/hardwall.h
new file mode 100644 (file)
index 0000000..c2169d4
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ *
+ * Provide methods for access control of per-cpu resources like
+ * UDN, IDN, or IPI.
+ */
+
+#ifndef _UAPI_ASM_TILE_HARDWALL_H
+#define _UAPI_ASM_TILE_HARDWALL_H
+
+#include <arch/chip.h>
+#include <linux/ioctl.h>
+
+#define HARDWALL_IOCTL_BASE 0xa2
+
+/*
+ * The HARDWALL_CREATE() ioctl is a macro with a "size" argument.
+ * The resulting ioctl value is passed to the kernel in conjunction
+ * with a pointer to a standard kernel bitmask of cpus.
+ * For network resources (UDN or IDN) the bitmask must physically
+ * represent a rectangular configuration on the chip.
+ * The "size" is the number of bytes of cpu mask data.
+ */
+#define _HARDWALL_CREATE 1
+#define HARDWALL_CREATE(size) \
+  _IOC(_IOC_READ, HARDWALL_IOCTL_BASE, _HARDWALL_CREATE, (size))
+
+#define _HARDWALL_ACTIVATE 2
+#define HARDWALL_ACTIVATE \
+  _IO(HARDWALL_IOCTL_BASE, _HARDWALL_ACTIVATE)
+
+#define _HARDWALL_DEACTIVATE 3
+#define HARDWALL_DEACTIVATE \
+ _IO(HARDWALL_IOCTL_BASE, _HARDWALL_DEACTIVATE)
+
+#define _HARDWALL_GET_ID 4
+#define HARDWALL_GET_ID \
+ _IO(HARDWALL_IOCTL_BASE, _HARDWALL_GET_ID)
+
+
+#endif /* _UAPI_ASM_TILE_HARDWALL_H */
diff --git a/arch/tile/include/uapi/asm/ptrace.h b/arch/tile/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..c717d0f
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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 _UAPI_ASM_TILE_PTRACE_H
+#define _UAPI_ASM_TILE_PTRACE_H
+
+#include <arch/chip.h>
+#include <arch/abi.h>
+
+/* These must match struct pt_regs, below. */
+#if CHIP_WORD_SIZE() == 32
+#define PTREGS_OFFSET_REG(n)    ((n)*4)
+#else
+#define PTREGS_OFFSET_REG(n)    ((n)*8)
+#endif
+#define PTREGS_OFFSET_BASE      0
+#define PTREGS_OFFSET_TP        PTREGS_OFFSET_REG(53)
+#define PTREGS_OFFSET_SP        PTREGS_OFFSET_REG(54)
+#define PTREGS_OFFSET_LR        PTREGS_OFFSET_REG(55)
+#define PTREGS_NR_GPRS          56
+#define PTREGS_OFFSET_PC        PTREGS_OFFSET_REG(56)
+#define PTREGS_OFFSET_EX1       PTREGS_OFFSET_REG(57)
+#define PTREGS_OFFSET_FAULTNUM  PTREGS_OFFSET_REG(58)
+#define PTREGS_OFFSET_ORIG_R0   PTREGS_OFFSET_REG(59)
+#define PTREGS_OFFSET_FLAGS     PTREGS_OFFSET_REG(60)
+#if CHIP_HAS_CMPEXCH()
+#define PTREGS_OFFSET_CMPEXCH   PTREGS_OFFSET_REG(61)
+#endif
+#define PTREGS_SIZE             PTREGS_OFFSET_REG(64)
+
+
+#ifndef __ASSEMBLY__
+
+#ifndef __KERNEL__
+/* Provide appropriate length type to userspace regardless of -m32/-m64. */
+typedef uint_reg_t pt_reg_t;
+#endif
+
+/*
+ * This struct defines the way the registers are stored on the stack during a
+ * system call or exception.  "struct sigcontext" has the same shape.
+ */
+struct pt_regs {
+       /* Saved main processor registers; 56..63 are special. */
+       /* tp, sp, and lr must immediately follow regs[] for aliasing. */
+       pt_reg_t regs[53];
+       pt_reg_t tp;            /* aliases regs[TREG_TP] */
+       pt_reg_t sp;            /* aliases regs[TREG_SP] */
+       pt_reg_t lr;            /* aliases regs[TREG_LR] */
+
+       /* Saved special registers. */
+       pt_reg_t pc;            /* stored in EX_CONTEXT_K_0 */
+       pt_reg_t ex1;           /* stored in EX_CONTEXT_K_1 (PL and ICS bit) */
+       pt_reg_t faultnum;      /* fault number (INT_SWINT_1 for syscall) */
+       pt_reg_t orig_r0;       /* r0 at syscall entry, else zero */
+       pt_reg_t flags;         /* flags (see below) */
+#if !CHIP_HAS_CMPEXCH()
+       pt_reg_t pad[3];
+#else
+       pt_reg_t cmpexch;       /* value of CMPEXCH_VALUE SPR at interrupt */
+       pt_reg_t pad[2];
+#endif
+};
+
+#endif /* __ASSEMBLY__ */
+
+#define PTRACE_GETREGS         12
+#define PTRACE_SETREGS         13
+#define PTRACE_GETFPREGS       14
+#define PTRACE_SETFPREGS       15
+
+/* Support TILE-specific ptrace options, with events starting at 16. */
+#define PTRACE_O_TRACEMIGRATE  0x00010000
+#define PTRACE_EVENT_MIGRATE   16
+
+
+#endif /* _UAPI_ASM_TILE_PTRACE_H */
similarity index 81%
rename from arch/tile/include/asm/exec.h
rename to arch/tile/include/uapi/asm/setup.h
index a714e1950867f28217b8372129303a704a361c03..e6f7da265ac3eafd4bde169d3acf8b48d63a1b53 100644 (file)
  *   more details.
  */
 
-#ifndef _ASM_TILE_EXEC_H
-#define _ASM_TILE_EXEC_H
+#ifndef _UAPI_ASM_TILE_SETUP_H
+#define _UAPI_ASM_TILE_SETUP_H
 
-#define arch_align_stack(x) (x)
+#define COMMAND_LINE_SIZE      2048
 
-#endif /* _ASM_TILE_EXEC_H */
+
+#endif /* _UAPI_ASM_TILE_SETUP_H */
diff --git a/arch/tile/include/uapi/asm/signal.h b/arch/tile/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..ef0d32d
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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 _UAPI_ASM_TILE_SIGNAL_H
+#define _UAPI_ASM_TILE_SIGNAL_H
+
+/* Do not notify a ptracer when this signal is handled. */
+#define SA_NOPTRACE 0x02000000u
+
+/* Used in earlier Tilera releases, so keeping for binary compatibility. */
+#define SA_RESTORER 0x04000000u
+
+#include <asm-generic/signal.h>
+
+
+#endif /* _UAPI_ASM_TILE_SIGNAL_H */
diff --git a/arch/tile/include/uapi/asm/unistd.h b/arch/tile/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..cd7b6dd
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#if !defined(__LP64__) || defined(__SYSCALL_COMPAT)
+/* Use the flavor of this syscall that matches the 32-bit API better. */
+#define __ARCH_WANT_SYNC_FILE_RANGE2
+#endif
+
+/* Use the standard ABI for syscalls. */
+#include <asm-generic/unistd.h>
+
+/* Additional Tilera-specific syscalls. */
+#define __NR_cacheflush        (__NR_arch_specific_syscall + 1)
+__SYSCALL(__NR_cacheflush, sys_cacheflush)
+
+#ifndef __tilegx__
+/* "Fast" syscalls provide atomic support for 32-bit chips. */
+#define __NR_FAST_cmpxchg      -1
+#define __NR_FAST_atomic_update        -2
+#define __NR_FAST_cmpxchg64    -3
+#define __NR_cmpxchg_badaddr   (__NR_arch_specific_syscall + 0)
+__SYSCALL(__NR_cmpxchg_badaddr, sys_cmpxchg_badaddr)
+#endif
index 7bc0859a9f5ea688779266c10b967ad9f9a554ed..08b4fe1717bb975aa6edff118fa79f641e77b237 100644 (file)
@@ -354,15 +354,6 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->regs[1] = ptr_to_compat_reg(&frame->info);
        regs->regs[2] = ptr_to_compat_reg(&frame->uc);
        regs->flags |= PT_FLAGS_CALLER_SAVES;
-
-       /*
-        * Notify any tracer that was single-stepping it.
-        * The tracer may want to single-step inside the
-        * handler too.
-        */
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
        return 0;
 
 give_sigsegv:
index 6be7991505019a30ce3ff6268c275a931a088644..307d010696c994d1db638accea596c01ba46ebbf 100644 (file)
@@ -548,6 +548,9 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
        if (!user_mode(regs))
                return 0;
 
+       /* Enable interrupts; they are disabled again on return to caller. */
+       local_irq_enable();
+
        if (thread_info_flags & _TIF_NEED_RESCHED) {
                schedule();
                return 1;
@@ -594,13 +597,13 @@ SYSCALL_DEFINE4(execve, const char __user *, path,
                struct pt_regs *, regs)
 {
        long error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(path);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
        if (error == 0)
                single_step_execve();
@@ -615,13 +618,13 @@ long compat_sys_execve(const char __user *path,
                       struct pt_regs *regs)
 {
        long error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(path);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = compat_do_execve(filename, argv, envp, regs);
+       error = compat_do_execve(filename->name, argv, envp, regs);
        putname(filename);
        if (error == 0)
                single_step_execve();
index e29b0553211d611af9802dfe190f9d0d9d868f69..67efb656d10451946baa827066811948dc45b2d6 100644 (file)
@@ -219,15 +219,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->regs[1] = (unsigned long) &frame->info;
        regs->regs[2] = (unsigned long) &frame->uc;
        regs->flags |= PT_FLAGS_CALLER_SAVES;
-
-       /*
-        * Notify any tracer that was single-stepping it.
-        * The tracer may want to single-step inside the
-        * handler too.
-        */
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
        return 0;
 
 give_sigsegv:
@@ -278,7 +269,8 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
                ret = setup_rt_frame(sig, ka, info, oldset, regs);
        if (ret)
                return;
-       signal_delivered(sig, info, ka, regs, 0);
+       signal_delivered(sig, info, ka, regs,
+                       test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
index 87eebfe03c61aa7de2524ede5d3aac3128aaccb5..c3bba73e4be6d88be5d813d94dcdf01eb2ef4857 100644 (file)
@@ -7,8 +7,8 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include "chan.h"
-#include "os.h"
-#include "irq_kern.h"
+#include <os.h>
+#include <irq_kern.h>
 
 #ifdef CONFIG_NOCONFIG_CHAN
 static void *not_configged_init(char *str, int device,
index f180813ce2c7cb0caf950fa1d90852ab1f0ada55..9be670ad23b5fa6c94bb6b361bb9db59a0924a2d 100644 (file)
@@ -11,8 +11,8 @@
 #include <termios.h>
 #include <sys/ioctl.h>
 #include "chan_user.h"
-#include "os.h"
-#include "um_malloc.h"
+#include <os.h>
+#include <um_malloc.h>
 
 void generic_close(int fd, void *unused)
 {
index 6257b7a6e1afb7f8cdabc672beac7c6f95d6f73f..dc693298eb8fc0a73719d98521f8a4ae9f911dfa 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef __CHAN_USER_H__
 #define __CHAN_USER_H__
 
-#include "init.h"
+#include <init.h>
 
 struct chan_opts {
        void (*const announce)(char *dev_name, int dev);
index 7f2ed0b8824a53ea085be063f860c8a3844b55a1..67cbee63e702ef5948346716e058548092ec5be1 100644 (file)
@@ -1,9 +1,9 @@
 #ifndef __COW_SYS_H__
 #define __COW_SYS_H__
 
-#include "kern_util.h"
-#include "os.h"
-#include "um_malloc.h"
+#include <kern_util.h>
+#include <os.h>
+#include <um_malloc.h>
 
 static inline void *cow_malloc(int size)
 {
index 6e0e891f8a00d0ca52ddcd0ce15b50bce6601c70..c2dd1951559f3376f9db686b11b6d27c7888e14e 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef __DAEMON_H__
 #define __DAEMON_H__
 
-#include "net_user.h"
+#include <net_user.h>
 
 #define SWITCH_VERSION 3
 
index b4a1522f21575bbdc1142e0c8653edf999f6c651..7568cc2f3cd680ef79e3e8ad81e376ccb06ff7bb 100644 (file)
@@ -6,9 +6,9 @@
  * Licensed under the GPL.
  */
 
-#include "linux/init.h"
+#include <linux/init.h>
 #include <linux/netdevice.h>
-#include "net_kern.h"
+#include <net_kern.h>
 #include "daemon.h"
 
 struct daemon_init {
index a4fd7bc14af7ddbf3e290ec2084cc80b40d5c60a..8813c10d0177504f35bfcf58e1b49cffa2a943c8 100644 (file)
@@ -14,9 +14,9 @@
 #include <sys/time.h>
 #include <sys/un.h>
 #include "daemon.h"
-#include "net_user.h"
-#include "os.h"
-#include "um_malloc.h"
+#include <net_user.h>
+#include <os.h>
+#include <um_malloc.h>
 
 enum request_type { REQ_NEW_CONTROL };
 
index 5b81d2574415e8a3984bd228517111c6e1378642..a13a427b996bad391eba6fcac6b60a0baa03a850 100644 (file)
@@ -9,8 +9,8 @@
 #include <errno.h>
 #include <termios.h>
 #include "chan_user.h"
-#include "os.h"
-#include "um_malloc.h"
+#include <os.h>
+#include <um_malloc.h>
 
 struct fd_chan {
        int fd;
index 0345d6206d40c6a03c9fa43097a1914ee195aacc..f99b32a4dbff57e1a539acadfc335f218a007212 100644 (file)
@@ -6,7 +6,7 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <errno.h>
-#include "os.h"
+#include <os.h>
 
 struct dog_data {
        int stdin;
index f9f6a4e205901ee603d56d0167fb3c6e0807e868..9b90fdc4b151d325e9179424b1b4a44878e357ec 100644 (file)
@@ -3,15 +3,15 @@
  * Licensed under the GPL
  */
 
-#include "linux/fs.h"
-#include "linux/module.h"
-#include "linux/slab.h"
-#include "linux/sound.h"
-#include "linux/soundcard.h"
-#include "linux/mutex.h"
-#include "asm/uaccess.h"
-#include "init.h"
-#include "os.h"
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+#include <linux/mutex.h>
+#include <asm/uaccess.h>
+#include <init.h>
+#include <os.h>
 
 struct hostaudio_state {
        int fd;
index 457475f98414392ece09be3dcfbf0578c31f1215..fd9a15b318afdc5066a8a5a1502cc0c185f947dd 100644 (file)
@@ -3,15 +3,15 @@
  * Licensed under the GPL
  */
 
-#include "linux/irqreturn.h"
-#include "linux/kd.h"
-#include "linux/sched.h"
-#include "linux/slab.h"
+#include <linux/irqreturn.h>
+#include <linux/kd.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
 #include "chan.h"
-#include "irq_kern.h"
-#include "irq_user.h"
-#include "kern_util.h"
-#include "os.h"
+#include <irq_kern.h>
+#include <irq_user.h>
+#include <kern_util.h>
+#include <os.h>
 
 #define LINE_BUFSIZE 4096
 
index bae95611e7abc3faa1ccaba25f052cfa4b60b246..138a14526d9c5c140fe4c91caee9c528a63d5680 100644 (file)
@@ -6,12 +6,12 @@
 #ifndef __LINE_H__
 #define __LINE_H__
 
-#include "linux/list.h"
-#include "linux/workqueue.h"
-#include "linux/tty.h"
-#include "linux/interrupt.h"
-#include "linux/spinlock.h"
-#include "linux/mutex.h"
+#include <linux/list.h>
+#include <linux/workqueue.h>
+#include <linux/tty.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include "chan_user.h"
 #include "mconsole_kern.h"
 
index c139ae1d682691771bfc84f8e0f3469cf7682743..8b22535c62ceb71e84276a14ef14f385f6f643d8 100644 (file)
@@ -12,7 +12,7 @@
 #define u32 uint32_t
 #endif
 
-#include "sysdep/ptrace.h"
+#include <sysdep/ptrace.h>
 
 #define MCONSOLE_MAGIC (0xcafebabe)
 #define MCONSOLE_MAX_DATA (512)
index 9efeb6da48bc6c959fd1c87d92fba1057baa07a1..79ccfe6c70787054c61d1116cb42449d562dfca8 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/switch_to.h>
 
-#include "init.h"
-#include "irq_kern.h"
-#include "irq_user.h"
-#include "kern_util.h"
+#include <init.h>
+#include <irq_kern.h>
+#include <irq_user.h>
+#include <kern_util.h>
 #include "mconsole.h"
 #include "mconsole_kern.h"
-#include "os.h"
+#include <os.h>
 
 static int do_unlink_socket(struct notifier_block *notifier,
                            unsigned long what, void *data)
index d2fe07e78958cb521c4aa3e439581da596b85efe..7a0c6a1ad1d4786c70980a2c1a558c4b1d491339 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef __MCONSOLE_KERN_H__
 #define __MCONSOLE_KERN_H__
 
-#include "linux/list.h"
+#include <linux/list.h>
 #include "mconsole.h"
 
 struct mconsole_entry {
index c0ef803c7c709d2178f028585f00c658bf6441c6..62145c27616759dc2cc09fa4196356feed00939b 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/mm.h>
 
 #include <asm/uaccess.h>
-#include "mem_user.h"
+#include <mem_user.h>
 
 /* These are set in mmapper_init, which is called at boot time */
 static unsigned long mmapper_size;
index 458d324f062de9e2caefd413d7301af3951b5ccf..b1314ebf1f7243713e29cd179ff2499f6b12ac3c 100644 (file)
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include "init.h"
-#include "irq_kern.h"
-#include "irq_user.h"
+#include <init.h>
+#include <irq_kern.h>
+#include <irq_user.h>
 #include "mconsole_kern.h"
-#include "net_kern.h"
-#include "net_user.h"
+#include <net_kern.h>
+#include <net_user.h>
 
 #define DRIVER_NAME "uml-netdev"
 
index 05090c37fa8439417dc2cfbd456a39c911a9f7e5..cd14157b556d178d14998a5e024a15629c3491ad 100644 (file)
@@ -11,9 +11,9 @@
 #include <string.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
-#include "net_user.h"
-#include "os.h"
-#include "um_malloc.h"
+#include <net_user.h>
+#include <os.h>
+#include <um_malloc.h>
 
 int tap_open_common(void *dev, char *gate_addr)
 {
index 2b45a1446c86b5bf34f01cfe9d71d19ec1a118cc..10495747ce8ed932c7b65066ccfe46120490b7fd 100644 (file)
@@ -7,7 +7,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include "chan_user.h"
-#include "os.h"
+#include <os.h>
 
 /* This address is used only as a unique identifier */
 static int null_chan;
index 2860525f8ff6d56219e81dd2fe7afa8f3c627c35..be0fb57bd1d7a61d3c34213edced786c357c4197 100644 (file)
@@ -3,9 +3,9 @@
  * Licensed under the GPL.
  */
 
-#include "linux/init.h"
+#include <linux/init.h>
 #include <linux/netdevice.h>
-#include "net_kern.h"
+#include <net_kern.h>
 #include "pcap_user.h"
 
 struct pcap_init {
index 702a75b190ee552876e2e0a7e715e536e3cd154c..c07b9c752c8647185ea2e98e65d3b61115b5773f 100644 (file)
@@ -7,9 +7,9 @@
 #include <pcap.h>
 #include <string.h>
 #include <asm/types.h>
-#include "net_user.h"
+#include <net_user.h>
 #include "pcap_user.h"
-#include "um_malloc.h"
+#include <um_malloc.h>
 
 #define PCAP_FD(p) (*(int *)(p))
 
index d8ba6153f9125bb2d749d850e8630bae6fb80a7b..1ca7c764cc638734e69bd5c507f9cda260ca75bc 100644 (file)
@@ -3,7 +3,7 @@
  * Licensed under the GPL
  */
 
-#include "net_user.h"
+#include <net_user.h>
 
 struct pcap_data {
        char *host_if;
index 1d83d50236e17a6a56e122aad6763b70b9222f9d..40ca5cc275e9eaa68bb1d3b758fb856aba31b816 100644 (file)
@@ -3,16 +3,16 @@
  * Licensed under the GPL
  */
 
-#include "linux/completion.h"
-#include "linux/interrupt.h"
-#include "linux/list.h"
-#include "linux/mutex.h"
-#include "linux/slab.h"
-#include "linux/workqueue.h"
-#include "asm/atomic.h"
-#include "init.h"
-#include "irq_kern.h"
-#include "os.h"
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+#include <init.h>
+#include <irq_kern.h>
+#include <os.h>
 #include "port.h"
 
 struct port_list {
index 7b010b76ddf092cc7cd6322fcf49dd519a4d2ecf..9a8e1b64c22e3dcf4a51845b4a9343adfbc1e144 100644 (file)
@@ -10,9 +10,9 @@
 #include <unistd.h>
 #include <netinet/in.h>
 #include "chan_user.h"
-#include "os.h"
+#include <os.h>
 #include "port.h"
-#include "um_malloc.h"
+#include <um_malloc.h>
 
 struct port_chan {
        int raw;
index cff2b75d31fd7b3bf53be49c75f6a887f8159129..f1fcc2cedb5ef964bdf0a5b73a11d7fd4d2e3cd1 100644 (file)
@@ -12,8 +12,8 @@
 #include <termios.h>
 #include <sys/stat.h>
 #include "chan_user.h"
-#include "os.h"
-#include "um_malloc.h"
+#include <os.h>
+#include <um_malloc.h>
 
 struct pty_chan {
        void (*announce)(char *dev_name, int dev);
index e32c6aa6396fa2df733b807b9252fa9acd755281..9e3a722058279ab1a9b0978f03d61589622e2bb1 100644 (file)
@@ -13,8 +13,8 @@
 #include <linux/miscdevice.h>
 #include <linux/delay.h>
 #include <asm/uaccess.h>
-#include "irq_kern.h"
-#include "os.h"
+#include <irq_kern.h>
+#include <os.h>
 
 /*
  * core module and version information
index e89cfc68fc3e077b526186fefc4bd8b810bff9e4..f597fa7c91d35a3bc33bab043faaf2476d6285a0 100644 (file)
@@ -1,6 +1,6 @@
 #include <string.h>
 #include "slip_common.h"
-#include "net_user.h"
+#include <net_user.h>
 
 int slip_proto_read(int fd, void *buf, int len, struct slip_proto *slip)
 {
index dd2aadc14af0ab6768723bc8fbade09e6c3203b3..ed5249fc0574d18f9de12642c17be2eca38759f5 100644 (file)
@@ -6,7 +6,7 @@
 #include <linux/if_arp.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
-#include "net_kern.h"
+#include <net_kern.h>
 #include "slip.h"
 
 struct slip_init {
index 932b4d69bec20e9929f12426376aa617665be60a..55c290d925f3cd4e756ca1a557b94fefdbe5c839 100644 (file)
 #include <string.h>
 #include <sys/termios.h>
 #include <sys/wait.h>
-#include "net_user.h"
-#include "os.h"
+#include <net_user.h>
+#include <os.h>
 #include "slip.h"
-#include "um_malloc.h"
+#include <um_malloc.h>
 
 static int slip_user_init(void *data, void *dev)
 {
index e376284f0fb7fdc42e1d1e026abe52408501f4d1..4ef11ca7cacf8184d0baa2fb8947c1d966d8eaeb 100644 (file)
@@ -4,11 +4,11 @@
  */
 
 #include <linux/if_arp.h>
-#include "linux/init.h"
+#include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/string.h>
-#include "net_kern.h"
-#include "net_user.h"
+#include <net_kern.h>
+#include <net_user.h>
 #include "slirp.h"
 
 struct slirp_init {
index db4adb639ff82e41c0f3025145953fab810ebb91..c999d187abb9d8a908eda42f342419963273dc35 100644 (file)
@@ -7,8 +7,8 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/wait.h>
-#include "net_user.h"
-#include "os.h"
+#include <net_user.h>
+#include <os.h>
 #include "slirp.h"
 
 static int slirp_user_init(void *data, void *dev)
index 7e86f00701231f665f806b657c6c94f62fc75d42..16fdd0a0f9d617c67b7d99f0aa4317f2fcdfc7aa 100644 (file)
@@ -3,19 +3,19 @@
  * Licensed under the GPL
  */
 
-#include "linux/fs.h"
-#include "linux/tty.h"
-#include "linux/tty_driver.h"
-#include "linux/major.h"
-#include "linux/mm.h"
-#include "linux/init.h"
-#include "linux/console.h"
-#include "asm/termbits.h"
-#include "asm/irq.h"
+#include <linux/fs.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/major.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <asm/termbits.h>
+#include <asm/irq.h>
 #include "ssl.h"
 #include "chan.h"
-#include "init.h"
-#include "irq_user.h"
+#include <init.h>
+#include <irq_user.h>
 #include "mconsole_kern.h"
 
 static const int ssl_version = 1;
index 929b99a261f3a538c2ac25845ab33c8d11dbd96b..827777af3f6d673bcb26570e4e28ccc370cfcd5e 100644 (file)
@@ -3,27 +3,27 @@
  * Licensed under the GPL
  */
 
-#include "linux/posix_types.h"
-#include "linux/tty.h"
-#include "linux/tty_flip.h"
-#include "linux/types.h"
-#include "linux/major.h"
-#include "linux/kdev_t.h"
-#include "linux/console.h"
-#include "linux/string.h"
-#include "linux/sched.h"
-#include "linux/list.h"
-#include "linux/init.h"
-#include "linux/interrupt.h"
-#include "linux/slab.h"
-#include "linux/hardirq.h"
-#include "asm/current.h"
-#include "asm/irq.h"
+#include <linux/posix_types.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/kdev_t.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/hardirq.h>
+#include <asm/current.h>
+#include <asm/irq.h>
 #include "stdio_console.h"
 #include "chan.h"
-#include "irq_user.h"
+#include <irq_user.h>
 #include "mconsole_kern.h"
-#include "init.h"
+#include <init.h>
 
 #define MAX_TTYS (16)
 
index a97391f9ec54eea1c4cd290d87c9b2b243d9fa68..eaa201bca5ed85db9ad0486ae9495498bcfb676a 100644 (file)
@@ -7,8 +7,8 @@
 #include <fcntl.h>
 #include <termios.h>
 #include "chan_user.h"
-#include "os.h"
-#include "um_malloc.h"
+#include <os.h>
+#include <um_malloc.h>
 
 struct tty_chan {
        char *dev;
index 0643e5bc9f41310b78f5b8cc36cc7abb6175e4f3..41bf72073cccafd9bbd918ded89e6263d6883b93 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/scatterlist.h>
 #include <asm/tlbflush.h>
-#include "kern_util.h"
+#include <kern_util.h>
 #include "mconsole_kern.h"
-#include "init.h"
-#include "irq_kern.h"
+#include <init.h>
+#include <irq_kern.h>
 #include "ubd.h"
-#include "os.h"
+#include <os.h>
 #include "cow.h"
 
 enum ubd_req { UBD_READ, UBD_WRITE };
index ffe02c431dea9b4f2def4acb8781a6308943e308..a703e45d8aac3d421da9b25d6622e98de01a36b9 100644 (file)
@@ -19,7 +19,7 @@
 #include <byteswap.h>
 
 #include "ubd.h"
-#include "os.h"
+#include <os.h>
 
 void ignore_sigwinch_sig(void)
 {
index 6f8c0fe890fb89ee53e3ea0160ded80f586bb1b0..c190c64409119596b015cdf1208c6c251235c33d 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef __DRIVERS_UMCAST_H
 #define __DRIVERS_UMCAST_H
 
-#include "net_user.h"
+#include <net_user.h>
 
 struct umcast_data {
        char *addr;
index 42dab11d2ecf5e76482c40005c590f3962c1c067..f5ba6e377913b479a74bfb3bd433dd2f0146af92 100644 (file)
  * Licensed under the GPL.
  */
 
-#include "linux/init.h"
+#include <linux/init.h>
 #include <linux/netdevice.h>
 #include "umcast.h"
-#include "net_kern.h"
+#include <net_kern.h>
 
 struct umcast_init {
        char *addr;
index 010fa2d849ecbf501c652914afe51737705261bc..6074184bb51b5eb13d74d13b32a92f1364031d39 100644 (file)
@@ -16,8 +16,8 @@
 #include <errno.h>
 #include <netinet/in.h>
 #include "umcast.h"
-#include "net_user.h"
-#include "um_malloc.h"
+#include <net_user.h>
+#include <um_malloc.h>
 
 static struct sockaddr_in *new_addr(char *addr, unsigned short port)
 {
index 1b852bffdebcf019d61c66dda7f4da77e4e1ff1f..6a365fadc7c4d90e73891b0db71cdc3b4bb49312 100644 (file)
@@ -7,10 +7,10 @@
  *
  */
 
-#include "linux/init.h"
+#include <linux/init.h>
 #include <linux/netdevice.h>
-#include "net_kern.h"
-#include "net_user.h"
+#include <net_kern.h>
+#include <net_user.h>
 #include "vde.h"
 
 static void vde_init(struct net_device *dev, void *data)
index b8c286748d3d3be5008a9c30e070948f56941d20..64cb630d11573df6fdb5c0e1379e1346475ce820 100644 (file)
@@ -6,8 +6,8 @@
 #include <stddef.h>
 #include <errno.h>
 #include <libvdeplug.h>
-#include "net_user.h"
-#include "um_malloc.h"
+#include <net_user.h>
+#include <um_malloc.h>
 #include "vde.h"
 
 static int vde_user_init(void *data, void *dev)
index 969110e56487cef57ea99787cb77890a84e81876..20e30be44795b2d957402601180dc1684363ae91 100644 (file)
@@ -11,8 +11,8 @@
 #include <string.h>
 #include <termios.h>
 #include "chan_user.h"
-#include "os.h"
-#include "um_malloc.h"
+#include <os.h>
+#include <um_malloc.h>
 #include "xterm.h"
 
 struct xterm_chan {
index e3031e69445d133d94a0e335dfd485bd04c17a4b..e8f9957bfbf6bad39a17812298a194f4f39b882e 100644 (file)
@@ -7,8 +7,8 @@
 #include <linux/completion.h>
 #include <linux/irqreturn.h>
 #include <asm/irq.h>
-#include "irq_kern.h"
-#include "os.h"
+#include <irq_kern.h>
+#include <os.h>
 
 struct xterm_wait {
        struct completion ready;
index 9f6139a8a525c5ae3f157b4e6e86f160910d4a50..f88c5860520b03d099523327ab32e20d92877f30 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __UM_DMA_H
 #define __UM_DMA_H
 
-#include "asm/io.h"
+#include <asm/io.h>
 
 extern unsigned long uml_physmem;
 
index 53e8b498ebbaf139a98cfc8628b4232713ee9b92..da705448590f2fea52f4f44c913ac1bad54bb123 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef __ARCH_UM_MMU_H
 #define __ARCH_UM_MMU_H
 
-#include "mm_id.h"
+#include <mm_id.h>
 #include <asm/mm_context.h>
 
 typedef struct mm_context {
index 7cfc3cedce8411b392a7c96f5104a24022e58bce..5ff53d9185f7f81260f4b41f46226ed1683a836a 100644 (file)
@@ -99,7 +99,7 @@ extern unsigned long uml_physmem;
 
 #define __va_space (8*1024*1024)
 
-#include "mem.h"
+#include <mem.h>
 
 /* Cast to unsigned long before casting to void * to avoid a warning from
  * mmap_kmem about cutting a long long down to a void *.  Not sure that
index 5888f1b834771a102a7d212581ec1f3eb9aff3b2..ae02909a18752adebe5657aef42c620a629d3293 100644 (file)
@@ -23,9 +23,9 @@
                                   pte_present gives true */
 
 #ifdef CONFIG_3_LEVEL_PGTABLES
-#include "asm/pgtable-3level.h"
+#include <asm/pgtable-3level.h>
 #else
-#include "asm/pgtable-2level.h"
+#include <asm/pgtable-2level.h>
 #endif
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
index 33a6a2423bd25638a2b93f20fdc77bcf6e0f1737..c03cd5a02364493fe83c81261eb45c0689bcfed8 100644 (file)
@@ -10,9 +10,9 @@ struct pt_regs;
 
 struct task_struct;
 
-#include "asm/ptrace.h"
-#include "registers.h"
-#include "sysdep/archsetjmp.h"
+#include <asm/ptrace.h>
+#include <registers.h>
+#include <sysdep/archsetjmp.h>
 
 #include <linux/prefetch.h>
 
@@ -26,7 +26,6 @@ struct thread_struct {
        jmp_buf *fault_catcher;
        struct task_struct *prev_sched;
        unsigned long temp_stack;
-       jmp_buf *exec_buf;
        struct arch_thread arch;
        jmp_buf switch_buf;
        int mm_count;
@@ -54,7 +53,6 @@ struct thread_struct {
        .fault_addr             = NULL, \
        .prev_sched             = NULL, \
        .temp_stack             = 0, \
-       .exec_buf               = NULL, \
        .arch                   = INIT_ARCH_THREAD, \
        .request                = { 0 } \
 }
@@ -63,8 +61,6 @@ static inline void release_thread(struct task_struct *task)
 {
 }
 
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 extern unsigned long thread_saved_pc(struct task_struct *t);
 
 static inline void mm_copy_segments(struct mm_struct *from_mm,
index 442f1d025dc2f838096eaa5a77c066933a1db58d..cb9b3c47ca8e1cc679d4213d7eba8e271066419c 100644 (file)
@@ -9,7 +9,7 @@
 #ifndef __ASSEMBLY__
 
 #include <asm/ptrace-abi.h>
-#include "sysdep/ptrace.h"
+#include <sysdep/ptrace.h>
 
 struct pt_regs {
        struct uml_pt_regs regs;
index 4a4b09d4f36648c0bf85724aa9533d9890403a07..e4507938d8cfa948a502632e12796feeca1d816f 100644 (file)
@@ -3,9 +3,9 @@
 
 #ifdef CONFIG_SMP
 
-#include "linux/bitops.h"
-#include "asm/current.h"
-#include "linux/cpumask.h"
+#include <linux/bitops.h>
+#include <asm/current.h>
+#include <linux/cpumask.h>
 
 #define raw_smp_processor_id() (current_thread->cpu)
 
index c04e5ab68f56a3f14d3831c501c3af66b0d2610b..2c8eeb2df8b43a6c21b4b10da99fe1042276229f 100644 (file)
@@ -65,8 +65,6 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_TRACE      0       /* syscall trace active */
 #define TIF_SIGPENDING         1       /* signal pending */
 #define TIF_NEED_RESCHED       2       /* rescheduling necessary */
-#define TIF_POLLING_NRFLAG      3       /* true if poll_idle() is polling
-                                        * TIF_NEED_RESCHED */
 #define TIF_RESTART_BLOCK      4
 #define TIF_MEMDIE             5       /* is terminating due to OOM killer */
 #define TIF_SYSCALL_AUDIT      6
@@ -76,7 +74,6 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
 #define _TIF_MEMDIE            (1 << TIF_MEMDIE)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 
index 2de92a08a76bb7eaeb81fe408ee5bd1ced7ce0a7..4f46abda060d17ef2621a001b4be6101ea0b20bc 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef __ARCH_H__
 #define __ARCH_H__
 
-#include "sysdep/ptrace.h"
+#include <sysdep/ptrace.h>
 
 extern void arch_check_bugs(void);
 extern int arch_fixup(unsigned long address, struct uml_pt_regs *regs);
index 86daa546181568fb10b860c76f428b1f1a12dc47..694c792bab4ec71b0829c110e59c6d774ec6223f 100644 (file)
@@ -35,7 +35,7 @@
 
 #ifndef __ASSEMBLY__
 
-#include "sysdep/ptrace.h"
+#include <sysdep/ptrace.h>
 
 struct cpu_task {
        int pid;
index 7a5bfa6291b807c039ab5f150e357266b415b414..e05bd667de152e06038daec8dd86dda7075ed7bb 100644 (file)
@@ -6,8 +6,8 @@
 #ifndef __IRQ_KERN_H__
 #define __IRQ_KERN_H__
 
-#include "linux/interrupt.h"
-#include "asm/ptrace.h"
+#include <linux/interrupt.h>
+#include <asm/ptrace.h>
 
 extern int um_request_irq(unsigned int irq, int fd, int type,
                          irq_handler_t handler,
index 2b6d703925b57c8ea862ef7fd1706c8770f42396..df5633053957d309d91fde9ea2ab743d79693e2e 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef __IRQ_USER_H__
 #define __IRQ_USER_H__
 
-#include "sysdep/ptrace.h"
+#include <sysdep/ptrace.h>
 
 struct irq_fd {
        struct irq_fd *next;
index af6b6dc868bab6b82e1351250edcc1d62f873285..83a91f9763302a5fca9b1516fbc958f05adfd9e9 100644 (file)
@@ -6,8 +6,8 @@
 #ifndef __KERN_UTIL_H__
 #define __KERN_UTIL_H__
 
-#include "sysdep/ptrace.h"
-#include "sysdep/faultinfo.h"
+#include <sysdep/ptrace.h>
+#include <sysdep/faultinfo.h>
 
 struct siginfo;
 
index e860bc5848e0aaff10b382f185aed8b5a4acd81e..9bdddf4c405b4012aaf52226378cd1d03cad7c67 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef __UML_LONGJMP_H
 #define __UML_LONGJMP_H
 
-#include "sysdep/archsetjmp.h"
-#include "os.h"
+#include <sysdep/archsetjmp.h>
+#include <os.h>
 
 extern int setjmp(jmp_buf);
 extern void longjmp(jmp_buf, int);
index 89b686c1a3ea8f9703354c2c1cafd8bb6635cd26..95feaa47a2fbb369512daeb67ffdc19554f837ad 100644 (file)
@@ -7,9 +7,9 @@
 #define __OS_H__
 
 #include <stdarg.h>
-#include "irq_user.h"
-#include "longjmp.h"
-#include "mm_id.h"
+#include <irq_user.h>
+#include <longjmp.h>
+#include <mm_id.h>
 
 #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
 
@@ -191,7 +191,6 @@ extern int os_getpid(void);
 extern int os_getpgrp(void);
 
 extern void init_new_thread_signals(void);
-extern int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr);
 
 extern int os_map_memory(void *virt, int fd, unsigned long long off,
                         unsigned long len, int r, int w, int x);
index f1e0aa56c52a859fb4302791ad2f267d7b0a171c..f5b76355ad71af70a4f7b5ed6643a7df5016b198 100644 (file)
@@ -6,8 +6,8 @@
 #ifndef __REGISTERS_H
 #define __REGISTERS_H
 
-#include "sysdep/ptrace.h"
-#include "sysdep/archsetjmp.h"
+#include <sysdep/ptrace.h>
+#include <sysdep/archsetjmp.h>
 
 extern int save_fp_registers(int pid, unsigned long *fp_regs);
 extern int restore_fp_registers(int pid, unsigned long *fp_regs);
index 64d2c74433060601c1c5a847fde0c64849178381..c45df961c874dd157334057370321b8040441c9e 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef __SKAS_H
 #define __SKAS_H
 
-#include "sysdep/ptrace.h"
+#include <sysdep/ptrace.h>
 
 extern int userspace_pid[];
 extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
index 3d31bbacd016c910bfcc311892a0f7789bdae8e8..630a9c92b93c7befd8e5b7a5b59a5dc18e35562d 100644 (file)
@@ -9,6 +9,6 @@
 #define PTRACE_FAULTINFO 52
 #define PTRACE_SWITCH_MM 55
 
-#include "sysdep/skas_ptrace.h"
+#include <sysdep/skas_ptrace.h>
 
 #endif
index 91ea538e1612b5d75e6c645436936ad2820460d0..1fb12235ab9c8479a0c81aca2fd4b9d10ff20c69 100644 (file)
@@ -1 +1 @@
-#include "sysdep/kernel-offsets.h"
+#include <sysdep/kernel-offsets.h>
index b7a43feafde773aeb4998675be30074ee5613c32..972bf1659564fc640fe630771dc2d82e6af315b5 100644 (file)
@@ -5,7 +5,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include "init.h"
+#include <init.h>
 
 static __initdata const char *config[] = {
 "CONFIG"
index a3cab6d3ae020ccbb1701742e3e85c5c8d2af161..fb8fd6fb6563f6305a808973f748ffea438a9597 100644 (file)
@@ -89,7 +89,7 @@ SECTIONS
 
   .kstrtab : { *(.kstrtab) }
 
-  #include "asm/common.lds.S"
+  #include <asm/common.lds.S>
 
   init.data : { INIT_DATA }
 
index ec649bf72f68c6217d52c91c45401dfe17123e91..49480f09245647c592c3f74228e9bf9063f79451 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/console.h>
 #include <linux/init.h>
-#include "os.h"
+#include <os.h>
 
 static void early_console_write(struct console *con, const char *s, unsigned int n)
 {
index 8c82786da823df2cdf53ad9361b9b950d85018c7..3a8ece7d09ca2015b3e2c218a3e7a84e951d9bee 100644 (file)
 #include <asm/current.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
-#include "as-layout.h"
-#include "mem_user.h"
-#include "skas.h"
-#include "os.h"
-#include "internal.h"
+#include <as-layout.h>
+#include <mem_user.h>
+#include <skas.h>
+#include <os.h>
 
 void flush_thread(void)
 {
@@ -48,28 +47,3 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
 #endif
 }
 EXPORT_SYMBOL(start_thread);
-
-long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env)
-{
-       long err;
-
-       err = do_execve(file, argv, env, &current->thread.regs);
-       if (!err)
-               UML_LONGJMP(current->thread.exec_buf, 1);
-       return err;
-}
-
-long sys_execve(const char __user *file, const char __user *const __user *argv,
-               const char __user *const __user *env)
-{
-       long error;
-       char *filename;
-
-       filename = getname(file);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename)) goto out;
-       error = do_execve(filename, argv, env, &current->thread.regs);
-       putname(filename);
- out:
-       return error;
-}
index e9bcf247bcee1ff323db3fdff6ee49b4465480c6..1bf61266da8e1e355ef7c1377dcff22f21385ce9 100644 (file)
@@ -3,7 +3,7 @@
  * Licensed under the GPL
  */
 
-#include "linux/module.h"
+#include <linux/module.h>
 
 extern void __bb_init_func(void *)  __attribute__((weak));
 EXPORT_SYMBOL(__bb_init_func);
index e2f043d0de6c80fd0050aedb0edf1748efbdb72b..74ddb44288a30caba1bc0f4a49aa9d402d5850ea 100644 (file)
@@ -3,7 +3,7 @@
  * Licensed under the GPL
  */
 
-#include "linux/module.h"
+#include <linux/module.h>
 
 extern void mcount(void);
 EXPORT_SYMBOL(mcount);
index 10cc18f729fdde317b4fea334f0d8604ae3c5baf..55cead809b18baccf804dd89dafec13c37eb0af0 100644 (file)
@@ -3,12 +3,12 @@
  * Licensed under the GPL
  */
 
-#include "linux/init.h"
-#include "linux/bootmem.h"
-#include "linux/initrd.h"
-#include "asm/types.h"
-#include "init.h"
-#include "os.h"
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/initrd.h>
+#include <asm/types.h>
+#include <init.h>
+#include <os.h>
 
 /* Changed by uml_initrd_setup, which is a setup */
 static char *initrd __initdata = NULL;
diff --git a/arch/um/kernel/internal.h b/arch/um/kernel/internal.h
deleted file mode 100644 (file)
index 5bf97db..0000000
+++ /dev/null
@@ -1 +0,0 @@
-extern long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env);
index 9883026f0730ca89f7acde365d51a26e2929d933..36e12f0cefd5e95a688df0c56e0390377ded2028 100644 (file)
@@ -5,17 +5,17 @@
  *     Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
  */
 
-#include "linux/cpumask.h"
-#include "linux/hardirq.h"
-#include "linux/interrupt.h"
-#include "linux/kernel_stat.h"
-#include "linux/module.h"
-#include "linux/sched.h"
-#include "linux/seq_file.h"
-#include "linux/slab.h"
-#include "as-layout.h"
-#include "kern_util.h"
-#include "os.h"
+#include <linux/cpumask.h>
+#include <linux/hardirq.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <as-layout.h>
+#include <kern_util.h>
+#include <os.h>
 
 /*
  * This list is accessed under irq_lock, except in sigio_handler,
index e17bea0b22e179a2f1cd364dcf1dc5ffa076b216..543c047569393ec46bdbfacc370ed71535dd5d14 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 #include <linux/module.h>
-#include "os.h"
+#include <os.h>
 
 EXPORT_SYMBOL(set_signals);
 EXPORT_SYMBOL(get_signals);
index ebb86b2184456396cf723fcef4b3981a4c68703d..5abcbfbe7e2586857ddc48a41b3a1af7fdc5f02c 100644 (file)
 #include <linux/slab.h>
 #include <asm/fixmap.h>
 #include <asm/page.h>
-#include "as-layout.h"
-#include "init.h"
-#include "kern.h"
-#include "kern_util.h"
-#include "mem_user.h"
-#include "os.h"
+#include <as-layout.h>
+#include <init.h>
+#include <kern.h>
+#include <kern_util.h>
+#include <mem_user.h>
+#include <os.h>
 
 /* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
 unsigned long *empty_zero_page = NULL;
index c5f5afa5074571c2b5872bc157c9f199a80c9f5b..b6d699cdd55789ae51229e6256609c406cd9f959 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 #include <asm/uaccess.h>
-#include "as-layout.h"
-#include "kern_util.h"
-#include "os.h"
-#include "skas.h"
+#include <as-layout.h>
+#include <kern_util.h>
+#include <os.h>
+#include <skas.h>
 
 /*
  * This is a per-cpu array.  A processor only modifies its entry and it only
@@ -69,18 +69,6 @@ unsigned long alloc_stack(int order, int atomic)
        return page;
 }
 
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-       int pid;
-
-       current->thread.request.u.thread.proc = fn;
-       current->thread.request.u.thread.arg = arg;
-       pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
-                     &current->thread.regs, 0, NULL, NULL);
-       return pid;
-}
-EXPORT_SYMBOL(kernel_thread);
-
 static inline void set_current(struct task_struct *task)
 {
        cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
@@ -147,14 +135,10 @@ void new_thread_handler(void)
        arg = current->thread.request.u.thread.arg;
 
        /*
-        * The return value is 1 if the kernel thread execs a process,
-        * 0 if it just exits
+        * callback returns only if the kernel thread execs a process
         */
-       n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
-       if (n == 1)
-               userspace(&current->thread.regs.regs);
-       else
-               do_exit(0);
+       n = fn(arg);
+       userspace(&current->thread.regs.regs);
 }
 
 /* Called magically, see new_thread_handler above */
@@ -177,7 +161,7 @@ void fork_handler(void)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long sp,
-               unsigned long stack_top, struct task_struct * p,
+               unsigned long arg, struct task_struct * p,
                struct pt_regs *regs)
 {
        void (*handler)(void);
@@ -198,7 +182,8 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
                arch_copy_thread(&current->thread.arch, &p->thread.arch);
        } else {
                get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp);
-               p->thread.request.u.thread = current->thread.request.u.thread;
+               p->thread.request.u.thread.proc = (int (*)(void *))sp;
+               p->thread.request.u.thread.arg = (void *)arg;
                handler = new_thread_handler;
        }
 
index 3d15243ce69234c3ddbac961ef58b0282247a4e4..ced8903921aeb61a255edde5f69cb86a98a2b70e 100644 (file)
@@ -3,13 +3,13 @@
  * Licensed under the GPL
  */
 
-#include "linux/sched.h"
-#include "linux/spinlock.h"
-#include "linux/slab.h"
-#include "linux/oom.h"
-#include "kern_util.h"
-#include "os.h"
-#include "skas.h"
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/oom.h>
+#include <kern_util.h>
+#include <os.h>
+#include <skas.h>
 
 void (*pm_power_off)(void);
 
index c88211139a5160ba5b18fa3117445e2b5f351423..b5e0cbb34382845056c9d4c8625212122b79c81e 100644 (file)
@@ -4,9 +4,9 @@
  */
 
 #include <linux/interrupt.h>
-#include "irq_kern.h"
-#include "os.h"
-#include "sigio.h"
+#include <irq_kern.h>
+#include <os.h>
+#include <sigio.h>
 
 /* Protected by sigio_lock() called from write_sigio_workaround */
 static int sigio_irq_fd = -1;
index cc9c2350e41741647f074cc4f43d6c4e3599123f..db18eb6124e17d8c36f2e00af8a592230df92bdc 100644 (file)
@@ -9,8 +9,8 @@
 #include <asm/siginfo.h>
 #include <asm/signal.h>
 #include <asm/unistd.h>
-#include "frame_kern.h"
-#include "kern_util.h"
+#include <frame_kern.h>
+#include <kern_util.h>
 
 EXPORT_SYMBOL(block_signals);
 EXPORT_SYMBOL(unblock_signals);
index e1fd066a3525c20f4820c0227c42613984edabd4..289771dadf81f9343816e6c81176a626a52a8dbb 100644 (file)
@@ -7,10 +7,10 @@
 #include <sched.h>
 #include <asm/unistd.h>
 #include <sys/time.h>
-#include "as-layout.h"
-#include "ptrace_user.h"
-#include "stub-data.h"
-#include "sysdep/stub.h"
+#include <as-layout.h>
+#include <ptrace_user.h>
+#include <stub-data.h>
+#include <sysdep/stub.h>
 
 /*
  * This is in a separate file because it needs to be compiled with any
index 0a49ef0c2bf48995cb063ea425a10b91d11c8c96..ff03067a3b1496acf3725019b31ed17020ea5233 100644 (file)
@@ -3,14 +3,14 @@
  * Licensed under the GPL
  */
 
-#include "linux/mm.h"
-#include "linux/sched.h"
-#include "linux/slab.h"
-#include "asm/pgalloc.h"
-#include "asm/pgtable.h"
-#include "as-layout.h"
-#include "os.h"
-#include "skas.h"
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <as-layout.h>
+#include <os.h>
+#include <skas.h>
 
 extern int __syscall_stub_start;
 
index 0a9e57e7446b277ed8cdcfdda3e29c17cc257f57..4da11b3c8ddbc31af5b4a360f487769d84fcf60a 100644 (file)
@@ -3,12 +3,12 @@
  * Licensed under the GPL
  */
 
-#include "linux/init.h"
-#include "linux/sched.h"
-#include "as-layout.h"
-#include "kern.h"
-#include "os.h"
-#include "skas.h"
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <as-layout.h>
+#include <kern.h>
+#include <os.h>
+#include <skas.h>
 
 int new_mm(unsigned long stack)
 {
index 86368a025a9684e0bb4dea3707128c4693befe7c..c0681e0974329d783eca8ccb774cbd9b701ae947 100644 (file)
@@ -3,11 +3,11 @@
  * Licensed under the GPL
  */
 
-#include "linux/kernel.h"
-#include "linux/ptrace.h"
-#include "kern_util.h"
-#include "sysdep/ptrace.h"
-#include "sysdep/syscalls.h"
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+#include <kern_util.h>
+#include <sysdep/ptrace.h>
+#include <sysdep/syscalls.h>
 
 extern int syscall_table_size;
 #define NR_SYSCALLS (syscall_table_size / sizeof(void *))
index cd7df79c6a562cb114fe5b32cad143677944d6a8..1d3e0c17340b1e12442e5e61a50ce05bd5a6c1b4 100644 (file)
@@ -11,8 +11,8 @@
 #include <asm/current.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include "kern_util.h"
-#include "os.h"
+#include <kern_util.h>
+#include <os.h>
 
 pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr)
 {
index a02b7e9e6b94c0052d502876f3a47095f9793b94..5c8c3ea7db7b7c9d25c43f94c02be097389315ae 100644 (file)
@@ -3,24 +3,24 @@
  * Licensed under the GPL
  */
 
-#include "linux/percpu.h"
-#include "asm/pgalloc.h"
-#include "asm/tlb.h"
+#include <linux/percpu.h>
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
 
 #ifdef CONFIG_SMP
 
-#include "linux/sched.h"
-#include "linux/module.h"
-#include "linux/threads.h"
-#include "linux/interrupt.h"
-#include "linux/err.h"
-#include "linux/hardirq.h"
-#include "asm/smp.h"
-#include "asm/processor.h"
-#include "asm/spinlock.h"
-#include "kern.h"
-#include "irq_user.h"
-#include "os.h"
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/threads.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/hardirq.h>
+#include <asm/smp.h>
+#include <asm/processor.h>
+#include <asm/spinlock.h>
+#include <kern.h>
+#include <irq_user.h>
+#include <os.h>
 
 /* Per CPU bogomips and other parameters
  * The only piece used here is the ipi pipe, which is set before SMP is
index a4c6d8eee74c702999cc26955e250f40db30f553..a81f3705e90f6e23448ab827c5e980fa8306d9e6 100644 (file)
@@ -3,17 +3,16 @@
  * Licensed under the GPL
  */
 
-#include "linux/file.h"
-#include "linux/fs.h"
-#include "linux/mm.h"
-#include "linux/sched.h"
-#include "linux/utsname.h"
-#include "linux/syscalls.h"
-#include "asm/current.h"
-#include "asm/mman.h"
-#include "asm/uaccess.h"
-#include "asm/unistd.h"
-#include "internal.h"
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/utsname.h>
+#include <linux/syscalls.h>
+#include <asm/current.h>
+#include <asm/mman.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
 
 long sys_fork(void)
 {
@@ -50,19 +49,3 @@ long old_mmap(unsigned long addr, unsigned long len,
  out:
        return err;
 }
-
-int kernel_execve(const char *filename,
-                 const char *const argv[],
-                 const char *const envp[])
-{
-       mm_segment_t fs;
-       int ret;
-
-       fs = get_fs();
-       set_fs(KERNEL_DS);
-       ret = um_execve(filename, (const char __user *const __user *)argv,
-                       (const char __user *const __user *) envp);
-       set_fs(fs);
-
-       return ret;
-}
index 0960de54495abf48e7f290c024cb3877f70e1c69..e562ff80409ab9f72f220ee5db5993ff8ec7ebcf 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/sched.h>
-#include "sysrq.h"
+#include <asm/sysrq.h>
 
 /* Catch non-i386 SUBARCH's. */
 #if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
index 5f76d4ba151cf0b9cf79f099f8568061a63a631d..117568d4f64ab2bb3ebcf448f62c5f925612d2b8 100644 (file)
@@ -10,8 +10,8 @@
 #include <linux/threads.h>
 #include <asm/irq.h>
 #include <asm/param.h>
-#include "kern_util.h"
-#include "os.h"
+#include <kern_util.h>
+#include <os.h>
 
 void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
 {
index f819af951c19004b61be77050e699ed8897cb45d..9472079471bbfbbac8e24632ae5b79444f47e646 100644 (file)
@@ -8,10 +8,10 @@
 #include <linux/sched.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
-#include "as-layout.h"
-#include "mem_user.h"
-#include "os.h"
-#include "skas.h"
+#include <as-layout.h>
+#include <mem_user.h>
+#include <os.h>
+#include <skas.h>
 
 struct host_vm_change {
        struct host_vm_op {
index 0f00e9c82080f644030191cb31bc7ae3e0937f49..089f3987e273a2c3f9576ef923dbd8ba8648cca5 100644 (file)
 #include <asm/current.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
-#include "arch.h"
-#include "as-layout.h"
-#include "kern_util.h"
-#include "os.h"
-#include "skas.h"
+#include <arch.h>
+#include <as-layout.h>
+#include <kern_util.h>
+#include <os.h>
+#include <skas.h>
 
 /*
  * Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by
index 4db8770906caa90ee3ec29ec5554a13ee8788a74..87df5e3acc26eaa35798da9e8d2818ae2a6a5d70 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/setup.h>
-#include "as-layout.h"
-#include "arch.h"
-#include "init.h"
-#include "kern.h"
-#include "kern_util.h"
-#include "mem_user.h"
-#include "os.h"
+#include <as-layout.h>
+#include <arch.h>
+#include <init.h>
+#include <kern.h>
+#include <kern_util.h>
+#include <mem_user.h>
+#include <os.h>
 
 #define DEFAULT_COMMAND_LINE "root=98:0"
 
index 81e07e2be3ae540abb2715ca56824f02b79c6cea..f6cc3bd61781fec02c8b636d128e638308a376c0 100644 (file)
@@ -4,9 +4,9 @@
  */
 
 #include <asm/errno.h>
-#include "init.h"
-#include "kern.h"
-#include "os.h"
+#include <init.h>
+#include <kern.h>
+#include <os.h>
 
 /* Changed by set_umid_arg */
 static int umid_inited = 0;
index fbd99402d4d26219443f3d46c3b355b3c137790e..ff65fb4f1a95487f7a13940a986dac6380138006 100644 (file)
@@ -60,7 +60,7 @@ SECTIONS
        PROVIDE_HIDDEN(__rela_iplt_end = .);
   }
 
-  #include "asm/common.lds.S"
+  #include <asm/common.lds.S>
 
   init.data : { INIT_DATA }
   .data    :
index c5d039e1ff3b779736d987c213dc3e062160d66f..3a6bc2af09615378886ebcc6a15f2f439cbb4407 100644 (file)
@@ -9,10 +9,10 @@
 #include <errno.h>
 #include <sys/time.h>
 #include <asm/unistd.h>
-#include "aio.h"
-#include "init.h"
-#include "kern_util.h"
-#include "os.h"
+#include <aio.h>
+#include <init.h>
+#include <kern_util.h>
+#include <os.h>
 
 struct aio_thread_req {
        enum aio_type type;
index ddffd41c3f3f9898e68288a6cf3034d53c5b73b5..54183a679fdd52092306edbe1d8fe064b0d0d6e9 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef __DRIVERS_ETAP_H
 #define __DRIVERS_ETAP_H
 
-#include "net_user.h"
+#include <net_user.h>
 
 struct ethertap_data {
        char *dev_name;
index 7f6f9a71aae40e04db6ff38f901589e38aa54906..f424600a583f9afa3b42cc0ab2d0ecac16d4dbc5 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include "etap.h"
-#include "net_kern.h"
+#include <net_kern.h>
 
 struct ethertap_init {
        char *dev_name;
index db3d6481375a7c55cf5885771093f9a784d1db43..b39b6696ac58313b9c40ef3ba7b1a3bf8a3505c6 100644 (file)
@@ -13,9 +13,9 @@
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include "etap.h"
-#include "os.h"
-#include "net_user.h"
-#include "um_malloc.h"
+#include <os.h>
+#include <net_user.h>
+#include <um_malloc.h>
 
 #define MAX_PACKET ETH_MAX_PACKET
 
index f17c31586c8440b829bc1f14b2c9952aa2d386db..7367354ac8df6e548cb1b94eab806e0b8263c452 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef __UM_TUNTAP_H
 #define __UM_TUNTAP_H
 
-#include "net_user.h"
+#include <net_user.h>
 
 struct tuntap_data {
        char *dev_name;
index 4048800e4696a97612b3b2d282a024b3cbd86a96..d9d56e5810fe179f5f606b36a1d0c9c76a7d5b89 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/init.h>
 #include <linux/skbuff.h>
 #include <asm/errno.h>
-#include "net_kern.h"
+#include <net_kern.h>
 #include "tuntap.h"
 
 struct tuntap_init {
index a2aacffdd907d1830aab84ba1148dd72450caa98..14126d9176aa35bb368bfed159e002455aa4ed77 100644 (file)
@@ -13,8 +13,8 @@
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include <sys/uio.h>
-#include "kern_util.h"
-#include "os.h"
+#include <kern_util.h>
+#include <os.h>
 #include "tuntap.h"
 
 static int tuntap_user_init(void *data, void *dev)
index d895271ad6f711485c94b6c8c17ebeb3d4314366..1a365ddc4d023698dfa5f4d3e6eff08816661952 100644 (file)
@@ -9,9 +9,9 @@
  */
 #include <elf.h>
 #include <stddef.h>
-#include "init.h"
-#include "elf_user.h"
-#include "mem_user.h"
+#include <init.h>
+#include <elf_user.h>
+#include <mem_user.h>
 
 typedef Elf32_auxv_t elf_auxv_t;
 
index 66e583a4031b90aaf81ca0045f61a7ef5d882284..8fb25ca07c46f759c17ae96df68277aec7616d0c 100644 (file)
 #include <limits.h>
 
 #ifndef TEST
-#include "um_malloc.h"
+#include <um_malloc.h>
 #else
 #include <stdio.h>
 #define um_kmalloc malloc
 #endif
-#include "os.h"
+#include <os.h>
 
 /* Execute FILE, searching in the `PATH' environment variable if it contains
    no slashes, with arguments ARGV and environment from `environ'.  */
index b049a63bb74b060899888fdc731ca5cd5a137eee..c17bd6f7d674d98ad745ffb21c0ccab11fd515b9 100644 (file)
@@ -13,7 +13,7 @@
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/un.h>
-#include "os.h"
+#include <os.h>
 
 static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
 {
index cf26c4a9a43a7c38549a2bcd76564eb554c32409..e3ee4a51ef63a3ec7e7314aa7f00d59ec93ce37e 100644 (file)
@@ -10,9 +10,9 @@
 #include <linux/limits.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
-#include "kern_util.h"
-#include "os.h"
-#include "um_malloc.h"
+#include <kern_util.h>
+#include <os.h>
+#include <um_malloc.h>
 
 struct helper_data {
        void (*pre_exec)(void*);
index 9a49908b576c20c80c124854f04167081873cb7c..b9afb74b79ad05d1d1f3e967057e3152283c42eb 100644 (file)
@@ -8,9 +8,9 @@
 #include <poll.h>
 #include <signal.h>
 #include <string.h>
-#include "irq_user.h"
-#include "os.h"
-#include "um_malloc.h"
+#include <irq_user.h>
+#include <os.h>
+#include <um_malloc.h>
 
 /*
  * Locked by irq_lock in arch/um/kernel/irq.c.  Changed by os_create_pollfd
index 7a86dd516eb185476232df8581bee12b38bed196..749c96da7b99492a4656faf29be190fa9908b330 100644 (file)
 #include <signal.h>
 #include <string.h>
 #include <sys/resource.h>
-#include "as-layout.h"
-#include "init.h"
-#include "kern_util.h"
-#include "os.h"
-#include "um_malloc.h"
+#include <as-layout.h>
+#include <init.h>
+#include <kern_util.h>
+#include <os.h>
+#include <um_malloc.h>
 
 #define PGD_BOUND (4 * 1024 * 1024)
 #define STACKSIZE (8 * 1024 * 1024)
index 8e421e1d6d365450947771828160753d83c4c60b..ba4398056fe904d3fc85e024eee8687151cd5804 100644 (file)
@@ -13,8 +13,8 @@
 #include <sys/stat.h>
 #include <sys/mman.h>
 #include <sys/param.h>
-#include "init.h"
-#include "os.h"
+#include <init.h>
+#include <os.h>
 
 /* Modified by which_tmpdir, which is called during early boot */
 static char *default_tmpdir = "/tmp";
index 307f173e7f82fec41a5bc74b28d796783bafe08e..b8f34c9e53ae9fc820f81e215253ec2bc70f9ffc 100644 (file)
 #include <sys/ptrace.h>
 #include <sys/wait.h>
 #include <asm/unistd.h>
-#include "init.h"
-#include "longjmp.h"
-#include "os.h"
-#include "skas_ptrace.h"
+#include <init.h>
+#include <longjmp.h>
+#include <os.h>
+#include <skas_ptrace.h>
 
 #define ARBITRARY_ADDR -1
 #define FAILURE_PID    -1
@@ -244,16 +244,3 @@ void init_new_thread_signals(void)
        signal(SIGWINCH, SIG_IGN);
        signal(SIGTERM, SIG_DFL);
 }
-
-int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr)
-{
-       jmp_buf buf;
-       int n;
-
-       *jmp_ptr = &buf;
-       n = UML_SETJMP(&buf);
-       if (n != 0)
-               return n;
-       (*fn)(arg);
-       return 0;
-}
index b866b9e3bef9ddf212ae4e0f74d489ab66f88827..2ff8d4fe83c4fd2d202ab5a6e45028f844978d83 100644 (file)
@@ -7,9 +7,9 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/ptrace.h>
-#include "sysdep/ptrace.h"
-#include "sysdep/ptrace_user.h"
-#include "registers.h"
+#include <sysdep/ptrace.h>
+#include <sysdep/ptrace_user.h>
+#include <registers.h>
 
 int save_registers(int pid, struct uml_pt_regs *regs)
 {
index 3c161218c671519b1443891438f09a54ca31976a..8b61cc0e82c8e8752e2f8a68fdeb31be3441ebe8 100644 (file)
 #include <sched.h>
 #include <signal.h>
 #include <string.h>
-#include "kern_util.h"
-#include "init.h"
-#include "os.h"
-#include "sigio.h"
-#include "um_malloc.h"
+#include <kern_util.h>
+#include <init.h>
+#include <os.h>
+#include <sigio.h>
+#include <um_malloc.h>
 
 /*
  * Protected by sigio_lock(), also used by sigio_cleanup, which is an
index 6366ce904b9b96145cd6c42b317283f33503e14b..b1469fe9329564dac95f1fc5b6320f0ed56ea31b 100644 (file)
@@ -9,10 +9,10 @@
 #include <errno.h>
 #include <signal.h>
 #include <strings.h>
-#include "as-layout.h"
-#include "kern_util.h"
-#include "os.h"
-#include "sysdep/mcontext.h"
+#include <as-layout.h>
+#include <kern_util.h>
+#include <os.h>
+#include <sysdep/mcontext.h>
 #include "internal.h"
 
 void (*sig_info[NSIG])(int, siginfo_t *, struct uml_pt_regs *) = {
index 90b310d29179e3aca968d4aabc9f095a25216889..689b18db798ffb89ac5c6f5bae839aae4567c201 100644 (file)
@@ -8,16 +8,16 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/mman.h>
-#include "init.h"
-#include "as-layout.h"
-#include "mm_id.h"
-#include "os.h"
-#include "proc_mm.h"
-#include "ptrace_user.h"
-#include "registers.h"
-#include "skas.h"
-#include "sysdep/ptrace.h"
-#include "sysdep/stub.h"
+#include <init.h>
+#include <as-layout.h>
+#include <mm_id.h>
+#include <os.h>
+#include <proc_mm.h>
+#include <ptrace_user.h>
+#include <registers.h>
+#include <skas.h>
+#include <sysdep/ptrace.h>
+#include <sysdep/stub.h>
 
 extern unsigned long batch_syscall_stub, __syscall_stub_start;
 
index d93bb40499f7bd57b264b32b5a36ec4a52ed5a6a..4625949bf1e4cd4ee9c424aa3eab1bfec6458ff7 100644 (file)
 #include <sys/mman.h>
 #include <sys/wait.h>
 #include <asm/unistd.h>
-#include "as-layout.h"
-#include "init.h"
-#include "kern_util.h"
-#include "mem.h"
-#include "os.h"
-#include "proc_mm.h"
-#include "ptrace_user.h"
-#include "registers.h"
-#include "skas.h"
-#include "skas_ptrace.h"
-#include "sysdep/stub.h"
+#include <as-layout.h>
+#include <init.h>
+#include <kern_util.h>
+#include <mem.h>
+#include <os.h>
+#include <proc_mm.h>
+#include <ptrace_user.h>
+#include <registers.h>
+#include <skas.h>
+#include <skas_ptrace.h>
+#include <sysdep/stub.h>
 
 int is_skas_winch(int pid, int fd, void *data)
 {
index 425162e22af5d0d877ac04a0415e0bfe9b9a6907..da4b9e9999fd2640764c8a4afe0c11ca2f43bc3b 100644 (file)
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <asm/unistd.h>
-#include "init.h"
-#include "os.h"
-#include "mem_user.h"
-#include "ptrace_user.h"
-#include "registers.h"
-#include "skas.h"
-#include "skas_ptrace.h"
+#include <init.h>
+#include <os.h>
+#include <mem_user.h>
+#include <ptrace_user.h>
+#include <registers.h>
+#include <skas.h>
+#include <skas_ptrace.h>
 
 static void ptrace_child(void)
 {
index 0748fe0c8a73dfa07aad69af8db1e4dcf5194550..fac388cb464f470d1c0285778f387fad1f1ba1e7 100644 (file)
@@ -8,8 +8,8 @@
 #include <signal.h>
 #include <time.h>
 #include <sys/time.h>
-#include "kern_util.h"
-#include "os.h"
+#include <kern_util.h>
+#include <os.h>
 #include "internal.h"
 
 int set_interval(void)
index dd12b99dcb595e4b5f4fba75e6454833ece42ece..721d8afa329b17e5547a59885aec1a054b5e8ab5 100644 (file)
@@ -7,8 +7,8 @@
 #include <unistd.h>
 #include <errno.h>
 #include <fcntl.h>
-#include "kern_util.h"
-#include "os.h"
+#include <kern_util.h>
+#include <os.h>
 
 struct grantpt_info {
        int fd;
index 4832eb519f8dfa9492803de9615e6d04b896faa3..c1dc89261f678451e9428c63b63078cc706a6cf5 100644 (file)
@@ -12,8 +12,8 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/stat.h>
-#include "init.h"
-#include "os.h"
+#include <init.h>
+#include <os.h>
 
 #define UML_DIR "~/.uml/"
 
index 73926fa3f96b2e92efa8c3d301f89da027ee1808..db4a034aeee1ddc41cde5d5213627e68beed0369 100644 (file)
@@ -1,5 +1,5 @@
-#include "linux/types.h"
-#include "linux/module.h"
+#include <linux/types.h>
+#include <linux/module.h>
 
 /* Some of this are builtin function (some are not but could in the future),
  * so I *must* declare good prototypes for them and then EXPORT them.
index 9e3b43bb84c99398407a9305feeb480b3f03462c..492ef5e6e166e082969fda850698f75d281bac47 100644 (file)
@@ -13,7 +13,7 @@
 #include <wait.h>
 #include <sys/mman.h>
 #include <sys/utsname.h>
-#include "os.h"
+#include <os.h>
 
 void stack_protections(unsigned long address)
 {
index 1c11aed9c719646795ddc2e45824ee8dac053170..25908d26ce079282cb6461f100ed459fdcc1090c 100644 (file)
@@ -1,6 +1,6 @@
-#include "linux/threads.h"
-#include "linux/stddef.h"  // for NULL
-#include "linux/elf.h"  // for AT_NULL
+#include <linux/threads.h>
+#include <linux/stddef.h>  // for NULL
+#include <linux/elf.h>  // for AT_NULL
 
 /* The following function nicked from arch/ppc/kernel/process.c and
  * adapted slightly */
index 66ef155248f1d1b8365e511524d21c7067c5d888..8245df41b201f5c59f600f984f85124f56b67c9f 100644 (file)
@@ -1,4 +1,4 @@
-#include "linux/sched.h"
+#include <linux/sched.h>
 #include "asm/ptrace.h"
 
 int putreg(struct task_struct *child, unsigned long regno, 
index 224d2403c37bb243bbb47c364e725d690d8e44fc..4601b9296aa7c9241e4bbd5dc113708cbe4c6086 100644 (file)
@@ -1,6 +1,6 @@
 #include <errno.h>
 #include <asm/ptrace.h>
-#include "sysdep/ptrace.h"
+#include <sysdep/ptrace.h>
 
 int ptrace_getregs(long pid, unsigned long *regs_out)
 {
index 0e3230e937e14fd3260f5dad2d1e6167c0b3c975..efe0c1a3ea9c895ce429ead335c9c28c0db58ab4 100644 (file)
@@ -5,7 +5,7 @@
 #ifndef __SYS_PTRACE_PPC_H
 #define __SYS_PTRACE_PPC_H
 
-#include "linux/types.h"
+#include <linux/types.h>
 
 /* the following taken from <asm-ppc/ptrace.h> */
 
index 40694d0f3d15ab6d8db6f415c9c1509e722044f9..aac6c83fe44e560279a5dd0983b571c66ffb5316 100644 (file)
@@ -1,4 +1,4 @@
 #include "asm/ptrace.h"
 #include "asm/sigcontext.h"
-#include "sysdep/ptrace.h"
+#include <sysdep/ptrace.h>
 
index 2f816f1a0ff4d3ceae814f81e8aedd107b955430..f889449f9285177bb800e1d68ea520fc9f54d089 100644 (file)
@@ -3,8 +3,8 @@
  * Licensed under the GPL
  */
 
-#include "linux/kernel.h"
-#include "linux/smp.h"
+#include <linux/kernel.h>
+#include <linux/smp.h>
 #include "asm/ptrace.h"
 #include "sysrq.h"
 
index 1e638e75a6b70a342f00ed5565a4541f1f57533d..35ee2bf66354e8f1d9bffcea75ba3e444d3e2266 100644 (file)
@@ -21,9 +21,6 @@ config UNICORE32
          designs licensed by PKUnity Ltd.
          Please see web page at <http://www.pkunity.com/>.
 
-config HAVE_PWM
-       bool
-
 config GENERIC_GPIO
        def_bool y
 
@@ -106,7 +103,8 @@ config PUV3_DB0913
 
 config PUV3_NB0916
        bool "NetBook board (0916)"
-       select HAVE_PWM
+       select PWM
+       select PWM_PUV3
 
 config PUV3_SMW0919
        bool "Security Mini-Workstation board (0919)"
@@ -220,12 +218,6 @@ config PUV3_GPIO
        select GPIO_SYSFS if EXPERIMENTAL
        default y
 
-config PUV3_PWM
-       tristate
-       default BACKLIGHT_PWM
-       help
-         Enable support for NB0916 PWM controllers
-
 if PUV3_NB0916
 
 menu "PKUnity NetBook-0916 Features"
index 123c59a06c14d8dd78ca2cfd5101acec34429f9a..c910c9857e114316991b2e9c711819a3939cdad5 100644 (file)
@@ -11,6 +11,7 @@ generic-y += device.h
 generic-y += div64.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
diff --git a/arch/unicore32/include/asm/exec.h b/arch/unicore32/include/asm/exec.h
deleted file mode 100644 (file)
index 06d1f0f..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * 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__ */
index 89f7557583b82d9bfe86d6bd967251c99e66de0b..818b4a1edb5b1bd26e3d8eb7baffe212df50a6f0 100644 (file)
@@ -141,12 +141,12 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
-#define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
 
 /*
  * Change these and you break ASM code in entry-common.S
  */
-#define _TIF_WORK_MASK         0x000000ff
+#define _TIF_WORK_MASK \
+       (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME)
 
 #endif /* __KERNEL__ */
 #endif /* __UNICORE_THREAD_INFO_H__ */
index 7b91fe698eede079e15cf899695d847d25cb7b7e..4a85fb4638480732720c426425de25667cb5cc32 100644 (file)
  * Interrupt Enable Reg OST_OIER
  */
 #define OST_OIER       (PKUNITY_OST_BASE + 0x001C)
+
 /*
- * PWM Pulse Width Control Reg OST_PWMPWCR
- */
-#define OST_PWMPWCR    (PKUNITY_OST_BASE + 0x0080)
-/*
- * PWM Duty Cycle Control Reg OST_PWMDCCR
- */
-#define OST_PWMDCCR    (PKUNITY_OST_BASE + 0x0084)
-/*
- * PWM Period Control Reg OST_PWMPCR
+ * PWM Registers: IO base address: PKUNITY_OST_BASE + 0x80
+ *      PWCR: Pulse Width Control Reg
+ *      DCCR: Duty Cycle Control Reg
+ *      PCR: Period Control Reg
  */
-#define OST_PWMPCR     (PKUNITY_OST_BASE + 0x0088)
+#define OST_PWM_PWCR   (0x00)
+#define OST_PWM_DCCR   (0x04)
+#define OST_PWM_PCR    (0x08)
 
 /*
  * Match detected 0 OST_OSSR_M0
index 3240101569584308bc8a5b676470deb85e58ef7c..fa497e0efe5acc59f00ea5e64da5332f3628b58f 100644 (file)
@@ -16,7 +16,6 @@ obj-$(CONFIG_UNICORE_FPU_F64) += fpu-ucf64.o
 obj-$(CONFIG_ARCH_PUV3)                += clock.o irq.o time.o
 
 obj-$(CONFIG_PUV3_GPIO)                += gpio.o
-obj-$(CONFIG_PUV3_PWM)         += pwm.o
 obj-$(CONFIG_PUV3_PM)          += pm.o sleep.o
 obj-$(CONFIG_HIBERNATION)      += hibernate.o hibernate_asm.o
 
index 00a259f9819e147dc77e22802594bc48a2d042f7..dcb87ab19ddd8b5912dfa2d765c4158fa1bbad73 100644 (file)
@@ -544,8 +544,6 @@ fast_work_pending:
 work_pending:
        cand.a  r1, #_TIF_NEED_RESCHED
        bne     work_resched
-       cand.a  r1, #_TIF_SIGPENDING|_TIF_NOTIFY_RESUME
-       beq     no_work_pending
        mov     r0, sp                          @ 'regs'
        mov     r2, why                         @ 'syscall'
        cand.a  r1, #_TIF_SIGPENDING            @ delivering a signal?
diff --git a/arch/unicore32/kernel/pwm.c b/arch/unicore32/kernel/pwm.c
deleted file mode 100644 (file)
index 4615d51..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * linux/arch/unicore32/kernel/pwm.c
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- *     Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
- *     Copyright (C) 2001-2010 Guan Xuetao
- *
- * 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/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/pwm.h>
-
-#include <asm/div64.h>
-#include <mach/hardware.h>
-
-struct pwm_device {
-       struct list_head        node;
-       struct platform_device *pdev;
-
-       const char      *label;
-       struct clk      *clk;
-       int             clk_enabled;
-
-       unsigned int    use_count;
-       unsigned int    pwm_id;
-};
-
-/*
- * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE
- * duty_ns   = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
- */
-int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
-{
-       unsigned long long c;
-       unsigned long period_cycles, prescale, pv, dc;
-
-       if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
-               return -EINVAL;
-
-       c = clk_get_rate(pwm->clk);
-       c = c * period_ns;
-       do_div(c, 1000000000);
-       period_cycles = c;
-
-       if (period_cycles < 1)
-               period_cycles = 1;
-       prescale = (period_cycles - 1) / 1024;
-       pv = period_cycles / (prescale + 1) - 1;
-
-       if (prescale > 63)
-               return -EINVAL;
-
-       if (duty_ns == period_ns)
-               dc = OST_PWMDCCR_FDCYCLE;
-       else
-               dc = (pv + 1) * duty_ns / period_ns;
-
-       /* NOTE: the clock to PWM has to be enabled first
-        * before writing to the registers
-        */
-       clk_enable(pwm->clk);
-       OST_PWMPWCR = prescale;
-       OST_PWMDCCR = pv - dc;
-       OST_PWMPCR  = pv;
-       clk_disable(pwm->clk);
-
-       return 0;
-}
-EXPORT_SYMBOL(pwm_config);
-
-int pwm_enable(struct pwm_device *pwm)
-{
-       int rc = 0;
-
-       if (!pwm->clk_enabled) {
-               rc = clk_enable(pwm->clk);
-               if (!rc)
-                       pwm->clk_enabled = 1;
-       }
-       return rc;
-}
-EXPORT_SYMBOL(pwm_enable);
-
-void pwm_disable(struct pwm_device *pwm)
-{
-       if (pwm->clk_enabled) {
-               clk_disable(pwm->clk);
-               pwm->clk_enabled = 0;
-       }
-}
-EXPORT_SYMBOL(pwm_disable);
-
-static DEFINE_MUTEX(pwm_lock);
-static LIST_HEAD(pwm_list);
-
-struct pwm_device *pwm_request(int pwm_id, const char *label)
-{
-       struct pwm_device *pwm;
-       int found = 0;
-
-       mutex_lock(&pwm_lock);
-
-       list_for_each_entry(pwm, &pwm_list, node) {
-               if (pwm->pwm_id == pwm_id) {
-                       found = 1;
-                       break;
-               }
-       }
-
-       if (found) {
-               if (pwm->use_count == 0) {
-                       pwm->use_count++;
-                       pwm->label = label;
-               } else
-                       pwm = ERR_PTR(-EBUSY);
-       } else
-               pwm = ERR_PTR(-ENOENT);
-
-       mutex_unlock(&pwm_lock);
-       return pwm;
-}
-EXPORT_SYMBOL(pwm_request);
-
-void pwm_free(struct pwm_device *pwm)
-{
-       mutex_lock(&pwm_lock);
-
-       if (pwm->use_count) {
-               pwm->use_count--;
-               pwm->label = NULL;
-       } else
-               pr_warning("PWM device already freed\n");
-
-       mutex_unlock(&pwm_lock);
-}
-EXPORT_SYMBOL(pwm_free);
-
-static inline void __add_pwm(struct pwm_device *pwm)
-{
-       mutex_lock(&pwm_lock);
-       list_add_tail(&pwm->node, &pwm_list);
-       mutex_unlock(&pwm_lock);
-}
-
-static struct pwm_device *pwm_probe(struct platform_device *pdev,
-               unsigned int pwm_id, struct pwm_device *parent_pwm)
-{
-       struct pwm_device *pwm;
-       struct resource *r;
-       int ret = 0;
-
-       pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
-       if (pwm == NULL) {
-               dev_err(&pdev->dev, "failed to allocate memory\n");
-               return ERR_PTR(-ENOMEM);
-       }
-
-       pwm->clk = clk_get(NULL, "OST_CLK");
-       if (IS_ERR(pwm->clk)) {
-               ret = PTR_ERR(pwm->clk);
-               goto err_free;
-       }
-       pwm->clk_enabled = 0;
-
-       pwm->use_count = 0;
-       pwm->pwm_id = pwm_id;
-       pwm->pdev = pdev;
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (r == NULL) {
-               dev_err(&pdev->dev, "no memory resource defined\n");
-               ret = -ENODEV;
-               goto err_free_clk;
-       }
-
-       r = request_mem_region(r->start, resource_size(r), pdev->name);
-       if (r == NULL) {
-               dev_err(&pdev->dev, "failed to request memory resource\n");
-               ret = -EBUSY;
-               goto err_free_clk;
-       }
-
-       __add_pwm(pwm);
-       platform_set_drvdata(pdev, pwm);
-       return pwm;
-
-err_free_clk:
-       clk_put(pwm->clk);
-err_free:
-       kfree(pwm);
-       return ERR_PTR(ret);
-}
-
-static int __devinit puv3_pwm_probe(struct platform_device *pdev)
-{
-       struct pwm_device *pwm = pwm_probe(pdev, pdev->id, NULL);
-
-       if (IS_ERR(pwm))
-               return PTR_ERR(pwm);
-
-       return 0;
-}
-
-static int __devexit pwm_remove(struct platform_device *pdev)
-{
-       struct pwm_device *pwm;
-       struct resource *r;
-
-       pwm = platform_get_drvdata(pdev);
-       if (pwm == NULL)
-               return -ENODEV;
-
-       mutex_lock(&pwm_lock);
-       list_del(&pwm->node);
-       mutex_unlock(&pwm_lock);
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(r->start, resource_size(r));
-
-       clk_put(pwm->clk);
-       kfree(pwm);
-       return 0;
-}
-
-static struct platform_driver puv3_pwm_driver = {
-       .driver         = {
-               .name   = "PKUnity-v3-PWM",
-       },
-       .probe          = puv3_pwm_probe,
-       .remove         = __devexit_p(pwm_remove),
-};
-
-static int __init pwm_init(void)
-{
-       int ret = 0;
-
-       ret = platform_driver_register(&puv3_pwm_driver);
-       if (ret) {
-               printk(KERN_ERR "failed to register puv3_pwm_driver\n");
-               return ret;
-       }
-
-       return ret;
-}
-arch_initcall(pwm_init);
-
-static void __exit pwm_exit(void)
-{
-       platform_driver_unregister(&puv3_pwm_driver);
-}
-module_exit(pwm_exit);
-
-MODULE_LICENSE("GPL v2");
index 8adedb37720a0e997dea9ea88abff76113904830..b8b2ffd774d637bdf55a35bc2a5116d8872904c8 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/personality.h>
-#include <linux/freezer.h>
 #include <linux/uaccess.h>
 #include <linux/tracehook.h>
 #include <linux/elf.h>
index 3afe60a39ac992178554f6e3bbd23900918cffd9..fabdee96110b46821c911fa9de0be5ba30460b57 100644 (file)
@@ -51,13 +51,13 @@ asmlinkage long __sys_execve(const char __user *filename,
                          struct pt_regs *regs)
 {
        int error;
-       char *fn;
+       struct filename *fn;
 
        fn = getname(filename);
        error = PTR_ERR(fn);
        if (IS_ERR(fn))
                goto out;
-       error = do_execve(fn, argv, envp, regs);
+       error = do_execve(fn->name, argv, envp, regs);
        putname(fn);
 out:
        return error;
@@ -104,7 +104,6 @@ int kernel_execve(const char *filename,
  out:
        return ret;
 }
-EXPORT_SYMBOL(kernel_execve);
 
 /* Note: used by the compat code even in 64-bit Linux. */
 SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
index 1ae94bcae5d9ba7fb92f739c6d433b244ad09ae0..70071b19eb989b7926ac0f08c8f6d2431356c919 100644 (file)
@@ -108,6 +108,8 @@ config X86
        select GENERIC_STRNLEN_USER
        select HAVE_RCU_USER_QS if X86_64
        select HAVE_IRQ_TIME_ACCOUNTING
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
 
 config INSTRUCTION_DECODER
        def_bool y
index 9c289504e680303a2bdfed3308eb40eb35135176..076745fc8045a8c35d1df646ede41d3c191c52e6 100644 (file)
@@ -465,7 +465,7 @@ GLOBAL(\label)
        PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
        PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
        PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
-       PTREGSCALL stub32_execve, sys32_execve, %rcx
+       PTREGSCALL stub32_execve, compat_sys_execve, %rcx
        PTREGSCALL stub32_fork, sys_fork, %rdi
        PTREGSCALL stub32_clone, sys32_clone, %rdx
        PTREGSCALL stub32_vfork, sys_vfork, %rdi
index c5b938d92eab3c3eb07294fdc425b8e756f776b6..86d68d1c8806b27fdf5506d0807d6fe874b48438 100644 (file)
@@ -385,21 +385,6 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd,
        return ret;
 }
 
-asmlinkage long sys32_execve(const char __user *name, compat_uptr_t __user *argv,
-                            compat_uptr_t __user *envp, struct pt_regs *regs)
-{
-       long error;
-       char *filename;
-
-       filename = getname(name);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               return error;
-       error = compat_do_execve(filename, argv, envp, regs);
-       putname(filename);
-       return error;
-}
-
 asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp,
                            struct pt_regs *regs)
 {
index fbee9714d9abafd8f4a95c6586acdefaf1e1bd66..7f0edceb75630b3ddcdbab3c9958f0b9d1367cc7 100644 (file)
 #define MSR_P6_EVNTSEL0                        0x00000186
 #define MSR_P6_EVNTSEL1                        0x00000187
 
+#define MSR_KNC_PERFCTR0               0x00000020
+#define MSR_KNC_PERFCTR1               0x00000021
+#define MSR_KNC_EVNTSEL0               0x00000028
+#define MSR_KNC_EVNTSEL1               0x00000029
+
 /* AMD64 MSRs. Not complete. See the architecture manual for a more
    complete list. */
 
index b98c0d958ebbdf830536ad42e3d166c198c1d29e..ad1fc85116743d677ff5b050e7226c2988a5e559 100644 (file)
@@ -588,11 +588,6 @@ typedef struct {
 } mm_segment_t;
 
 
-/*
- * create a kernel thread without removing it from tasklists
- */
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
index 4ca1c611b55202cfa6df55c37032cce27eca86b8..a9a8cf3da49d72ae78eb3e98af8ad3e0523ce6e3 100644 (file)
@@ -54,8 +54,6 @@ asmlinkage long sys32_pwrite(unsigned int, const char __user *, u32, u32, u32);
 asmlinkage long sys32_personality(unsigned long);
 asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32);
 
-asmlinkage long sys32_execve(const char __user *, compat_uptr_t __user *,
-                            compat_uptr_t __user *, struct pt_regs *);
 asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *);
 
 long sys32_lseek(unsigned int, int, unsigned int);
index f1d8b441fc775b4920b7397d6a151d2eed314a09..2be0b880417e62b3b827fd5b68f18521a4625777 100644 (file)
@@ -25,7 +25,7 @@ int sys_fork(struct pt_regs *);
 int sys_vfork(struct pt_regs *);
 long sys_execve(const char __user *,
                const char __user *const __user *,
-               const char __user *const __user *, struct pt_regs *);
+               const char __user *const __user *);
 long sys_clone(unsigned long, unsigned long, void __user *,
               void __user *, struct pt_regs *);
 
index c535d847e3b5f75dff0d8d2dd7988935fc35b63f..2d946e63ee82bceca34043aff29958b5e0e34127 100644 (file)
@@ -79,7 +79,6 @@ struct thread_info {
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_SINGLESTEP         4       /* reenable singlestep on user return*/
-#define TIF_IRET               5       /* force IRET */
 #define TIF_SYSCALL_EMU                6       /* syscall emulation active */
 #define TIF_SYSCALL_AUDIT      7       /* syscall auditing active */
 #define TIF_SECCOMP            8       /* secure computing */
@@ -105,7 +104,6 @@ struct thread_info {
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_SINGLESTEP                (1 << TIF_SINGLESTEP)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
-#define _TIF_IRET              (1 << TIF_IRET)
 #define _TIF_SYSCALL_EMU       (1 << TIF_SYSCALL_EMU)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1 << TIF_SECCOMP)
index 0d9776e9e2dc3f2a539015a5f2930e00d2727a99..16f3fc6ebf2e858d495507f5609916baaa673104 100644 (file)
@@ -50,6 +50,7 @@
 # define __ARCH_WANT_SYS_TIME
 # define __ARCH_WANT_SYS_UTIME
 # define __ARCH_WANT_SYS_WAITPID
+# define __ARCH_WANT_SYS_EXECVE
 
 /*
  * "Conditional" syscalls
index 8b38be2de9e15a7cf149b3c088aac074f1be0463..46e24d36b7da12dc641e4718d0d80e42ca923751 100644 (file)
@@ -17,8 +17,8 @@ struct vsyscall_gtod_data {
 
        /* open coded 'struct timespec' */
        time_t          wall_time_sec;
-       u32             wall_time_nsec;
-       u32             monotonic_time_nsec;
+       u64             wall_time_snsec;
+       u64             monotonic_time_snsec;
        time_t          monotonic_time_sec;
 
        struct timezone sys_tz;
index a48ea05157d3bbcb8cb56c4a2f92bb45cad446e8..91ce48f05f9f6d623beaa84029be5ff1cdf1cfc8 100644 (file)
@@ -23,7 +23,7 @@ obj-y                 += time.o ioport.o ldt.o dumpstack.o nmi.o
 obj-y                  += setup.o x86_init.o i8259.o irqinit.o jump_label.o
 obj-$(CONFIG_IRQ_WORK)  += irq_work.o
 obj-y                  += probe_roms.o
-obj-$(CONFIG_X86_32)   += sys_i386_32.o i386_ksyms_32.o
+obj-$(CONFIG_X86_32)   += i386_ksyms_32.o
 obj-$(CONFIG_X86_64)   += sys_x86_64.o x8664_ksyms_64.o
 obj-y                  += syscall_$(BITS).o
 obj-$(CONFIG_X86_64)   += vsyscall_64.o
index 68de2dc962ec0dc52a8721578aa0ca9aff40ba39..28610822fb3cc4be10a04c098ee91b6a8b8ab78f 100644 (file)
@@ -69,4 +69,7 @@ void common(void) {
        OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment);
        OFFSET(BP_pref_address, boot_params, hdr.pref_address);
        OFFSET(BP_code32_start, boot_params, hdr.code32_start);
+
+       BLANK();
+       DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
 }
index d30a6a9a01218800008cad1aec082c9d8fa8cac8..a0e067d3d96cafa9a5af545c0b857db38dd80bab 100644 (file)
@@ -32,7 +32,7 @@ obj-$(CONFIG_PERF_EVENTS)             += perf_event.o
 
 ifdef CONFIG_PERF_EVENTS
 obj-$(CONFIG_CPU_SUP_AMD)              += perf_event_amd.o
-obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_p6.o perf_event_p4.o
+obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_p6.o perf_event_knc.o perf_event_p4.o
 obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o
 obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_uncore.o
 endif
index 8b6defe7eefc5e6de1538984622f109c4223528d..271d25700297402c2d47403ecc9f350d00dab8ad 100644 (file)
@@ -626,6 +626,8 @@ int p4_pmu_init(void);
 
 int p6_pmu_init(void);
 
+int knc_pmu_init(void);
+
 #else /* CONFIG_CPU_SUP_INTEL */
 
 static inline void reserve_ds_buffers(void)
index eebd5ffe1bba0b922f9ef8481fd141f2ba9668da..6336bcbd0618a1e8ff82dac76932c10f734f19ae 100644 (file)
@@ -41,17 +41,22 @@ struct cpu_perf_ibs {
 };
 
 struct perf_ibs {
-       struct pmu      pmu;
-       unsigned int    msr;
-       u64             config_mask;
-       u64             cnt_mask;
-       u64             enable_mask;
-       u64             valid_mask;
-       u64             max_period;
-       unsigned long   offset_mask[1];
-       int             offset_max;
-       struct cpu_perf_ibs __percpu *pcpu;
-       u64             (*get_count)(u64 config);
+       struct pmu                      pmu;
+       unsigned int                    msr;
+       u64                             config_mask;
+       u64                             cnt_mask;
+       u64                             enable_mask;
+       u64                             valid_mask;
+       u64                             max_period;
+       unsigned long                   offset_mask[1];
+       int                             offset_max;
+       struct cpu_perf_ibs __percpu    *pcpu;
+
+       struct attribute                **format_attrs;
+       struct attribute_group          format_group;
+       const struct attribute_group    *attr_groups[2];
+
+       u64                             (*get_count)(u64 config);
 };
 
 struct perf_ibs_data {
@@ -446,6 +451,19 @@ static void perf_ibs_del(struct perf_event *event, int flags)
 
 static void perf_ibs_read(struct perf_event *event) { }
 
+PMU_FORMAT_ATTR(rand_en,       "config:57");
+PMU_FORMAT_ATTR(cnt_ctl,       "config:19");
+
+static struct attribute *ibs_fetch_format_attrs[] = {
+       &format_attr_rand_en.attr,
+       NULL,
+};
+
+static struct attribute *ibs_op_format_attrs[] = {
+       NULL,   /* &format_attr_cnt_ctl.attr if IBS_CAPS_OPCNT */
+       NULL,
+};
+
 static struct perf_ibs perf_ibs_fetch = {
        .pmu = {
                .task_ctx_nr    = perf_invalid_context,
@@ -465,6 +483,7 @@ static struct perf_ibs perf_ibs_fetch = {
        .max_period             = IBS_FETCH_MAX_CNT << 4,
        .offset_mask            = { MSR_AMD64_IBSFETCH_REG_MASK },
        .offset_max             = MSR_AMD64_IBSFETCH_REG_COUNT,
+       .format_attrs           = ibs_fetch_format_attrs,
 
        .get_count              = get_ibs_fetch_count,
 };
@@ -488,6 +507,7 @@ static struct perf_ibs perf_ibs_op = {
        .max_period             = IBS_OP_MAX_CNT << 4,
        .offset_mask            = { MSR_AMD64_IBSOP_REG_MASK },
        .offset_max             = MSR_AMD64_IBSOP_REG_COUNT,
+       .format_attrs           = ibs_op_format_attrs,
 
        .get_count              = get_ibs_op_count,
 };
@@ -597,6 +617,17 @@ static __init int perf_ibs_pmu_init(struct perf_ibs *perf_ibs, char *name)
 
        perf_ibs->pcpu = pcpu;
 
+       /* register attributes */
+       if (perf_ibs->format_attrs[0]) {
+               memset(&perf_ibs->format_group, 0, sizeof(perf_ibs->format_group));
+               perf_ibs->format_group.name     = "format";
+               perf_ibs->format_group.attrs    = perf_ibs->format_attrs;
+
+               memset(&perf_ibs->attr_groups, 0, sizeof(perf_ibs->attr_groups));
+               perf_ibs->attr_groups[0]        = &perf_ibs->format_group;
+               perf_ibs->pmu.attr_groups       = perf_ibs->attr_groups;
+       }
+
        ret = perf_pmu_register(&perf_ibs->pmu, name, -1);
        if (ret) {
                perf_ibs->pcpu = NULL;
@@ -608,13 +639,19 @@ static __init int perf_ibs_pmu_init(struct perf_ibs *perf_ibs, char *name)
 
 static __init int perf_event_ibs_init(void)
 {
+       struct attribute **attr = ibs_op_format_attrs;
+
        if (!ibs_caps)
                return -ENODEV; /* ibs not supported by the cpu */
 
        perf_ibs_pmu_init(&perf_ibs_fetch, "ibs_fetch");
-       if (ibs_caps & IBS_CAPS_OPCNT)
+
+       if (ibs_caps & IBS_CAPS_OPCNT) {
                perf_ibs_op.config_mask |= IBS_OP_CNT_CTL;
+               *attr++ = &format_attr_cnt_ctl.attr;
+       }
        perf_ibs_pmu_init(&perf_ibs_op, "ibs_op");
+
        register_nmi_handler(NMI_LOCAL, perf_ibs_nmi_handler, 0, "perf_ibs");
        printk(KERN_INFO "perf: AMD IBS detected (0x%08x)\n", ibs_caps);
 
index 6bca492b85475bc8eab5577447ce1fa9a5133223..324bb523d9d9b402dbc6ac36706b6a8b90d577e7 100644 (file)
@@ -1906,6 +1906,8 @@ __init int intel_pmu_init(void)
                switch (boot_cpu_data.x86) {
                case 0x6:
                        return p6_pmu_init();
+               case 0xb:
+                       return knc_pmu_init();
                case 0xf:
                        return p4_pmu_init();
                }
diff --git a/arch/x86/kernel/cpu/perf_event_knc.c b/arch/x86/kernel/cpu/perf_event_knc.c
new file mode 100644 (file)
index 0000000..7c46bfd
--- /dev/null
@@ -0,0 +1,248 @@
+/* Driver for Intel Xeon Phi "Knights Corner" PMU */
+
+#include <linux/perf_event.h>
+#include <linux/types.h>
+
+#include "perf_event.h"
+
+static const u64 knc_perfmon_event_map[] =
+{
+  [PERF_COUNT_HW_CPU_CYCLES]           = 0x002a,
+  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x0016,
+  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0028,
+  [PERF_COUNT_HW_CACHE_MISSES]         = 0x0029,
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x0012,
+  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x002b,
+};
+
+static __initconst u64 knc_hw_cache_event_ids
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(L1D) ] = {
+       [ C(OP_READ) ] = {
+               /* On Xeon Phi event "0" is a valid DATA_READ          */
+               /*   (L1 Data Cache Reads) Instruction.                */
+               /* We code this as ARCH_PERFMON_EVENTSEL_INT as this   */
+               /* bit will always be set in x86_pmu_hw_config().      */
+               [ C(RESULT_ACCESS) ] = ARCH_PERFMON_EVENTSEL_INT,
+                                               /* DATA_READ           */
+               [ C(RESULT_MISS)   ] = 0x0003,  /* DATA_READ_MISS      */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0001,  /* DATA_WRITE          */
+               [ C(RESULT_MISS)   ] = 0x0004,  /* DATA_WRITE_MISS     */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0011,  /* L1_DATA_PF1         */
+               [ C(RESULT_MISS)   ] = 0x001c,  /* L1_DATA_PF1_MISS    */
+       },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x000c,  /* CODE_READ          */
+               [ C(RESULT_MISS)   ] = 0x000e,  /* CODE_CACHE_MISS    */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0x10cb,  /* L2_READ_MISS */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x10cc,  /* L2_WRITE_HIT */
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x10fc,  /* L2_DATA_PF2      */
+               [ C(RESULT_MISS)   ] = 0x10fe,  /* L2_DATA_PF2_MISS */
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = ARCH_PERFMON_EVENTSEL_INT,
+                                               /* DATA_READ */
+                                               /* see note on L1 OP_READ */
+               [ C(RESULT_MISS)   ] = 0x0002,  /* DATA_PAGE_WALK */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0001,  /* DATA_WRITE */
+               [ C(RESULT_MISS)   ] = 0x0002,  /* DATA_PAGE_WALK */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x000c,  /* CODE_READ */
+               [ C(RESULT_MISS)   ] = 0x000d,  /* CODE_PAGE_WALK */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0012,  /* BRANCHES */
+               [ C(RESULT_MISS)   ] = 0x002b,  /* BRANCHES_MISPREDICTED */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+};
+
+
+static u64 knc_pmu_event_map(int hw_event)
+{
+       return knc_perfmon_event_map[hw_event];
+}
+
+static struct event_constraint knc_event_constraints[] =
+{
+       INTEL_EVENT_CONSTRAINT(0xc3, 0x1),      /* HWP_L2HIT */
+       INTEL_EVENT_CONSTRAINT(0xc4, 0x1),      /* HWP_L2MISS */
+       INTEL_EVENT_CONSTRAINT(0xc8, 0x1),      /* L2_READ_HIT_E */
+       INTEL_EVENT_CONSTRAINT(0xc9, 0x1),      /* L2_READ_HIT_M */
+       INTEL_EVENT_CONSTRAINT(0xca, 0x1),      /* L2_READ_HIT_S */
+       INTEL_EVENT_CONSTRAINT(0xcb, 0x1),      /* L2_READ_MISS */
+       INTEL_EVENT_CONSTRAINT(0xcc, 0x1),      /* L2_WRITE_HIT */
+       INTEL_EVENT_CONSTRAINT(0xce, 0x1),      /* L2_STRONGLY_ORDERED_STREAMING_VSTORES_MISS */
+       INTEL_EVENT_CONSTRAINT(0xcf, 0x1),      /* L2_WEAKLY_ORDERED_STREAMING_VSTORE_MISS */
+       INTEL_EVENT_CONSTRAINT(0xd7, 0x1),      /* L2_VICTIM_REQ_WITH_DATA */
+       INTEL_EVENT_CONSTRAINT(0xe3, 0x1),      /* SNP_HITM_BUNIT */
+       INTEL_EVENT_CONSTRAINT(0xe6, 0x1),      /* SNP_HIT_L2 */
+       INTEL_EVENT_CONSTRAINT(0xe7, 0x1),      /* SNP_HITM_L2 */
+       INTEL_EVENT_CONSTRAINT(0xf1, 0x1),      /* L2_DATA_READ_MISS_CACHE_FILL */
+       INTEL_EVENT_CONSTRAINT(0xf2, 0x1),      /* L2_DATA_WRITE_MISS_CACHE_FILL */
+       INTEL_EVENT_CONSTRAINT(0xf6, 0x1),      /* L2_DATA_READ_MISS_MEM_FILL */
+       INTEL_EVENT_CONSTRAINT(0xf7, 0x1),      /* L2_DATA_WRITE_MISS_MEM_FILL */
+       INTEL_EVENT_CONSTRAINT(0xfc, 0x1),      /* L2_DATA_PF2 */
+       INTEL_EVENT_CONSTRAINT(0xfd, 0x1),      /* L2_DATA_PF2_DROP */
+       INTEL_EVENT_CONSTRAINT(0xfe, 0x1),      /* L2_DATA_PF2_MISS */
+       INTEL_EVENT_CONSTRAINT(0xff, 0x1),      /* L2_DATA_HIT_INFLIGHT_PF2 */
+       EVENT_CONSTRAINT_END
+};
+
+#define MSR_KNC_IA32_PERF_GLOBAL_STATUS                0x0000002d
+#define MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL   0x0000002e
+#define MSR_KNC_IA32_PERF_GLOBAL_CTRL          0x0000002f
+
+#define KNC_ENABLE_COUNTER0                    0x00000001
+#define KNC_ENABLE_COUNTER1                    0x00000002
+
+static void knc_pmu_disable_all(void)
+{
+       u64 val;
+
+       rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
+       val &= ~(KNC_ENABLE_COUNTER0|KNC_ENABLE_COUNTER1);
+       wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
+}
+
+static void knc_pmu_enable_all(int added)
+{
+       u64 val;
+
+       rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
+       val |= (KNC_ENABLE_COUNTER0|KNC_ENABLE_COUNTER1);
+       wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
+}
+
+static inline void
+knc_pmu_disable_event(struct perf_event *event)
+{
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       struct hw_perf_event *hwc = &event->hw;
+       u64 val;
+
+       val = hwc->config;
+       if (cpuc->enabled)
+               val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+
+       (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
+}
+
+static void knc_pmu_enable_event(struct perf_event *event)
+{
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       struct hw_perf_event *hwc = &event->hw;
+       u64 val;
+
+       val = hwc->config;
+       if (cpuc->enabled)
+               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
+
+       (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
+}
+
+PMU_FORMAT_ATTR(event, "config:0-7"    );
+PMU_FORMAT_ATTR(umask, "config:8-15"   );
+PMU_FORMAT_ATTR(edge,  "config:18"     );
+PMU_FORMAT_ATTR(inv,   "config:23"     );
+PMU_FORMAT_ATTR(cmask, "config:24-31"  );
+
+static struct attribute *intel_knc_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_cmask.attr,
+       NULL,
+};
+
+static __initconst struct x86_pmu knc_pmu = {
+       .name                   = "knc",
+       .handle_irq             = x86_pmu_handle_irq,
+       .disable_all            = knc_pmu_disable_all,
+       .enable_all             = knc_pmu_enable_all,
+       .enable                 = knc_pmu_enable_event,
+       .disable                = knc_pmu_disable_event,
+       .hw_config              = x86_pmu_hw_config,
+       .schedule_events        = x86_schedule_events,
+       .eventsel               = MSR_KNC_EVNTSEL0,
+       .perfctr                = MSR_KNC_PERFCTR0,
+       .event_map              = knc_pmu_event_map,
+       .max_events             = ARRAY_SIZE(knc_perfmon_event_map),
+       .apic                   = 1,
+       .max_period             = (1ULL << 31) - 1,
+       .version                = 0,
+       .num_counters           = 2,
+       /* in theory 40 bits, early silicon is buggy though */
+       .cntval_bits            = 32,
+       .cntval_mask            = (1ULL << 32) - 1,
+       .get_event_constraints  = x86_get_event_constraints,
+       .event_constraints      = knc_event_constraints,
+       .format_attrs           = intel_knc_formats_attr,
+};
+
+__init int knc_pmu_init(void)
+{
+       x86_pmu = knc_pmu;
+
+       memcpy(hw_cache_event_ids, knc_hw_cache_event_ids, 
+               sizeof(hw_cache_event_ids));
+
+       return 0;
+}
index 966512b2cacf37824bc2b2bccda04e6f26f12ddf..2e8caf03f59317eddc80bfda5958589841fe358f 100644 (file)
@@ -56,6 +56,8 @@ static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
                switch (boot_cpu_data.x86) {
                case 6:
                        return msr - MSR_P6_PERFCTR0;
+               case 11:
+                       return msr - MSR_KNC_PERFCTR0;
                case 15:
                        return msr - MSR_P4_BPU_PERFCTR0;
                }
@@ -82,6 +84,8 @@ static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
                switch (boot_cpu_data.x86) {
                case 6:
                        return msr - MSR_P6_EVNTSEL0;
+               case 11:
+                       return msr - MSR_KNC_EVNTSEL0;
                case 15:
                        return msr - MSR_P4_BSU_ESCR0;
                }
index 0750e3ba87c09447c7443112b0a1e5678538de91..a1193aef6d7d2ef1af31a4b257ed0e161876ad19 100644 (file)
@@ -299,6 +299,21 @@ ENTRY(ret_from_fork)
        CFI_ENDPROC
 END(ret_from_fork)
 
+ENTRY(ret_from_kernel_thread)
+       CFI_STARTPROC
+       pushl_cfi %eax
+       call schedule_tail
+       GET_THREAD_INFO(%ebp)
+       popl_cfi %eax
+       pushl_cfi $0x0202               # Reset kernel eflags
+       popfl_cfi
+       movl PT_EBP(%esp),%eax
+       call *PT_EBX(%esp)
+       movl $0,PT_EAX(%esp)
+       jmp syscall_exit
+       CFI_ENDPROC
+ENDPROC(ret_from_kernel_thread)
+
 /*
  * Interrupt exit functions should be protected against kprobes
  */
@@ -323,8 +338,7 @@ ret_from_intr:
        andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
 #else
        /*
-        * We can be coming here from a syscall done in the kernel space,
-        * e.g. a failed kernel_execve().
+        * We can be coming here from child spawned by kernel_thread().
         */
        movl PT_CS(%esp), %eax
        andl $SEGMENT_RPL_MASK, %eax
@@ -616,6 +630,10 @@ work_notifysig:                            # deal with pending signals and
        movl %esp, %eax
        jne work_notifysig_v86          # returning to kernel-space or
                                        # vm86-space
+1:
+#else
+       movl %esp, %eax
+#endif
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS(CLBR_NONE)
        movb PT_CS(%esp), %bl
@@ -626,24 +644,15 @@ work_notifysig:                           # deal with pending signals and
        call do_notify_resume
        jmp resume_userspace
 
+#ifdef CONFIG_VM86
        ALIGN
 work_notifysig_v86:
        pushl_cfi %ecx                  # save ti_flags for do_notify_resume
        call save_v86_state             # %eax contains pt_regs pointer
        popl_cfi %ecx
        movl %eax, %esp
-#else
-       movl %esp, %eax
+       jmp 1b
 #endif
-       TRACE_IRQS_ON
-       ENABLE_INTERRUPTS(CLBR_NONE)
-       movb PT_CS(%esp), %bl
-       andb $SEGMENT_RPL_MASK, %bl
-       cmpb $USER_RPL, %bl
-       jb resume_kernel
-       xorl %edx, %edx
-       call do_notify_resume
-       jmp resume_userspace
 END(work_pending)
 
        # perform syscall exit tracing
@@ -732,7 +741,6 @@ ENDPROC(ptregs_##name)
 PTREGSCALL1(iopl)
 PTREGSCALL0(fork)
 PTREGSCALL0(vfork)
-PTREGSCALL3(execve)
 PTREGSCALL2(sigaltstack)
 PTREGSCALL0(sigreturn)
 PTREGSCALL0(rt_sigreturn)
@@ -1015,16 +1023,6 @@ END(spurious_interrupt_bug)
  */
        .popsection
 
-ENTRY(kernel_thread_helper)
-       pushl $0                # fake return address for unwinder
-       CFI_STARTPROC
-       movl %edi,%eax
-       call *%esi
-       call do_exit
-       ud2                     # padding for call trace
-       CFI_ENDPROC
-ENDPROC(kernel_thread_helper)
-
 #ifdef CONFIG_XEN
 /* Xen doesn't set %esp to be precisely what the normal sysenter
    entrypoint expects, so fix it up before using the normal path. */
index 44531acd9a81e83f932a34a409c028b24cdb9bce..0c58952d64e8723b4486ce620c8b11bcfe8d01f5 100644 (file)
@@ -554,7 +554,7 @@ ENTRY(ret_from_fork)
        RESTORE_REST
 
        testl $3, CS-ARGOFFSET(%rsp)            # from kernel_thread?
-       jz   retint_restore_args
+       jz   1f
 
        testl $_TIF_IA32, TI_flags(%rcx)        # 32-bit compat task needs IRET
        jnz  int_ret_from_sys_call
@@ -562,6 +562,14 @@ ENTRY(ret_from_fork)
        RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
        jmp ret_from_sys_call                   # go to the SYSRET fastpath
 
+1:
+       subq $REST_SKIP, %rsp   # leave space for volatiles
+       CFI_ADJUST_CFA_OFFSET   REST_SKIP
+       movq %rbp, %rdi
+       call *%rbx
+       movl $0, RAX(%rsp)
+       RESTORE_REST
+       jmp int_ret_from_sys_call
        CFI_ENDPROC
 END(ret_from_fork)
 
@@ -862,7 +870,6 @@ ENTRY(stub_execve)
        PARTIAL_FRAME 0
        SAVE_REST
        FIXUP_TOP_OF_STACK %r11
-       movq %rsp, %rcx
        call sys_execve
        RESTORE_TOP_OF_STACK %r11
        movq %rax,RAX(%rsp)
@@ -912,8 +919,7 @@ ENTRY(stub_x32_execve)
        PARTIAL_FRAME 0
        SAVE_REST
        FIXUP_TOP_OF_STACK %r11
-       movq %rsp, %rcx
-       call sys32_execve
+       call compat_sys_execve
        RESTORE_TOP_OF_STACK %r11
        movq %rax,RAX(%rsp)
        RESTORE_REST
@@ -1318,52 +1324,6 @@ bad_gs:
        jmp  2b
        .previous
 
-ENTRY(kernel_thread_helper)
-       pushq $0                # fake return address
-       CFI_STARTPROC
-       /*
-        * Here we are in the child and the registers are set as they were
-        * at kernel_thread() invocation in the parent.
-        */
-       call *%rsi
-       # exit
-       mov %eax, %edi
-       call do_exit
-       ud2                     # padding for call trace
-       CFI_ENDPROC
-END(kernel_thread_helper)
-
-/*
- * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
- *
- * C extern interface:
- *      extern long execve(const char *name, char **argv, char **envp)
- *
- * asm input arguments:
- *     rdi: name, rsi: argv, rdx: envp
- *
- * We want to fallback into:
- *     extern long sys_execve(const char *name, char **argv,char **envp, struct pt_regs *regs)
- *
- * do_sys_execve asm fallback arguments:
- *     rdi: name, rsi: argv, rdx: envp, rcx: fake frame on the stack
- */
-ENTRY(kernel_execve)
-       CFI_STARTPROC
-       FAKE_STACK_FRAME $0
-       SAVE_ALL
-       movq %rsp,%rcx
-       call sys_execve
-       movq %rax, RAX(%rsp)
-       RESTORE_REST
-       testq %rax,%rax
-       je int_ret_from_sys_call
-       RESTORE_ARGS
-       UNFAKE_STACK_FRAME
-       ret
-       CFI_ENDPROC
-END(kernel_execve)
-
 /* Call softirq on interrupt stack. Interrupts are off. */
 ENTRY(call_softirq)
        CFI_STARTPROC
index 3f61904365cff214d26efa4a378830559e39a7f9..836f8322960e4b78c3263c3a18ed70cb67b589a7 100644 (file)
@@ -746,7 +746,9 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
 int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
 {
        int err;
+#ifdef CONFIG_DEBUG_RODATA
        char opc[BREAK_INSTR_SIZE];
+#endif /* CONFIG_DEBUG_RODATA */
 
        bpt->type = BP_BREAKPOINT;
        err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
index dc3567e083f9f5ec3a9d524756d191b5125490cc..b644e1c765dc211dbb07b6ee7570081e5cd0e6c6 100644 (file)
@@ -292,71 +292,6 @@ sys_clone(unsigned long clone_flags, unsigned long newsp,
        return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
 }
 
-/*
- * This gets run with %si containing the
- * function to call, and %di containing
- * the "args".
- */
-extern void kernel_thread_helper(void);
-
-/*
- * Create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-
-       regs.si = (unsigned long) fn;
-       regs.di = (unsigned long) arg;
-
-#ifdef CONFIG_X86_32
-       regs.ds = __USER_DS;
-       regs.es = __USER_DS;
-       regs.fs = __KERNEL_PERCPU;
-       regs.gs = __KERNEL_STACK_CANARY;
-#else
-       regs.ss = __KERNEL_DS;
-#endif
-
-       regs.orig_ax = -1;
-       regs.ip = (unsigned long) kernel_thread_helper;
-       regs.cs = __KERNEL_CS | get_kernel_rpl();
-       regs.flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1;
-
-       /* Ok, create the new process.. */
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
-/*
- * sys_execve() executes a new program.
- */
-long sys_execve(const char __user *name,
-               const char __user *const __user *argv,
-               const char __user *const __user *envp, struct pt_regs *regs)
-{
-       long error;
-       char *filename;
-
-       filename = getname(name);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               return error;
-       error = do_execve(filename, argv, envp, regs);
-
-#ifdef CONFIG_X86_32
-       if (error == 0) {
-               /* Make sure we don't return using sysenter.. */
-                set_thread_flag(TIF_IRET);
-        }
-#endif
-
-       putname(filename);
-       return error;
-}
-
 /*
  * Idle related variables and functions
  */
index b9ff83c7135bad337d4e5d7e7554be6e833204a0..44e0bff38e724de5b9e02e5bd9581133999ad40e 100644 (file)
@@ -57,6 +57,7 @@
 #include <asm/switch_to.h>
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
 
 /*
  * Return saved PC of a blocked thread.
@@ -127,23 +128,39 @@ void release_thread(struct task_struct *dead_task)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long sp,
-       unsigned long unused,
+       unsigned long arg,
        struct task_struct *p, struct pt_regs *regs)
 {
-       struct pt_regs *childregs;
+       struct pt_regs *childregs = task_pt_regs(p);
        struct task_struct *tsk;
        int err;
 
-       childregs = task_pt_regs(p);
+       p->thread.sp = (unsigned long) childregs;
+       p->thread.sp0 = (unsigned long) (childregs+1);
+
+       if (unlikely(!regs)) {
+               /* kernel thread */
+               memset(childregs, 0, sizeof(struct pt_regs));
+               p->thread.ip = (unsigned long) ret_from_kernel_thread;
+               task_user_gs(p) = __KERNEL_STACK_CANARY;
+               childregs->ds = __USER_DS;
+               childregs->es = __USER_DS;
+               childregs->fs = __KERNEL_PERCPU;
+               childregs->bx = sp;     /* function */
+               childregs->bp = arg;
+               childregs->orig_ax = -1;
+               childregs->cs = __KERNEL_CS | get_kernel_rpl();
+               childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1;
+               p->fpu_counter = 0;
+               p->thread.io_bitmap_ptr = NULL;
+               memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
+               return 0;
+       }
        *childregs = *regs;
        childregs->ax = 0;
        childregs->sp = sp;
 
-       p->thread.sp = (unsigned long) childregs;
-       p->thread.sp0 = (unsigned long) (childregs+1);
-
        p->thread.ip = (unsigned long) ret_from_fork;
-
        task_user_gs(p) = get_user_gs(regs);
 
        p->fpu_counter = 0;
@@ -190,6 +207,12 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
        regs->cs                = __USER_CS;
        regs->ip                = new_ip;
        regs->sp                = new_sp;
+       regs->flags             = X86_EFLAGS_IF;
+       /*
+        * force it to the iret return path by making it look as if there was
+        * some work pending.
+        */
+       set_thread_flag(TIF_NOTIFY_RESUME);
 }
 EXPORT_SYMBOL_GPL(start_thread);
 
index 8a6d20ce19784ee96362cbaaa29c696497122a6a..16c6365e2b867c883805061f533349751f9bfbf0 100644 (file)
@@ -146,29 +146,18 @@ static inline u32 read_32bit_tls(struct task_struct *t, int tls)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long sp,
-               unsigned long unused,
+               unsigned long arg,
        struct task_struct *p, struct pt_regs *regs)
 {
        int err;
        struct pt_regs *childregs;
        struct task_struct *me = current;
 
-       childregs = ((struct pt_regs *)
-                       (THREAD_SIZE + task_stack_page(p))) - 1;
-       *childregs = *regs;
-
-       childregs->ax = 0;
-       if (user_mode(regs))
-               childregs->sp = sp;
-       else
-               childregs->sp = (unsigned long)childregs;
-
+       p->thread.sp0 = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+       childregs = task_pt_regs(p);
        p->thread.sp = (unsigned long) childregs;
-       p->thread.sp0 = (unsigned long) (childregs+1);
        p->thread.usersp = me->thread.usersp;
-
        set_tsk_thread_flag(p, TIF_FORK);
-
        p->fpu_counter = 0;
        p->thread.io_bitmap_ptr = NULL;
 
@@ -178,6 +167,24 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
        p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs;
        savesegment(es, p->thread.es);
        savesegment(ds, p->thread.ds);
+       memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
+
+       if (unlikely(!regs)) {
+               /* kernel thread */
+               memset(childregs, 0, sizeof(struct pt_regs));
+               childregs->sp = (unsigned long)childregs;
+               childregs->ss = __KERNEL_DS;
+               childregs->bx = sp; /* function */
+               childregs->bp = arg;
+               childregs->orig_ax = -1;
+               childregs->cs = __KERNEL_CS | get_kernel_rpl();
+               childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1;
+               return 0;
+       }
+       *childregs = *regs;
+
+       childregs->ax = 0;
+       childregs->sp = sp;
 
        err = -ENOMEM;
        memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
index d609be046b5749991c01919561055072d717f970..a2bb18e02839489dcbf9dbc1e3d348f5fb176c34 100644 (file)
@@ -68,6 +68,7 @@
 #include <linux/percpu.h>
 #include <linux/crash_dump.h>
 #include <linux/tboot.h>
+#include <linux/jiffies.h>
 
 #include <video/edid.h>
 
@@ -1032,6 +1033,8 @@ void __init setup_arch(char **cmdline_p)
        mcheck_init();
 
        arch_init_ideal_nops();
+
+       register_refined_jiffies(CLOCK_TICK_RATE);
 }
 
 #ifdef CONFIG_X86_32
index b33144c8b3098a10d956882f31e6ca1933770ce7..29ad351804e9324d3aaf59c07c86d274958516b3 100644 (file)
@@ -840,10 +840,6 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
        if (thread_info_flags & _TIF_USER_RETURN_NOTIFY)
                fire_user_return_notifiers();
 
-#ifdef CONFIG_X86_32
-       clear_thread_flag(TIF_IRET);
-#endif /* CONFIG_X86_32 */
-
        rcu_user_enter();
 }
 
diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c
deleted file mode 100644 (file)
index 0b0cb5f..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * This file contains various random system calls that
- * have a non-standard calling sequence on the Linux/i386
- * platform.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/smp.h>
-#include <linux/sem.h>
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <linux/stat.h>
-#include <linux/syscalls.h>
-#include <linux/mman.h>
-#include <linux/file.h>
-#include <linux/utsname.h>
-#include <linux/ipc.h>
-
-#include <linux/uaccess.h>
-#include <linux/unistd.h>
-
-#include <asm/syscalls.h>
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename,
-                 const char *const argv[],
-                 const char *const envp[])
-{
-       long __res;
-       asm volatile ("int $0x80"
-       : "=a" (__res)
-       : "0" (__NR_execve), "b" (filename), "c" (argv), "d" (envp) : "memory");
-       return __res;
-}
index 54abcc0baf23f0f4181106a7b2a83312c01ed03f..5c9687b1bde6706293e199331e7c866f1b752095 100644 (file)
@@ -561,9 +561,9 @@ int handle_vm86_trap(struct kernel_vm86_regs *regs, long error_code, int trapno)
                if ((trapno == 3) || (trapno == 1)) {
                        KVM86->regs32->ax = VM86_TRAP + (trapno << 8);
                        /* setting this flag forces the code in entry_32.S to
-                          call save_v86_state() and change the stack pointer
-                          to KVM86->regs32 */
-                       set_thread_flag(TIF_IRET);
+                          the path where we call save_v86_state() and change
+                          the stack pointer to KVM86->regs32 */
+                       set_thread_flag(TIF_NOTIFY_RESUME);
                        return 0;
                }
                do_int(regs, trapno, (unsigned char __user *) (regs->pt.ss << 4), SP(regs));
index 8d141b30904657871358a4fb8deb927c7a022257..3a3e8c9e280dcac9ba655491b4300c1d698bfb5a 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/jiffies.h>
 #include <linux/sysctl.h>
 #include <linux/topology.h>
-#include <linux/clocksource.h>
+#include <linux/timekeeper_internal.h>
 #include <linux/getcpu.h>
 #include <linux/cpu.h>
 #include <linux/smp.h>
@@ -82,32 +82,41 @@ void update_vsyscall_tz(void)
        vsyscall_gtod_data.sys_tz = sys_tz;
 }
 
-void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
-                       struct clocksource *clock, u32 mult)
+void update_vsyscall(struct timekeeper *tk)
 {
-       struct timespec monotonic;
+       struct vsyscall_gtod_data *vdata = &vsyscall_gtod_data;
 
-       write_seqcount_begin(&vsyscall_gtod_data.seq);
+       write_seqcount_begin(&vdata->seq);
 
        /* copy vsyscall data */
-       vsyscall_gtod_data.clock.vclock_mode    = clock->archdata.vclock_mode;
-       vsyscall_gtod_data.clock.cycle_last     = clock->cycle_last;
-       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;
+       vdata->clock.vclock_mode        = tk->clock->archdata.vclock_mode;
+       vdata->clock.cycle_last         = tk->clock->cycle_last;
+       vdata->clock.mask               = tk->clock->mask;
+       vdata->clock.mult               = tk->mult;
+       vdata->clock.shift              = tk->shift;
+
+       vdata->wall_time_sec            = tk->xtime_sec;
+       vdata->wall_time_snsec          = tk->xtime_nsec;
+
+       vdata->monotonic_time_sec       = tk->xtime_sec
+                                       + tk->wall_to_monotonic.tv_sec;
+       vdata->monotonic_time_snsec     = tk->xtime_nsec
+                                       + (tk->wall_to_monotonic.tv_nsec
+                                               << tk->shift);
+       while (vdata->monotonic_time_snsec >=
+                                       (((u64)NSEC_PER_SEC) << tk->shift)) {
+               vdata->monotonic_time_snsec -=
+                                       ((u64)NSEC_PER_SEC) << tk->shift;
+               vdata->monotonic_time_sec++;
+       }
 
-       monotonic = timespec_add(*wall_time, *wtm);
-       vsyscall_gtod_data.monotonic_time_sec   = monotonic.tv_sec;
-       vsyscall_gtod_data.monotonic_time_nsec  = monotonic.tv_nsec;
+       vdata->wall_time_coarse.tv_sec  = tk->xtime_sec;
+       vdata->wall_time_coarse.tv_nsec = (long)(tk->xtime_nsec >> tk->shift);
 
-       vsyscall_gtod_data.wall_time_coarse     = __current_kernel_time();
-       vsyscall_gtod_data.monotonic_time_coarse =
-               timespec_add(vsyscall_gtod_data.wall_time_coarse, *wtm);
+       vdata->monotonic_time_coarse    = timespec_add(vdata->wall_time_coarse,
+                                                       tk->wall_to_monotonic);
 
-       write_seqcount_end(&vsyscall_gtod_data.seq);
+       write_seqcount_end(&vdata->seq);
 }
 
 static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
index 7a35a6e71d44332d351cdeb9ec28e96c6467c7b6..a47103fbc6925ac7c717ef1ed2d1f9eccaa35fa4 100644 (file)
@@ -17,7 +17,7 @@
 8      i386    creat                   sys_creat
 9      i386    link                    sys_link
 10     i386    unlink                  sys_unlink
-11     i386    execve                  ptregs_execve                   stub32_execve
+11     i386    execve                  sys_execve                      stub32_execve
 12     i386    chdir                   sys_chdir
 13     i386    time                    sys_time                        compat_sys_time
 14     i386    mknod                   sys_mknod
index aeaff8bef2f162642ef4ad31603a301384f4b1fe..9fa950df80e54ff6d6aa661e3c7e9c6bbe049d2b 100644 (file)
@@ -13,6 +13,8 @@ endmenu
 config UML_X86
        def_bool y
        select GENERIC_FIND_FIRST_BIT
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
 
 config 64BIT
        bool "64-bit kernel" if SUBARCH = "x86"
index b6efe2381b5dc19bad2f6b19c5aa8b6fc0f27b35..4b181b74454f8bdedc9802069d5ec5edaf58fe15 100644 (file)
@@ -1,6 +1,150 @@
 #ifndef __UM_CHECKSUM_H
 #define __UM_CHECKSUM_H
 
+#include <linux/string.h>
+#include <linux/in6.h>
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
+
+/*
+ *     Note: when you get a NULL pointer exception here this means someone
+ *     passed in an incorrect kernel address to one of these functions.
+ *
+ *     If you use these functions directly please don't forget the
+ *     access_ok().
+ */
+
+static __inline__
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+                                      int len, __wsum sum)
+{
+       memcpy(dst, src, len);
+       return csum_partial(dst, len, sum);
+}
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums, and handles user-space pointer exceptions correctly, when needed.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+static __inline__
+__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+                                        int len, __wsum sum, int *err_ptr)
+{
+       if (copy_from_user(dst, src, len)) {
+               *err_ptr = -EFAULT;
+               return (__force __wsum)-1;
+       }
+
+       return csum_partial(dst, len, sum);
+}
+
+/**
+ * csum_fold - Fold and invert a 32bit checksum.
+ * sum: 32bit unfolded sum
+ *
+ * Fold a 32bit running checksum to 16bit and invert it. This is usually
+ * the last step before putting a checksum into a packet.
+ * Make sure not to mix with 64bit checksums.
+ */
+static inline __sum16 csum_fold(__wsum sum)
+{
+       __asm__(
+               "  addl %1,%0\n"
+               "  adcl $0xffff,%0"
+               : "=r" (sum)
+               : "r" ((__force u32)sum << 16),
+                 "0" ((__force u32)sum & 0xffff0000)
+       );
+       return (__force __sum16)(~(__force u32)sum >> 16);
+}
+
+/**
+ * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
+ * @saddr: source address
+ * @daddr: destination address
+ * @len: length of packet
+ * @proto: ip protocol of packet
+ * @sum: initial sum to be added in (32bit unfolded)
+ *
+ * Returns the pseudo header checksum the input data. Result is
+ * 32bit unfolded.
+ */
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+                  unsigned short proto, __wsum sum)
+{
+       asm("  addl %1, %0\n"
+           "  adcl %2, %0\n"
+           "  adcl %3, %0\n"
+           "  adcl $0, %0\n"
+               : "=r" (sum)
+           : "g" (daddr), "g" (saddr), "g" ((len + proto) << 8), "0" (sum));
+       return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+                                          unsigned short len,
+                                          unsigned short proto,
+                                          __wsum sum)
+{
+       return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/**
+ * ip_fast_csum - Compute the IPv4 header checksum efficiently.
+ * iph: ipv4 header
+ * ihl: length of header / 4
+ */
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+       unsigned int sum;
+
+       asm(    "  movl (%1), %0\n"
+               "  subl $4, %2\n"
+               "  jbe 2f\n"
+               "  addl 4(%1), %0\n"
+               "  adcl 8(%1), %0\n"
+               "  adcl 12(%1), %0\n"
+               "1: adcl 16(%1), %0\n"
+               "  lea 4(%1), %1\n"
+               "  decl %2\n"
+               "  jne  1b\n"
+               "  adcl $0, %0\n"
+               "  movl %0, %2\n"
+               "  shrl $16, %0\n"
+               "  addw %w2, %w0\n"
+               "  adcl $0, %0\n"
+               "  notl %0\n"
+               "2:"
+       /* Since the input registers which are loaded with iph and ipl
+          are modified, we must also specify them as outputs, or gcc
+          will assume they contain their original values. */
+       : "=r" (sum), "=r" (iph), "=r" (ihl)
+       : "1" (iph), "2" (ihl)
+       : "memory");
+       return (__force __sum16)sum;
+}
+
 #ifdef CONFIG_X86_32
 # include "checksum_32.h"
 #else
index caab74252e27d64b5c60d2c0636f366aec8f3bba..ab77b6f9a4bf3eef1abc883820067a50cb68ccd2 100644 (file)
@@ -5,145 +5,6 @@
 #ifndef __UM_SYSDEP_CHECKSUM_H
 #define __UM_SYSDEP_CHECKSUM_H
 
-#include "linux/in6.h"
-#include "linux/string.h"
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- *     Note: when you get a NULL pointer exception here this means someone
- *     passed in an incorrect kernel address to one of these functions.
- *
- *     If you use these functions directly please don't forget the
- *     access_ok().
- */
-
-static __inline__
-__wsum csum_partial_copy_nocheck(const void *src, void *dst,
-                                      int len, __wsum sum)
-{
-       memcpy(dst, src, len);
-       return csum_partial(dst, len, sum);
-}
-
-/*
- * the same as csum_partial, but copies from src while it
- * checksums, and handles user-space pointer exceptions correctly, when needed.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-static __inline__
-__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
-                                        int len, __wsum sum, int *err_ptr)
-{
-       if (copy_from_user(dst, src, len)) {
-               *err_ptr = -EFAULT;
-               return (__force __wsum)-1;
-       }
-
-       return csum_partial(dst, len, sum);
-}
-
-/*
- *     This is a version of ip_compute_csum() optimized for IP headers,
- *     which always checksum on 4 octet boundaries.
- *
- *     By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
- *     Arnt Gulbrandsen.
- */
-static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
-       unsigned int sum;
-
-       __asm__ __volatile__(
-           "movl (%1), %0      ;\n"
-           "subl $4, %2        ;\n"
-           "jbe 2f             ;\n"
-           "addl 4(%1), %0     ;\n"
-           "adcl 8(%1), %0     ;\n"
-           "adcl 12(%1), %0    ;\n"
-"1:        adcl 16(%1), %0     ;\n"
-           "lea 4(%1), %1      ;\n"
-           "decl %2            ;\n"
-           "jne 1b             ;\n"
-           "adcl $0, %0        ;\n"
-           "movl %0, %2        ;\n"
-           "shrl $16, %0       ;\n"
-           "addw %w2, %w0      ;\n"
-           "adcl $0, %0        ;\n"
-           "notl %0            ;\n"
-"2:                            ;\n"
-       /* Since the input registers which are loaded with iph and ipl
-          are modified, we must also specify them as outputs, or gcc
-          will assume they contain their original values. */
-       : "=r" (sum), "=r" (iph), "=r" (ihl)
-       : "1" (iph), "2" (ihl)
-       : "memory");
-       return (__force __sum16)sum;
-}
-
-/*
- *     Fold a partial checksum
- */
-
-static inline __sum16 csum_fold(__wsum sum)
-{
-       __asm__(
-               "addl %1, %0            ;\n"
-               "adcl $0xffff, %0       ;\n"
-               : "=r" (sum)
-               : "r" ((__force u32)sum << 16),
-                 "0" ((__force u32)sum & 0xffff0000)
-       );
-       return (__force __sum16)(~(__force u32)sum >> 16);
-}
-
-static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
-                                                  unsigned short len,
-                                                  unsigned short proto,
-                                                  __wsum sum)
-{
-    __asm__(
-       "addl %1, %0    ;\n"
-       "adcl %2, %0    ;\n"
-       "adcl %3, %0    ;\n"
-       "adcl $0, %0    ;\n"
-       : "=r" (sum)
-       : "g" (daddr), "g"(saddr), "g"((len + proto) << 8), "0"(sum));
-    return sum;
-}
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
-                                                  unsigned short len,
-                                                  unsigned short proto,
-                                                  __wsum sum)
-{
-       return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-
 static inline __sum16 ip_compute_csum(const void *buff, int len)
 {
     return csum_fold (csum_partial(buff, len, 0));
@@ -198,4 +59,3 @@ static __inline__ __wsum csum_and_copy_to_user(const void *src,
 }
 
 #endif
-
index a5be9031ea851fcfc0df6ebe7f79ad1217299000..7b6cd1921573c97361b8d486bbba3e8870d53ad6 100644 (file)
@@ -5,131 +5,6 @@
 #ifndef __UM_SYSDEP_CHECKSUM_H
 #define __UM_SYSDEP_CHECKSUM_H
 
-#include "linux/string.h"
-#include "linux/in6.h"
-#include "asm/uaccess.h"
-
-extern __wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- *     Note: when you get a NULL pointer exception here this means someone
- *     passed in an incorrect kernel address to one of these functions.
- *
- *     If you use these functions directly please don't forget the
- *     access_ok().
- */
-
-static __inline__
-__wsum csum_partial_copy_nocheck(const void *src, void *dst,
-                                      int len, __wsum sum)
-{
-       memcpy(dst, src, len);
-       return(csum_partial(dst, len, sum));
-}
-
-static __inline__
-__wsum csum_partial_copy_from_user(const void __user *src,
-                                         void *dst, int len, __wsum sum,
-                                         int *err_ptr)
-{
-        if (copy_from_user(dst, src, len)) {
-                *err_ptr = -EFAULT;
-                return (__force __wsum)-1;
-        }
-        return csum_partial(dst, len, sum);
-}
-
-/**
- * csum_fold - Fold and invert a 32bit checksum.
- * sum: 32bit unfolded sum
- *
- * Fold a 32bit running checksum to 16bit and invert it. This is usually
- * the last step before putting a checksum into a packet.
- * Make sure not to mix with 64bit checksums.
- */
-static inline __sum16 csum_fold(__wsum sum)
-{
-       __asm__(
-               "  addl %1,%0\n"
-               "  adcl $0xffff,%0"
-               : "=r" (sum)
-               : "r" ((__force u32)sum << 16),
-                 "0" ((__force u32)sum & 0xffff0000)
-       );
-       return (__force __sum16)(~(__force u32)sum >> 16);
-}
-
-/**
- * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
- * @saddr: source address
- * @daddr: destination address
- * @len: length of packet
- * @proto: ip protocol of packet
- * @sum: initial sum to be added in (32bit unfolded)
- *
- * Returns the pseudo header checksum the input data. Result is
- * 32bit unfolded.
- */
-static inline __wsum
-csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
-                  unsigned short proto, __wsum sum)
-{
-       asm("  addl %1, %0\n"
-           "  adcl %2, %0\n"
-           "  adcl %3, %0\n"
-           "  adcl $0, %0\n"
-               : "=r" (sum)
-           : "g" (daddr), "g" (saddr), "g" ((len + proto) << 8), "0" (sum));
-       return sum;
-}
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
-                                          unsigned short len,
-                                          unsigned short proto,
-                                          __wsum sum)
-{
-       return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-/**
- * ip_fast_csum - Compute the IPv4 header checksum efficiently.
- * iph: ipv4 header
- * ihl: length of header / 4
- */
-static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
-       unsigned int sum;
-
-       asm(    "  movl (%1), %0\n"
-               "  subl $4, %2\n"
-               "  jbe 2f\n"
-               "  addl 4(%1), %0\n"
-               "  adcl 8(%1), %0\n"
-               "  adcl 12(%1), %0\n"
-               "1: adcl 16(%1), %0\n"
-               "  lea 4(%1), %1\n"
-               "  decl %2\n"
-               "  jne  1b\n"
-               "  adcl $0, %0\n"
-               "  movl %0, %2\n"
-               "  shrl $16, %0\n"
-               "  addw %w2, %w0\n"
-               "  adcl $0, %0\n"
-               "  notl %0\n"
-               "2:"
-       /* Since the input registers which are loaded with iph and ipl
-          are modified, we must also specify them as outputs, or gcc
-          will assume they contain their original values. */
-       : "=r" (sum), "=r" (iph), "=r" (ihl)
-       : "1" (iph), "2" (ihl)
-       : "memory");
-       return (__force __sum16)sum;
-}
-
 static inline unsigned add32_with_carry(unsigned a, unsigned b)
 {
         asm("addl %2,%0\n\t"
index 0e07adc8cbe41b58b43d5d50ba20daf250294579..0feee2fd5077bbd90c9c6e914d1b386f12482120 100644 (file)
@@ -6,7 +6,7 @@
 #define __UM_ELF_X86_H
 
 #include <asm/user.h>
-#include "skas.h"
+#include <skas.h>
 
 #ifdef CONFIG_X86_32
 
index e72cd0df5ba381436b8158ebad5ee0f758ba8eab..755133258c45bd0d1b9a1997e6ac272738c64954 100644 (file)
@@ -1,11 +1,13 @@
 #ifndef __UM_X86_PTRACE_H
 #define __UM_X86_PTRACE_H
 
-#ifdef CONFIG_X86_32
-# include "ptrace_32.h"
-#else
-# include "ptrace_64.h"
+#include <linux/compiler.h>
+#ifndef CONFIG_X86_32
+#define __FRAME_OFFSETS /* Needed to get the R* macros */
 #endif
+#include <asm/ptrace-generic.h>
+
+#define user_mode(r) UPT_IS_USER(&(r)->regs)
 
 #define PT_REGS_AX(r) UPT_AX(&(r)->regs)
 #define PT_REGS_BX(r) UPT_BX(&(r)->regs)
@@ -36,4 +38,52 @@ static inline long regs_return_value(struct pt_regs *regs)
 {
        return PT_REGS_AX(regs);
 }
+
+/*
+ * Forward declaration to avoid including sysdep/tls.h, which causes a
+ * circular include, and compilation failures.
+ */
+struct user_desc;
+
+#ifdef CONFIG_X86_32
+
+#define HOST_AUDIT_ARCH AUDIT_ARCH_I386
+
+extern int ptrace_get_thread_area(struct task_struct *child, int idx,
+                                  struct user_desc __user *user_desc);
+
+extern int ptrace_set_thread_area(struct task_struct *child, int idx,
+                                  struct user_desc __user *user_desc);
+
+#else
+
+#define HOST_AUDIT_ARCH AUDIT_ARCH_X86_64
+
+#define PT_REGS_R8(r) UPT_R8(&(r)->regs)
+#define PT_REGS_R9(r) UPT_R9(&(r)->regs)
+#define PT_REGS_R10(r) UPT_R10(&(r)->regs)
+#define PT_REGS_R11(r) UPT_R11(&(r)->regs)
+#define PT_REGS_R12(r) UPT_R12(&(r)->regs)
+#define PT_REGS_R13(r) UPT_R13(&(r)->regs)
+#define PT_REGS_R14(r) UPT_R14(&(r)->regs)
+#define PT_REGS_R15(r) UPT_R15(&(r)->regs)
+
+#include <asm/errno.h>
+
+static inline int ptrace_get_thread_area(struct task_struct *child, int idx,
+                                         struct user_desc __user *user_desc)
+{
+        return -ENOSYS;
+}
+
+static inline int ptrace_set_thread_area(struct task_struct *child, int idx,
+                                         struct user_desc __user *user_desc)
+{
+        return -ENOSYS;
+}
+
+extern long arch_prctl(struct task_struct *task, int code,
+                      unsigned long __user *addr);
+
+#endif
 #endif /* __UM_X86_PTRACE_H */
diff --git a/arch/x86/um/asm/ptrace_32.h b/arch/x86/um/asm/ptrace_32.h
deleted file mode 100644 (file)
index 2cf2253..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_PTRACE_I386_H
-#define __UM_PTRACE_I386_H
-
-#define HOST_AUDIT_ARCH AUDIT_ARCH_I386
-
-#include "linux/compiler.h"
-#include "asm/ptrace-generic.h"
-
-#define user_mode(r) UPT_IS_USER(&(r)->regs)
-
-/*
- * Forward declaration to avoid including sysdep/tls.h, which causes a
- * circular include, and compilation failures.
- */
-struct user_desc;
-
-extern int ptrace_get_thread_area(struct task_struct *child, int idx,
-                                  struct user_desc __user *user_desc);
-
-extern int ptrace_set_thread_area(struct task_struct *child, int idx,
-                                  struct user_desc __user *user_desc);
-
-#endif
diff --git a/arch/x86/um/asm/ptrace_64.h b/arch/x86/um/asm/ptrace_64.h
deleted file mode 100644 (file)
index ea7bff3..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_PTRACE_X86_64_H
-#define __UM_PTRACE_X86_64_H
-
-#include "linux/compiler.h"
-#include "asm/errno.h"
-
-#define __FRAME_OFFSETS /* Needed to get the R* macros */
-#include "asm/ptrace-generic.h"
-
-#define HOST_AUDIT_ARCH AUDIT_ARCH_X86_64
-
-#define PT_REGS_R8(r) UPT_R8(&(r)->regs)
-#define PT_REGS_R9(r) UPT_R9(&(r)->regs)
-#define PT_REGS_R10(r) UPT_R10(&(r)->regs)
-#define PT_REGS_R11(r) UPT_R11(&(r)->regs)
-#define PT_REGS_R12(r) UPT_R12(&(r)->regs)
-#define PT_REGS_R13(r) UPT_R13(&(r)->regs)
-#define PT_REGS_R14(r) UPT_R14(&(r)->regs)
-#define PT_REGS_R15(r) UPT_R15(&(r)->regs)
-
-/* XXX */
-#define user_mode(r) UPT_IS_USER(&(r)->regs)
-
-struct user_desc;
-
-static inline int ptrace_get_thread_area(struct task_struct *child, int idx,
-                                         struct user_desc __user *user_desc)
-{
-        return -ENOSYS;
-}
-
-static inline int ptrace_set_thread_area(struct task_struct *child, int idx,
-                                         struct user_desc __user *user_desc)
-{
-        return -ENOSYS;
-}
-
-extern long arch_prctl(struct task_struct *task, int code,
-                      unsigned long __user *addr);
-#endif
index 17d88cf2c6c419ff1e8fafc3c779f3a1453d9b59..33daff4dade46cf32ffa1163190cdf8fe5c77f30 100644 (file)
@@ -4,9 +4,9 @@
  */
 
 #include <signal.h>
-#include "kern_util.h"
-#include "longjmp.h"
-#include "sysdep/ptrace.h"
+#include <kern_util.h>
+#include <longjmp.h>
+#include <sysdep/ptrace.h>
 #include <generated/asm-offsets.h>
 
 /* Set during early boot */
index 44e02ba2a2656c54595d50ac315b7a64b5f24a7a..8cc8256c698db19a5728e1fd4b2923bef3abb4ed 100644 (file)
@@ -4,7 +4,7 @@
  * Licensed under the GPL
  */
 
-#include "sysdep/ptrace.h"
+#include <sysdep/ptrace.h>
 
 void arch_check_bugs(void)
 {
index d670f68532f4d159582095eb0f48c73cab0e63f1..8784ab30d91b5504932701ca31cdbbd0476135f6 100644 (file)
@@ -3,7 +3,7 @@
  * Licensed under the GPL
  */
 
-#include "sysdep/ptrace.h"
+#include <sysdep/ptrace.h>
 
 /* These two are from asm-um/uaccess.h and linux/module.h, check them. */
 struct exception_table_entry
index 26b0e39d2ce98a110351e61a96c227fa5b6ca61f..8e08176f0bcbeabf7ffc67403f3f73543b61d2a3 100644 (file)
@@ -7,11 +7,11 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <asm/unistd.h>
-#include "os.h"
-#include "proc_mm.h"
-#include "skas.h"
-#include "skas_ptrace.h"
-#include "sysdep/tls.h"
+#include <os.h>
+#include <proc_mm.h>
+#include <skas.h>
+#include <skas_ptrace.h>
+#include <sysdep/tls.h>
 
 extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
 
index 546518727a731b213eb6dd70560b0e18c88cb689..c6492e75797b7bbceca4437810a59f6eb892a405 100644 (file)
@@ -1,6 +1,6 @@
-#include "linux/mm.h"
-#include "asm/page.h"
-#include "asm/mman.h"
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/mman.h>
 
 const char *arch_vma_name(struct vm_area_struct *vma)
 {
index 0cdbb86b012bf15249ca623d8685e8d899e933a6..41bfe84e11ab0e2bfad89a2e4e1d994f1c8fc288 100644 (file)
@@ -9,8 +9,8 @@
 #ifdef __i386__
 #include <sys/user.h>
 #endif
-#include "longjmp.h"
-#include "sysdep/ptrace_user.h"
+#include <longjmp.h>
+#include <sysdep/ptrace_user.h>
 
 int save_fp_registers(int pid, unsigned long *fp_regs)
 {
index efb16c5c9bcf1b23cd367a47a656eaddcf7442df..8502ad30e61bcfc49a9e28c975d356b4b628a62c 100644 (file)
@@ -2,7 +2,7 @@
 #include <stdlib.h>
 #include <signal.h>
 #include <sys/mman.h>
-#include "longjmp.h"
+#include <longjmp.h>
 
 #ifdef __i386__
 
index 82276b6071af64573e1322915dc93de821e130c8..9d94b3b76c746ac6ca5f5e5eb39f0caf48096693 100644 (file)
@@ -5,7 +5,7 @@
 #include <sys/syscall.h>
 #include <unistd.h>
 
-#include "sysdep/tls.h"
+#include <sysdep/tls.h>
 
 #ifndef PTRACE_GET_THREAD_AREA
 #define PTRACE_GET_THREAD_AREA 25
index 3b949daa095cffa22895ea0ebdfbe3e58a523d32..ce3dd4f36f3ff387a61c894ba0db52b31811341e 100644 (file)
@@ -3,10 +3,10 @@
  * Licensed under the GPL
  */
 
-#include "linux/mm.h"
-#include "linux/sched.h"
-#include "asm/uaccess.h"
-#include "skas.h"
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+#include <skas.h>
 
 extern int arch_switch_tls(struct task_struct *to);
 
index 3960ca1dd35a3bb8f032a8f975e24d1c5c1a6c8f..617885b1899273bf9f6203f21bc9158471db778c 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 #include <errno.h>
-#include "ptrace_user.h"
+#include <ptrace_user.h>
 
 int ptrace_getregs(long pid, unsigned long *regs_out)
 {
index 6ce2d76eb9083daf283998775465b0b18cbb9c2f..eb9356904ad3bdeee29211039e940f51d267d2e3 100644 (file)
@@ -2,7 +2,7 @@
 #define __SYSDEP_X86_PTRACE_H
 
 #include <generated/user_constants.h>
-#include "sysdep/faultinfo.h"
+#include <sysdep/faultinfo.h>
 
 #define MAX_REG_OFFSET (UM_FRAME_SIZE)
 #define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
index bd161e300102c7a37cd8d6f9892ce3947fe62cc7..3f55e5bd3cecd8e669a5b5af7c47babbe893da31 100644 (file)
@@ -1,8 +1,8 @@
 #include <asm/unistd.h>
 #include <sys/mman.h>
 #include <signal.h>
-#include "as-layout.h"
-#include "stub-data.h"
+#include <as-layout.h>
+#include <stub-data.h>
 
 #ifdef __i386__
 #include "stub_32.h"
index 05cb796aecb55f102ca67e4e8240c98a966d968f..8436079be914d3cdc4fa82faa4b5a4f208543308 100644 (file)
@@ -3,8 +3,8 @@
  * Licensed under the GPL
  */
 
-#include "asm/unistd.h"
-#include "sysdep/ptrace.h"
+#include <asm/unistd.h>
+#include <sysdep/ptrace.h>
 
 typedef long syscall_handler_t(struct pt_regs);
 
index ba7363ecf896598c21534af5d09ef1c32e275668..bdaa08cfbcf4bc38eecc3ec57e34c5b0e62ecf2c 100644 (file)
@@ -11,8 +11,8 @@
 #include <asm/unistd.h>
 #include <asm/uaccess.h>
 #include <asm/ucontext.h>
-#include "frame_kern.h"
-#include "skas.h"
+#include <frame_kern.h>
+#include <skas.h>
 
 #ifdef CONFIG_X86_32
 
index 54a36ec20cb75c32b65a7e0e28043a8c19c6a6f0..b972649d3a18f08683587a2cef6c0f3f51a79b39 100644 (file)
@@ -1,4 +1,4 @@
-#include "as-layout.h"
+#include <as-layout.h>
 
        .globl syscall_stub
 .section .__syscall_stub, "ax"
index 20e4a96a6dcbe064ddc99f719e7ffdb506fa4cdc..7160b20172d0a4671d1e5dd6d8fe77956e32a47a 100644 (file)
@@ -1,4 +1,4 @@
-#include "as-layout.h"
+#include <as-layout.h>
 
        .globl syscall_stub
 .section .__syscall_stub, "ax"
index b7450bd22e7d1dae1c2f4d4d77f4ed53a636e5b6..1518d2805ae81733eb0629989f4d39ae595502c2 100644 (file)
@@ -3,9 +3,9 @@
  * Licensed under the GPL
  */
 
-#include "sysdep/stub.h"
-#include "sysdep/faultinfo.h"
-#include "sysdep/mcontext.h"
+#include <sysdep/stub.h>
+#include <sysdep/faultinfo.h>
+#include <sysdep/mcontext.h>
 
 void __attribute__ ((__section__ (".__syscall_stub")))
 stub_segv_handler(int sig, siginfo_t *info, void *p)
index b5408cecac6cd68f5f649b0a45749c1fdab40d77..232e60504b3a8c6c62db26a29b35b07c295d6ac9 100644 (file)
@@ -25,7 +25,6 @@
 #define old_mmap sys_old_mmap
 
 #define ptregs_fork sys_fork
-#define ptregs_execve sys_execve
 #define ptregs_iopl sys_iopl
 #define ptregs_vm86old sys_vm86old
 #define ptregs_clone i386_clone
index 2d5cc51e9bef7c312c7e3837d07e3cde5180d4a0..c9bee5b8c0d3e84e7d42cef757c7c74906514e28 100644 (file)
@@ -3,12 +3,12 @@
  * Licensed under the GPL
  */
 
-#include "linux/kernel.h"
-#include "linux/smp.h"
-#include "linux/sched.h"
-#include "linux/kallsyms.h"
-#include "asm/ptrace.h"
-#include "sysrq.h"
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/sched.h>
+#include <linux/kallsyms.h>
+#include <asm/ptrace.h>
+#include <asm/sysrq.h>
 
 /* This is declared by <linux/sched.h> */
 void show_regs(struct pt_regs *regs)
index 08258f17996926de8db8943c4fc1fdccbce38efa..a0e7fb1134a074c292b248eef68f952aba755581 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/utsname.h>
 #include <asm/current.h>
 #include <asm/ptrace.h>
-#include "sysrq.h"
+#include <asm/sysrq.h>
 
 void __show_regs(struct pt_regs *regs)
 {
index baba84f8ecb8ad8783a00943d31002f35880a7d0..5f5feff3d24cf967c9135b97226bf0f92ef1ae0d 100644 (file)
@@ -3,12 +3,12 @@
  * Licensed under the GPL
  */
 
-#include "linux/percpu.h"
-#include "linux/sched.h"
-#include "asm/uaccess.h"
-#include "os.h"
-#include "skas.h"
-#include "sysdep/tls.h"
+#include <linux/percpu.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+#include <os.h>
+#include <skas.h>
+#include <sysdep/tls.h>
 
 /*
  * If needed we can detect when it's uninitialized.
index f7ba46200ecdd03fc895810ac620c767d7b66851..d22363cb854e51327b1b551ea85b07c9d904489d 100644 (file)
@@ -1,4 +1,4 @@
-#include "linux/sched.h"
+#include <linux/sched.h>
 
 void clear_flushed_tls(struct task_struct *task)
 {
index 885eff49d6abe61c2bdfc3c6673acb69678f161b..4df6c373421a435dfeac34d68407ce10602d688d 100644 (file)
@@ -80,7 +80,7 @@ notrace static long vdso_fallback_gtod(struct timeval *tv, struct timezone *tz)
 }
 
 
-notrace static inline long vgetns(void)
+notrace static inline u64 vgetsns(void)
 {
        long v;
        cycles_t cycles;
@@ -91,21 +91,24 @@ notrace static inline long vgetns(void)
        else
                return 0;
        v = (cycles - gtod->clock.cycle_last) & gtod->clock.mask;
-       return (v * gtod->clock.mult) >> gtod->clock.shift;
+       return v * gtod->clock.mult;
 }
 
 /* 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;
+       unsigned long seq;
+       u64 ns;
        int mode;
 
+       ts->tv_nsec = 0;
        do {
                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();
+               ns = gtod->wall_time_snsec;
+               ns += vgetsns();
+               ns >>= gtod->clock.shift;
        } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
 
        timespec_add_ns(ts, ns);
@@ -114,15 +117,18 @@ notrace static int __always_inline do_realtime(struct timespec *ts)
 
 notrace static int do_monotonic(struct timespec *ts)
 {
-       unsigned long seq, ns;
+       unsigned long seq;
+       u64 ns;
        int mode;
 
+       ts->tv_nsec = 0;
        do {
                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();
+               ns = gtod->monotonic_time_snsec;
+               ns += vgetsns();
+               ns >>= gtod->clock.shift;
        } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
        timespec_add_ns(ts, ns);
 
index bf788d34530df5fbb93e60bb64023d80f7bbedf3..e3497f240eabb869e6cda863036689e6b093899d 100644 (file)
@@ -987,7 +987,16 @@ static void xen_write_cr4(unsigned long cr4)
 
        native_write_cr4(cr4);
 }
-
+#ifdef CONFIG_X86_64
+static inline unsigned long xen_read_cr8(void)
+{
+       return 0;
+}
+static inline void xen_write_cr8(unsigned long val)
+{
+       BUG_ON(val);
+}
+#endif
 static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
 {
        int ret;
@@ -1156,6 +1165,11 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
        .read_cr4_safe = native_read_cr4_safe,
        .write_cr4 = xen_write_cr4,
 
+#ifdef CONFIG_X86_64
+       .read_cr8 = xen_read_cr8,
+       .write_cr8 = xen_write_cr8,
+#endif
+
        .wbinvd = native_wbinvd,
 
        .read_msr = native_read_msr_safe,
@@ -1164,6 +1178,8 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
        .read_tsc = native_read_tsc,
        .read_pmc = native_read_pmc,
 
+       .read_tscp = native_read_tscp,
+
        .iret = xen_iret,
        .irq_enable_sysexit = xen_sysexit,
 #ifdef CONFIG_X86_64
index fd28d86fe3d2c979c5c9ac0e5ab95bf3d977a224..6226c99729b963594a2e133290cbf8f3c6e681b8 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/gfp.h>
 #include <linux/memblock.h>
 #include <linux/seq_file.h>
+#include <linux/crash_dump.h>
 
 #include <trace/events/xen.h>
 
@@ -2381,6 +2382,43 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
 EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region);
 
 #ifdef CONFIG_XEN_PVHVM
+#ifdef CONFIG_PROC_VMCORE
+/*
+ * This function is used in two contexts:
+ * - the kdump kernel has to check whether a pfn of the crashed kernel
+ *   was a ballooned page. vmcore is using this function to decide
+ *   whether to access a pfn of the crashed kernel.
+ * - the kexec kernel has to check whether a pfn was ballooned by the
+ *   previous kernel. If the pfn is ballooned, handle it properly.
+ * Returns 0 if the pfn is not backed by a RAM page, the caller may
+ * handle the pfn special in this case.
+ */
+static int xen_oldmem_pfn_is_ram(unsigned long pfn)
+{
+       struct xen_hvm_get_mem_type a = {
+               .domid = DOMID_SELF,
+               .pfn = pfn,
+       };
+       int ram;
+
+       if (HYPERVISOR_hvm_op(HVMOP_get_mem_type, &a))
+               return -ENXIO;
+
+       switch (a.mem_type) {
+               case HVMMEM_mmio_dm:
+                       ram = 0;
+                       break;
+               case HVMMEM_ram_rw:
+               case HVMMEM_ram_ro:
+               default:
+                       ram = 1;
+                       break;
+       }
+
+       return ram;
+}
+#endif
+
 static void xen_hvm_exit_mmap(struct mm_struct *mm)
 {
        struct xen_hvm_pagetable_dying a;
@@ -2411,6 +2449,9 @@ void __init xen_hvm_init_mmu_ops(void)
 {
        if (is_pagetable_dying_supported())
                pv_mmu_ops.exit_mmap = xen_hvm_exit_mmap;
+#ifdef CONFIG_PROC_VMCORE
+       register_oldmem_pfn_is_ram(&xen_oldmem_pfn_is_ram);
+#endif
 }
 #endif
 
index 0d20f5526dd8e99b7ba770d677bc17480f4bdb40..fccd81eddff1f6de89b07cc13c362809364c9507 100644 (file)
@@ -1,3 +1,4 @@
 include include/asm-generic/Kbuild.asm
 
 generic-y += clkdev.h
+generic-y += exec.h
diff --git a/arch/xtensa/include/asm/exec.h b/arch/xtensa/include/asm/exec.h
deleted file mode 100644 (file)
index af949e2..0000000
+++ /dev/null
@@ -1,14 +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) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_EXEC_H
-#define _XTENSA_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* _XTENSA_EXEC_H */
index 81abfd5d01acfdb7c01f4c5e6c1ba4bc3f731e06..9481004ac119e04ef8f6a80921561de071b445a1 100644 (file)
@@ -128,19 +128,14 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SIGPENDING         1       /* signal pending */
 #define TIF_NEED_RESCHED       2       /* rescheduling necessary */
 #define TIF_SINGLESTEP         3       /* restore singlestep on return to user mode */
-#define TIF_IRET               4       /* return with iret */
 #define TIF_MEMDIE             5       /* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK    6       /* restore signal mask in do_signal() */
 #define TIF_NOTIFY_RESUME      7       /* callback before returning to user */
-#define TIF_POLLING_NRFLAG     16      /* true if poll_idle() is polling TIF_NEED_RESCHED */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP                (1<<TIF_SINGLESTEP)
-#define _TIF_IRET              (1<<TIF_IRET)
-#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
-#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 
 #define _TIF_WORK_MASK         0x0000FFFE      /* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK      0x0000FFFF      /* work to do on any return to u-space */
index bc44311aa18cc7207dd0e4bde95585cc6b81c3c0..bc020825cce55197e6aaf7dfc127203a143e3553 100644 (file)
@@ -328,13 +328,13 @@ long xtensa_execve(const char __user *name,
                    struct pt_regs *regs)
 {
        long error;
-       char * filename;
+       struct filename *filename;
 
        filename = getname(name);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
 out:
        return error;
index efe4e854b3cdd06808eec1bcd3fe8fa70b07ed96..63c566f627bc9ca13ac0df36a9752698ca9a62c0 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/personality.h>
-#include <linux/freezer.h>
 #include <linux/tracehook.h>
 
 #include <asm/ucontext.h>
@@ -527,9 +526,6 @@ static void do_signal(struct pt_regs *regs)
 
 void do_notify_resume(struct pt_regs *regs)
 {
-       if (!user_mode(regs))
-               return;
-
        if (test_thread_flag(TIF_SIGPENDING))
                do_signal(regs);
 
index d2da64170513caae07726bca207f71ba13065b46..a33870b1847bb70c6ef1937f7bef4e93bdf9c980 100644 (file)
@@ -606,8 +606,8 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
        /*
         * A queue starts its life with bypass turned on to avoid
         * unnecessary bypass on/off overhead and nasty surprises during
-        * init.  The initial bypass will be finished at the end of
-        * blk_init_allocated_queue().
+        * init.  The initial bypass will be finished when the queue is
+        * registered by blk_register_queue().
         */
        q->bypass_depth = 1;
        __set_bit(QUEUE_FLAG_BYPASS, &q->queue_flags);
@@ -694,7 +694,7 @@ blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn,
        q->request_fn           = rfn;
        q->prep_rq_fn           = NULL;
        q->unprep_rq_fn         = NULL;
-       q->queue_flags          = QUEUE_FLAG_DEFAULT;
+       q->queue_flags          |= QUEUE_FLAG_DEFAULT;
 
        /* Override internal queue lock with supplied lock pointer */
        if (lock)
@@ -710,11 +710,6 @@ blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn,
        /* init elevator */
        if (elevator_init(q, NULL))
                return NULL;
-
-       blk_queue_congestion_threshold(q);
-
-       /* all done, end the initial bypass */
-       blk_queue_bypass_end(q);
        return q;
 }
 EXPORT_SYMBOL(blk_init_allocated_queue);
@@ -1657,8 +1652,8 @@ generic_make_request_checks(struct bio *bio)
                goto end_io;
        }
 
-       if (unlikely(!(bio->bi_rw & REQ_DISCARD) &&
-                    nr_sectors > queue_max_hw_sectors(q))) {
+       if (likely(bio_is_rw(bio) &&
+                  nr_sectors > queue_max_hw_sectors(q))) {
                printk(KERN_ERR "bio too big device %s (%u > %u)\n",
                       bdevname(bio->bi_bdev, b),
                       bio_sectors(bio),
@@ -1699,8 +1694,12 @@ generic_make_request_checks(struct bio *bio)
 
        if ((bio->bi_rw & REQ_DISCARD) &&
            (!blk_queue_discard(q) ||
-            ((bio->bi_rw & REQ_SECURE) &&
-             !blk_queue_secdiscard(q)))) {
+            ((bio->bi_rw & REQ_SECURE) && !blk_queue_secdiscard(q)))) {
+               err = -EOPNOTSUPP;
+               goto end_io;
+       }
+
+       if (bio->bi_rw & REQ_WRITE_SAME && !bdev_write_same(bio->bi_bdev)) {
                err = -EOPNOTSUPP;
                goto end_io;
        }
@@ -1810,15 +1809,20 @@ EXPORT_SYMBOL(generic_make_request);
  */
 void submit_bio(int rw, struct bio *bio)
 {
-       int count = bio_sectors(bio);
-
        bio->bi_rw |= rw;
 
        /*
         * If it's a regular read/write or a barrier with data attached,
         * go through the normal accounting stuff before submission.
         */
-       if (bio_has_data(bio) && !(rw & REQ_DISCARD)) {
+       if (bio_has_data(bio)) {
+               unsigned int count;
+
+               if (unlikely(rw & REQ_WRITE_SAME))
+                       count = bdev_logical_block_size(bio->bi_bdev) >> 9;
+               else
+                       count = bio_sectors(bio);
+
                if (rw & WRITE) {
                        count_vm_events(PGPGOUT, count);
                } else {
@@ -1864,11 +1868,10 @@ EXPORT_SYMBOL(submit_bio);
  */
 int blk_rq_check_limits(struct request_queue *q, struct request *rq)
 {
-       if (rq->cmd_flags & REQ_DISCARD)
+       if (!rq_mergeable(rq))
                return 0;
 
-       if (blk_rq_sectors(rq) > queue_max_sectors(q) ||
-           blk_rq_bytes(rq) > queue_max_hw_sectors(q) << 9) {
+       if (blk_rq_sectors(rq) > blk_queue_get_max_sectors(q, rq->cmd_flags)) {
                printk(KERN_ERR "%s: over max size limit.\n", __func__);
                return -EIO;
        }
@@ -2340,7 +2343,7 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
        req->buffer = bio_data(req->bio);
 
        /* update sector only for requests with clear definition of sector */
-       if (req->cmd_type == REQ_TYPE_FS || (req->cmd_flags & REQ_DISCARD))
+       if (req->cmd_type == REQ_TYPE_FS)
                req->__sector += total_bytes >> 9;
 
        /* mixed attributes always follow the first bio */
@@ -2781,16 +2784,10 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
        blk_rq_init(NULL, rq);
 
        __rq_for_each_bio(bio_src, rq_src) {
-               bio = bio_alloc_bioset(gfp_mask, bio_src->bi_max_vecs, bs);
+               bio = bio_clone_bioset(bio_src, gfp_mask, bs);
                if (!bio)
                        goto free_and_out;
 
-               __bio_clone(bio, bio_src);
-
-               if (bio_integrity(bio_src) &&
-                   bio_integrity_clone(bio, bio_src, gfp_mask, bs))
-                       goto free_and_out;
-
                if (bio_ctr && bio_ctr(bio, bio_src, data))
                        goto free_and_out;
 
@@ -2807,7 +2804,7 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
 
 free_and_out:
        if (bio)
-               bio_free(bio, bs);
+               bio_put(bio);
        blk_rq_unprep_clone(rq);
 
        return -ENOMEM;
index 19cc761cacb2a4b71fe9d4579226025324ffddf5..9373b58dfab185878baf9cb196bcd61dd7637894 100644 (file)
@@ -129,6 +129,80 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
 }
 EXPORT_SYMBOL(blkdev_issue_discard);
 
+/**
+ * blkdev_issue_write_same - queue a write same operation
+ * @bdev:      target blockdev
+ * @sector:    start sector
+ * @nr_sects:  number of sectors to write
+ * @gfp_mask:  memory allocation flags (for bio_alloc)
+ * @page:      page containing data to write
+ *
+ * Description:
+ *    Issue a write same request for the sectors in question.
+ */
+int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
+                           sector_t nr_sects, gfp_t gfp_mask,
+                           struct page *page)
+{
+       DECLARE_COMPLETION_ONSTACK(wait);
+       struct request_queue *q = bdev_get_queue(bdev);
+       unsigned int max_write_same_sectors;
+       struct bio_batch bb;
+       struct bio *bio;
+       int ret = 0;
+
+       if (!q)
+               return -ENXIO;
+
+       max_write_same_sectors = q->limits.max_write_same_sectors;
+
+       if (max_write_same_sectors == 0)
+               return -EOPNOTSUPP;
+
+       atomic_set(&bb.done, 1);
+       bb.flags = 1 << BIO_UPTODATE;
+       bb.wait = &wait;
+
+       while (nr_sects) {
+               bio = bio_alloc(gfp_mask, 1);
+               if (!bio) {
+                       ret = -ENOMEM;
+                       break;
+               }
+
+               bio->bi_sector = sector;
+               bio->bi_end_io = bio_batch_end_io;
+               bio->bi_bdev = bdev;
+               bio->bi_private = &bb;
+               bio->bi_vcnt = 1;
+               bio->bi_io_vec->bv_page = page;
+               bio->bi_io_vec->bv_offset = 0;
+               bio->bi_io_vec->bv_len = bdev_logical_block_size(bdev);
+
+               if (nr_sects > max_write_same_sectors) {
+                       bio->bi_size = max_write_same_sectors << 9;
+                       nr_sects -= max_write_same_sectors;
+                       sector += max_write_same_sectors;
+               } else {
+                       bio->bi_size = nr_sects << 9;
+                       nr_sects = 0;
+               }
+
+               atomic_inc(&bb.done);
+               submit_bio(REQ_WRITE | REQ_WRITE_SAME, bio);
+       }
+
+       /* Wait for bios in-flight */
+       if (!atomic_dec_and_test(&bb.done))
+               wait_for_completion(&wait);
+
+       if (!test_bit(BIO_UPTODATE, &bb.flags))
+               ret = -ENOTSUPP;
+
+       return ret;
+}
+EXPORT_SYMBOL(blkdev_issue_write_same);
+
 /**
  * blkdev_issue_zeroout - generate number of zero filed write bios
  * @bdev:      blockdev to issue
@@ -140,7 +214,7 @@ EXPORT_SYMBOL(blkdev_issue_discard);
  *  Generate and issue number of bios with zerofiled pages.
  */
 
-int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
+int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
                        sector_t nr_sects, gfp_t gfp_mask)
 {
        int ret;
@@ -190,4 +264,32 @@ int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
 
        return ret;
 }
+
+/**
+ * blkdev_issue_zeroout - zero-fill a block range
+ * @bdev:      blockdev to write
+ * @sector:    start sector
+ * @nr_sects:  number of sectors to write
+ * @gfp_mask:  memory allocation flags (for bio_alloc)
+ *
+ * Description:
+ *  Generate and issue number of bios with zerofiled pages.
+ */
+
+int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
+                        sector_t nr_sects, gfp_t gfp_mask)
+{
+       if (bdev_write_same(bdev)) {
+               unsigned char bdn[BDEVNAME_SIZE];
+
+               if (!blkdev_issue_write_same(bdev, sector, nr_sects, gfp_mask,
+                                            ZERO_PAGE(0)))
+                       return 0;
+
+               bdevname(bdev, bdn);
+               pr_err("%s: WRITE SAME failed. Manually zeroing.\n", bdn);
+       }
+
+       return __blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask);
+}
 EXPORT_SYMBOL(blkdev_issue_zeroout);
index e76279e411622519eebb54d4802eb11b796788db..936a110de0b9c63ac8a3ab6d44d80d60d5533088 100644 (file)
@@ -275,14 +275,8 @@ no_merge:
 int ll_back_merge_fn(struct request_queue *q, struct request *req,
                     struct bio *bio)
 {
-       unsigned short max_sectors;
-
-       if (unlikely(req->cmd_type == REQ_TYPE_BLOCK_PC))
-               max_sectors = queue_max_hw_sectors(q);
-       else
-               max_sectors = queue_max_sectors(q);
-
-       if (blk_rq_sectors(req) + bio_sectors(bio) > max_sectors) {
+       if (blk_rq_sectors(req) + bio_sectors(bio) >
+           blk_rq_get_max_sectors(req)) {
                req->cmd_flags |= REQ_NOMERGE;
                if (req == q->last_merge)
                        q->last_merge = NULL;
@@ -299,15 +293,8 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req,
 int ll_front_merge_fn(struct request_queue *q, struct request *req,
                      struct bio *bio)
 {
-       unsigned short max_sectors;
-
-       if (unlikely(req->cmd_type == REQ_TYPE_BLOCK_PC))
-               max_sectors = queue_max_hw_sectors(q);
-       else
-               max_sectors = queue_max_sectors(q);
-
-
-       if (blk_rq_sectors(req) + bio_sectors(bio) > max_sectors) {
+       if (blk_rq_sectors(req) + bio_sectors(bio) >
+           blk_rq_get_max_sectors(req)) {
                req->cmd_flags |= REQ_NOMERGE;
                if (req == q->last_merge)
                        q->last_merge = NULL;
@@ -338,7 +325,8 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
        /*
         * Will it become too large?
         */
-       if ((blk_rq_sectors(req) + blk_rq_sectors(next)) > queue_max_sectors(q))
+       if ((blk_rq_sectors(req) + blk_rq_sectors(next)) >
+           blk_rq_get_max_sectors(req))
                return 0;
 
        total_phys_segments = req->nr_phys_segments + next->nr_phys_segments;
@@ -417,16 +405,7 @@ static int attempt_merge(struct request_queue *q, struct request *req,
        if (!rq_mergeable(req) || !rq_mergeable(next))
                return 0;
 
-       /*
-        * Don't merge file system requests and discard requests
-        */
-       if ((req->cmd_flags & REQ_DISCARD) != (next->cmd_flags & REQ_DISCARD))
-               return 0;
-
-       /*
-        * Don't merge discard requests and secure discard requests
-        */
-       if ((req->cmd_flags & REQ_SECURE) != (next->cmd_flags & REQ_SECURE))
+       if (!blk_check_merge_flags(req->cmd_flags, next->cmd_flags))
                return 0;
 
        /*
@@ -440,6 +419,10 @@ static int attempt_merge(struct request_queue *q, struct request *req,
            || next->special)
                return 0;
 
+       if (req->cmd_flags & REQ_WRITE_SAME &&
+           !blk_write_same_mergeable(req->bio, next->bio))
+               return 0;
+
        /*
         * If we are allowed to merge, then append bio list
         * from next to rq and release next. merge_requests_fn
@@ -521,15 +504,10 @@ int blk_attempt_req_merge(struct request_queue *q, struct request *rq,
 
 bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
 {
-       if (!rq_mergeable(rq))
+       if (!rq_mergeable(rq) || !bio_mergeable(bio))
                return false;
 
-       /* don't merge file system requests and discard requests */
-       if ((bio->bi_rw & REQ_DISCARD) != (rq->bio->bi_rw & REQ_DISCARD))
-               return false;
-
-       /* don't merge discard requests and secure discard requests */
-       if ((bio->bi_rw & REQ_SECURE) != (rq->bio->bi_rw & REQ_SECURE))
+       if (!blk_check_merge_flags(rq->cmd_flags, bio->bi_rw))
                return false;
 
        /* different data direction or already started, don't merge */
@@ -544,6 +522,11 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
        if (bio_integrity(bio) != blk_integrity_rq(rq))
                return false;
 
+       /* must be using the same buffer */
+       if (rq->cmd_flags & REQ_WRITE_SAME &&
+           !blk_write_same_mergeable(rq->bio, bio))
+               return false;
+
        return true;
 }
 
index 565a6786032f59e40cee28bf4bde4ffb451cffa8..779bb7646bcd13f871dd4ba20862722db699078c 100644 (file)
@@ -113,6 +113,7 @@ void blk_set_default_limits(struct queue_limits *lim)
        lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
        lim->max_segment_size = BLK_MAX_SEGMENT_SIZE;
        lim->max_sectors = lim->max_hw_sectors = BLK_SAFE_MAX_SECTORS;
+       lim->max_write_same_sectors = 0;
        lim->max_discard_sectors = 0;
        lim->discard_granularity = 0;
        lim->discard_alignment = 0;
@@ -144,6 +145,7 @@ void blk_set_stacking_limits(struct queue_limits *lim)
        lim->max_segments = USHRT_MAX;
        lim->max_hw_sectors = UINT_MAX;
        lim->max_sectors = UINT_MAX;
+       lim->max_write_same_sectors = UINT_MAX;
 }
 EXPORT_SYMBOL(blk_set_stacking_limits);
 
@@ -285,6 +287,18 @@ void blk_queue_max_discard_sectors(struct request_queue *q,
 }
 EXPORT_SYMBOL(blk_queue_max_discard_sectors);
 
+/**
+ * blk_queue_max_write_same_sectors - set max sectors for a single write same
+ * @q:  the request queue for the device
+ * @max_write_same_sectors: maximum number of sectors to write per command
+ **/
+void blk_queue_max_write_same_sectors(struct request_queue *q,
+                                     unsigned int max_write_same_sectors)
+{
+       q->limits.max_write_same_sectors = max_write_same_sectors;
+}
+EXPORT_SYMBOL(blk_queue_max_write_same_sectors);
+
 /**
  * blk_queue_max_segments - set max hw segments for a request for this queue
  * @q:  the request queue for the device
@@ -510,6 +524,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
 
        t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
        t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
+       t->max_write_same_sectors = min(t->max_write_same_sectors,
+                                       b->max_write_same_sectors);
        t->bounce_pfn = min_not_zero(t->bounce_pfn, b->bounce_pfn);
 
        t->seg_boundary_mask = min_not_zero(t->seg_boundary_mask,
index 9628b291f96057a42cbf6a5492bd7480fe7e93da..ce6204608822462c18bda72c7ca2403fd17ec5eb 100644 (file)
@@ -26,9 +26,15 @@ queue_var_show(unsigned long var, char *page)
 static ssize_t
 queue_var_store(unsigned long *var, const char *page, size_t count)
 {
-       char *p = (char *) page;
+       int err;
+       unsigned long v;
+
+       err = strict_strtoul(page, 10, &v);
+       if (err || v > UINT_MAX)
+               return -EINVAL;
+
+       *var = v;
 
-       *var = simple_strtoul(p, &p, 10);
        return count;
 }
 
@@ -48,6 +54,9 @@ queue_requests_store(struct request_queue *q, const char *page, size_t count)
                return -EINVAL;
 
        ret = queue_var_store(&nr, page, count);
+       if (ret < 0)
+               return ret;
+
        if (nr < BLKDEV_MIN_RQ)
                nr = BLKDEV_MIN_RQ;
 
@@ -102,6 +111,9 @@ queue_ra_store(struct request_queue *q, const char *page, size_t count)
        unsigned long ra_kb;
        ssize_t ret = queue_var_store(&ra_kb, page, count);
 
+       if (ret < 0)
+               return ret;
+
        q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10);
 
        return ret;
@@ -168,6 +180,13 @@ static ssize_t queue_discard_zeroes_data_show(struct request_queue *q, char *pag
        return queue_var_show(queue_discard_zeroes_data(q), page);
 }
 
+static ssize_t queue_write_same_max_show(struct request_queue *q, char *page)
+{
+       return sprintf(page, "%llu\n",
+               (unsigned long long)q->limits.max_write_same_sectors << 9);
+}
+
+
 static ssize_t
 queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
 {
@@ -176,6 +195,9 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
                        page_kb = 1 << (PAGE_CACHE_SHIFT - 10);
        ssize_t ret = queue_var_store(&max_sectors_kb, page, count);
 
+       if (ret < 0)
+               return ret;
+
        if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb)
                return -EINVAL;
 
@@ -236,6 +258,9 @@ static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
        unsigned long nm;
        ssize_t ret = queue_var_store(&nm, page, count);
 
+       if (ret < 0)
+               return ret;
+
        spin_lock_irq(q->queue_lock);
        queue_flag_clear(QUEUE_FLAG_NOMERGES, q);
        queue_flag_clear(QUEUE_FLAG_NOXMERGES, q);
@@ -264,6 +289,9 @@ queue_rq_affinity_store(struct request_queue *q, const char *page, size_t count)
        unsigned long val;
 
        ret = queue_var_store(&val, page, count);
+       if (ret < 0)
+               return ret;
+
        spin_lock_irq(q->queue_lock);
        if (val == 2) {
                queue_flag_set(QUEUE_FLAG_SAME_COMP, q);
@@ -364,6 +392,11 @@ static struct queue_sysfs_entry queue_discard_zeroes_data_entry = {
        .show = queue_discard_zeroes_data_show,
 };
 
+static struct queue_sysfs_entry queue_write_same_max_entry = {
+       .attr = {.name = "write_same_max_bytes", .mode = S_IRUGO },
+       .show = queue_write_same_max_show,
+};
+
 static struct queue_sysfs_entry queue_nonrot_entry = {
        .attr = {.name = "rotational", .mode = S_IRUGO | S_IWUSR },
        .show = queue_show_nonrot,
@@ -411,6 +444,7 @@ static struct attribute *default_attrs[] = {
        &queue_discard_granularity_entry.attr,
        &queue_discard_max_entry.attr,
        &queue_discard_zeroes_data_entry.attr,
+       &queue_write_same_max_entry.attr,
        &queue_nonrot_entry.attr,
        &queue_nomerges_entry.attr,
        &queue_rq_affinity_entry.attr,
@@ -527,6 +561,12 @@ int blk_register_queue(struct gendisk *disk)
        if (WARN_ON(!q))
                return -ENXIO;
 
+       /*
+        * Initialization must be complete by now.  Finish the initial
+        * bypass from queue allocation.
+        */
+       blk_queue_bypass_end(q);
+
        ret = blk_trace_init_sysfs(dev);
        if (ret)
                return ret;
index 4af6f5cc1167a65494dc52b39cd3f1dfd1271087..cc345e1d8d4ea0088832833ef985d6b1e764fa44 100644 (file)
@@ -186,7 +186,8 @@ int blk_queue_init_tags(struct request_queue *q, int depth,
                tags = __blk_queue_init_tags(q, depth);
 
                if (!tags)
-                       goto fail;
+                       return -ENOMEM;
+
        } else if (q->queue_tags) {
                rc = blk_queue_resize_tags(q, depth);
                if (rc)
@@ -203,9 +204,6 @@ int blk_queue_init_tags(struct request_queue *q, int depth,
        queue_flag_set_unlocked(QUEUE_FLAG_QUEUED, q);
        INIT_LIST_HEAD(&q->tag_busy_list);
        return 0;
-fail:
-       kfree(tags);
-       return -ENOMEM;
 }
 EXPORT_SYMBOL(blk_queue_init_tags);
 
index 2a0ea32d249fdaa9694e0249e435777565535d70..ca51543b248ca16f0eb28e937ec321e52f3130c8 100644 (file)
@@ -171,14 +171,13 @@ static inline int queue_congestion_off_threshold(struct request_queue *q)
  *
  *     a) it's attached to a gendisk, and
  *     b) the queue had IO stats enabled when this request was started, and
- *     c) it's a file system request or a discard request
+ *     c) it's a file system request
  */
 static inline int blk_do_io_stat(struct request *rq)
 {
        return rq->rq_disk &&
               (rq->cmd_flags & REQ_IO_STAT) &&
-              (rq->cmd_type == REQ_TYPE_FS ||
-               (rq->cmd_flags & REQ_DISCARD));
+               (rq->cmd_type == REQ_TYPE_FS);
 }
 
 /*
index 6a55d418896f5ceee0042da69c0177c495219cbc..9b1d42b62f207d5a37f657e21fc65769bc9e85c2 100644 (file)
@@ -562,8 +562,7 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where)
 
        if (rq->cmd_flags & REQ_SOFTBARRIER) {
                /* barriers are scheduling boundary, update end_sector */
-               if (rq->cmd_type == REQ_TYPE_FS ||
-                   (rq->cmd_flags & REQ_DISCARD)) {
+               if (rq->cmd_type == REQ_TYPE_FS) {
                        q->end_sector = rq_end_sector(rq);
                        q->boundary_rq = rq;
                }
@@ -605,8 +604,7 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where)
                if (elv_attempt_insert_merge(q, rq))
                        break;
        case ELEVATOR_INSERT_SORT:
-               BUG_ON(rq->cmd_type != REQ_TYPE_FS &&
-                      !(rq->cmd_flags & REQ_DISCARD));
+               BUG_ON(rq->cmd_type != REQ_TYPE_FS);
                rq->cmd_flags |= REQ_SORTED;
                q->nr_sorted++;
                if (rq_mergeable(rq)) {
index 4a85096f5410adde92d01cd58ecba30373c808f1..a31d91d9bc5a33d70388b0063e1d80c41383c125 100644 (file)
@@ -185,6 +185,22 @@ static int blk_ioctl_discard(struct block_device *bdev, uint64_t start,
        return blkdev_issue_discard(bdev, start, len, GFP_KERNEL, flags);
 }
 
+static int blk_ioctl_zeroout(struct block_device *bdev, uint64_t start,
+                            uint64_t len)
+{
+       if (start & 511)
+               return -EINVAL;
+       if (len & 511)
+               return -EINVAL;
+       start >>= 9;
+       len >>= 9;
+
+       if (start + len > (i_size_read(bdev->bd_inode) >> 9))
+               return -EINVAL;
+
+       return blkdev_issue_zeroout(bdev, start, len, GFP_KERNEL);
+}
+
 static int put_ushort(unsigned long arg, unsigned short val)
 {
        return put_user(val, (unsigned short __user *)arg);
@@ -300,6 +316,17 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
                return blk_ioctl_discard(bdev, range[0], range[1],
                                         cmd == BLKSECDISCARD);
        }
+       case BLKZEROOUT: {
+               uint64_t range[2];
+
+               if (!(mode & FMODE_WRITE))
+                       return -EBADF;
+
+               if (copy_from_user(range, (void __user *)arg, sizeof(range)))
+                       return -EFAULT;
+
+               return blk_ioctl_zeroout(bdev, range[0], range[1]);
+       }
 
        case HDIO_GETGEO: {
                struct hd_geometry geo;
index f93a0320e952dd6b07fb8c73739ee73d3c1af0a0..f55683ad4ffad67063b0825a844c3214c07d0601 100644 (file)
@@ -162,23 +162,12 @@ static const struct block_device_operations drbd_ops = {
        .release = drbd_release,
 };
 
-static void bio_destructor_drbd(struct bio *bio)
-{
-       bio_free(bio, drbd_md_io_bio_set);
-}
-
 struct bio *bio_alloc_drbd(gfp_t gfp_mask)
 {
-       struct bio *bio;
-
        if (!drbd_md_io_bio_set)
                return bio_alloc(gfp_mask, 1);
 
-       bio = bio_alloc_bioset(gfp_mask, 1, drbd_md_io_bio_set);
-       if (!bio)
-               return NULL;
-       bio->bi_destructor = bio_destructor_drbd;
-       return bio;
+       return bio_alloc_bioset(gfp_mask, 1, drbd_md_io_bio_set);
 }
 
 #ifdef __CHECKER__
index 87311ebac0db4e5cc3f04fe0e255bf01d62aa730..1bbc681688e4375aa5098bd1b99d85b38baa796e 100644 (file)
@@ -266,11 +266,10 @@ static struct bio *bio_chain_clone(struct bio *old_chain, gfp_t gfpmask)
        struct bio *tmp, *new_chain = NULL, *tail = NULL;
 
        while (old_chain) {
-               tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs);
+               tmp = bio_clone_kmalloc(old_chain, gfpmask);
                if (!tmp)
                        goto err_out;
 
-               __bio_clone(tmp, old_chain);
                tmp->bi_bdev = NULL;
                gfpmask &= ~__GFP_WAIT;
                tmp->bi_next = NULL;
index ba66e4445f412a3c6d3321de8050ad937d902deb..2e7de7a59bfca01c4a35edaa1824a7a38f90e52f 100644 (file)
@@ -522,38 +522,6 @@ static void pkt_bio_finished(struct pktcdvd_device *pd)
        }
 }
 
-static void pkt_bio_destructor(struct bio *bio)
-{
-       kfree(bio->bi_io_vec);
-       kfree(bio);
-}
-
-static struct bio *pkt_bio_alloc(int nr_iovecs)
-{
-       struct bio_vec *bvl = NULL;
-       struct bio *bio;
-
-       bio = kmalloc(sizeof(struct bio), GFP_KERNEL);
-       if (!bio)
-               goto no_bio;
-       bio_init(bio);
-
-       bvl = kcalloc(nr_iovecs, sizeof(struct bio_vec), GFP_KERNEL);
-       if (!bvl)
-               goto no_bvl;
-
-       bio->bi_max_vecs = nr_iovecs;
-       bio->bi_io_vec = bvl;
-       bio->bi_destructor = pkt_bio_destructor;
-
-       return bio;
-
- no_bvl:
-       kfree(bio);
- no_bio:
-       return NULL;
-}
-
 /*
  * Allocate a packet_data struct
  */
@@ -567,7 +535,7 @@ static struct packet_data *pkt_alloc_packet_data(int frames)
                goto no_pkt;
 
        pkt->frames = frames;
-       pkt->w_bio = pkt_bio_alloc(frames);
+       pkt->w_bio = bio_kmalloc(GFP_KERNEL, frames);
        if (!pkt->w_bio)
                goto no_bio;
 
@@ -581,9 +549,10 @@ static struct packet_data *pkt_alloc_packet_data(int frames)
        bio_list_init(&pkt->orig_bios);
 
        for (i = 0; i < frames; i++) {
-               struct bio *bio = pkt_bio_alloc(1);
+               struct bio *bio = bio_kmalloc(GFP_KERNEL, 1);
                if (!bio)
                        goto no_rd_bio;
+
                pkt->r_bios[i] = bio;
        }
 
@@ -1111,21 +1080,17 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
         * Schedule reads for missing parts of the packet.
         */
        for (f = 0; f < pkt->frames; f++) {
-               struct bio_vec *vec;
-
                int p, offset;
+
                if (written[f])
                        continue;
+
                bio = pkt->r_bios[f];
-               vec = bio->bi_io_vec;
-               bio_init(bio);
-               bio->bi_max_vecs = 1;
+               bio_reset(bio);
                bio->bi_sector = pkt->sector + f * (CD_FRAMESIZE >> 9);
                bio->bi_bdev = pd->bdev;
                bio->bi_end_io = pkt_end_io_read;
                bio->bi_private = pkt;
-               bio->bi_io_vec = vec;
-               bio->bi_destructor = pkt_bio_destructor;
 
                p = (f * CD_FRAMESIZE) / PAGE_SIZE;
                offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
@@ -1418,14 +1383,11 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
        }
 
        /* Start the write request */
-       bio_init(pkt->w_bio);
-       pkt->w_bio->bi_max_vecs = PACKET_MAX_SIZE;
+       bio_reset(pkt->w_bio);
        pkt->w_bio->bi_sector = pkt->sector;
        pkt->w_bio->bi_bdev = pd->bdev;
        pkt->w_bio->bi_end_io = pkt_end_io_packet_write;
        pkt->w_bio->bi_private = pkt;
-       pkt->w_bio->bi_io_vec = bvec;
-       pkt->w_bio->bi_destructor = pkt_bio_destructor;
        for (f = 0; f < pkt->frames; f++)
                if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
                        BUG();
index aab9605f0b43291974c67855caf920c5656c8b0d..24ffd8cec51e1c62eea5dd4af7b7d32410321f58 100644 (file)
@@ -74,21 +74,21 @@ static inline void netwinder_ds1620_reset(void)
 
 static inline void netwinder_lock(unsigned long *flags)
 {
-       spin_lock_irqsave(&nw_gpio_lock, *flags);
+       raw_spin_lock_irqsave(&nw_gpio_lock, *flags);
 }
 
 static inline void netwinder_unlock(unsigned long *flags)
 {
-       spin_unlock_irqrestore(&nw_gpio_lock, *flags);
+       raw_spin_unlock_irqrestore(&nw_gpio_lock, *flags);
 }
 
 static inline void netwinder_set_fan(int i)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&nw_gpio_lock, flags);
+       raw_spin_lock_irqsave(&nw_gpio_lock, flags);
        nw_gpio_modify_op(GPIO_FAN, i ? GPIO_FAN : 0);
-       spin_unlock_irqrestore(&nw_gpio_lock, flags);
+       raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
 }
 
 static inline int netwinder_get_fan(void)
index a0e2f7d70355a1c16e8c67df377e41f47aee37c3..e371480d36394974cc5e27787c6a243e2c075dcf 100644 (file)
@@ -583,9 +583,9 @@ static void kick_open(void)
         * we want to write a bit pattern XXX1 to Xilinx to enable
         * the write gate, which will be open for about the next 2ms.
         */
-       spin_lock_irqsave(&nw_gpio_lock, flags);
+       raw_spin_lock_irqsave(&nw_gpio_lock, flags);
        nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE);
-       spin_unlock_irqrestore(&nw_gpio_lock, flags);
+       raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
 
        /*
         * let the ISA bus to catch on...
index 54a3a6d09819922486f4de420f4ed0f96a6e7bb0..0bb207eaef2ff65e854866fddfdb11fce27cc066 100644 (file)
@@ -285,7 +285,7 @@ static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd,
 
 static const struct file_operations raw_fops = {
        .read           = do_sync_read,
-       .aio_read       = generic_file_aio_read,
+       .aio_read       = blkdev_aio_read,
        .write          = do_sync_write,
        .aio_write      = blkdev_aio_write,
        .fsync          = blkdev_fsync,
index 65f8e9a54975e8274c9de6403718f5ff39ee2e85..1f3417a8322dfe8b0ca773873e058f7eb3a6c283 100644 (file)
 #include <asm/smp_plat.h>
 #include <asm/cpu.h>
 
-#include <plat/clock.h>
-#include <plat/omap-pm.h>
-#include <plat/common.h>
-#include <plat/omap_device.h>
-
-#include <mach/hardware.h>
-
 /* OPP tolerance in percentage */
 #define        OPP_TOLERANCE   4
 
 static struct cpufreq_frequency_table *freq_table;
 static atomic_t freq_table_users = ATOMIC_INIT(0);
 static struct clk *mpu_clk;
-static char *mpu_clk_name;
 static struct device *mpu_dev;
 static struct regulator *mpu_reg;
 
@@ -108,6 +100,14 @@ static int omap_target(struct cpufreq_policy *policy,
        }
 
        freq = freqs.new * 1000;
+       ret = clk_round_rate(mpu_clk, freq);
+       if (IS_ERR_VALUE(ret)) {
+               dev_warn(mpu_dev,
+                        "CPUfreq: Cannot find matching frequency for %lu\n",
+                        freq);
+               return ret;
+       }
+       freq = ret;
 
        if (mpu_reg) {
                opp = opp_find_freq_ceil(mpu_dev, &freq);
@@ -172,7 +172,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
 {
        int result = 0;
 
-       mpu_clk = clk_get(NULL, mpu_clk_name);
+       mpu_clk = clk_get(NULL, "cpufreq_ck");
        if (IS_ERR(mpu_clk))
                return PTR_ERR(mpu_clk);
 
@@ -253,22 +253,10 @@ static struct cpufreq_driver omap_driver = {
 
 static int __init omap_cpufreq_init(void)
 {
-       if (cpu_is_omap24xx())
-               mpu_clk_name = "virt_prcm_set";
-       else if (cpu_is_omap34xx())
-               mpu_clk_name = "dpll1_ck";
-       else if (cpu_is_omap44xx())
-               mpu_clk_name = "dpll_mpu_ck";
-
-       if (!mpu_clk_name) {
-               pr_err("%s: unsupported Silicon?\n", __func__);
-               return -EINVAL;
-       }
-
-       mpu_dev = omap_device_get_by_hwmod_name("mpu");
-       if (IS_ERR(mpu_dev)) {
+       mpu_dev = get_cpu_device(0);
+       if (!mpu_dev) {
                pr_warning("%s: unable to get the mpu device\n", __func__);
-               return PTR_ERR(mpu_dev);
+               return -EINVAL;
        }
 
        mpu_reg = regulator_get(mpu_dev, "vcc");
index d06ea2950dd9ffb9ad266bcedbb2db934e020376..677cd6e4e1a1c1afb387217fdc9f0f363c3149cf 100644 (file)
@@ -208,6 +208,16 @@ config SIRF_DMA
        help
          Enable support for the CSR SiRFprimaII DMA engine.
 
+config TI_EDMA
+       tristate "TI EDMA support"
+       depends on ARCH_DAVINCI
+       select DMA_ENGINE
+       select DMA_VIRTUAL_CHANNELS
+       default n
+       help
+         Enable support for the TI EDMA controller. This DMA
+         engine is found on TI DaVinci and AM33xx parts.
+
 config ARCH_HAS_ASYNC_TX_FIND_CHANNEL
        bool
 
@@ -292,6 +302,13 @@ config DMA_OMAP
        select DMA_ENGINE
        select DMA_VIRTUAL_CHANNELS
 
+config MMP_PDMA
+       bool "MMP PDMA support"
+       depends on (ARCH_MMP || ARCH_PXA)
+       select DMA_ENGINE
+       help
+         Support the MMP PDMA engine for PXA and MMP platfrom.
+
 config DMA_ENGINE
        bool
 
index 4cf6b128ab9a466b8f4c2c5237064f0f8e80846f..7428feaa8705393e13a7425ea5259dc8eabd4d30 100644 (file)
@@ -23,6 +23,7 @@ obj-$(CONFIG_IMX_DMA) += imx-dma.o
 obj-$(CONFIG_MXS_DMA) += mxs-dma.o
 obj-$(CONFIG_TIMB_DMA) += timb_dma.o
 obj-$(CONFIG_SIRF_DMA) += sirf-dma.o
+obj-$(CONFIG_TI_EDMA) += edma.o
 obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
 obj-$(CONFIG_TEGRA20_APB_DMA) += tegra20-apb-dma.o
 obj-$(CONFIG_PL330_DMA) += pl330.o
@@ -32,3 +33,4 @@ obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
 obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o
 obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o
 obj-$(CONFIG_DMA_OMAP) += omap-dma.o
+obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
index 6fbeebb9486fdae644a0268393c7650033b856b4..d1cc5791476bc39c700f9ab0913eb5f3e50d1bda 100644 (file)
@@ -1892,6 +1892,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
        pl08x->pd = dev_get_platdata(&adev->dev);
        if (!pl08x->pd) {
                dev_err(&adev->dev, "no platform data supplied\n");
+               ret = -EINVAL;
                goto out_no_platdata;
        }
 
@@ -1943,6 +1944,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
                dev_err(&adev->dev, "%s failed to allocate "
                        "physical channel holders\n",
                        __func__);
+               ret = -ENOMEM;
                goto out_no_phychans;
        }
 
index d3c5a5a88f1e9af91b97848f6d9c107ac2010da5..c4b0eb3cde819977fbf2ac45cfb1b588ccc04f37 100644 (file)
  * which does not support descriptor writeback.
  */
 
+static inline unsigned int dwc_get_dms(struct dw_dma_slave *slave)
+{
+       return slave ? slave->dst_master : 0;
+}
+
+static inline unsigned int dwc_get_sms(struct dw_dma_slave *slave)
+{
+       return slave ? slave->src_master : 1;
+}
+
 #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;   \
+               int _dms = dwc_get_dms(__slave);                \
+               int _sms = dwc_get_sms(__slave);                \
                u8 _smsize = __slave ? _sconfig->src_maxburst : \
                        DW_DMA_MSIZE_16;                        \
                u8 _dmsize = __slave ? _sconfig->dst_maxburst : \
                 | DWC_CTLL_SMS(_sms));                         \
        })
 
-/*
- * This is configuration-dependent and usually a funny size like 4095.
- *
- * Note that this is a transfer count, i.e. if we transfer 32-bit
- * words, we can do 16380 bytes per descriptor.
- *
- * This parameter is also system-specific.
- */
-#define DWC_MAX_COUNT  4095U
-
 /*
  * Number of descriptors to allocate for each channel. This should be
  * made configurable somehow; preferably, the clients (at least the
@@ -177,6 +177,11 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 
                cfghi = dws->cfg_hi;
                cfglo |= dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK;
+       } else {
+               if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV)
+                       cfghi = DWC_CFGH_DST_PER(dwc->dma_sconfig.slave_id);
+               else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM)
+                       cfghi = DWC_CFGH_SRC_PER(dwc->dma_sconfig.slave_id);
        }
 
        channel_writel(dwc, CFG_LO, cfglo);
@@ -206,7 +211,7 @@ static inline unsigned int dwc_fast_fls(unsigned long long v)
        return 0;
 }
 
-static void dwc_dump_chan_regs(struct dw_dma_chan *dwc)
+static inline void dwc_dump_chan_regs(struct dw_dma_chan *dwc)
 {
        dev_err(chan2dev(&dwc->chan),
                "  SAR: 0x%x DAR: 0x%x LLP: 0x%x CTL: 0x%x:%08x\n",
@@ -227,10 +232,29 @@ static inline void dwc_chan_disable(struct dw_dma *dw, struct dw_dma_chan *dwc)
 
 /*----------------------------------------------------------------------*/
 
+/* Perform single block transfer */
+static inline void dwc_do_single_block(struct dw_dma_chan *dwc,
+                                      struct dw_desc *desc)
+{
+       struct dw_dma   *dw = to_dw_dma(dwc->chan.device);
+       u32             ctllo;
+
+       /* Software emulation of LLP mode relies on interrupts to continue
+        * multi block transfer. */
+       ctllo = desc->lli.ctllo | DWC_CTLL_INT_EN;
+
+       channel_writel(dwc, SAR, desc->lli.sar);
+       channel_writel(dwc, DAR, desc->lli.dar);
+       channel_writel(dwc, CTL_LO, ctllo);
+       channel_writel(dwc, CTL_HI, desc->lli.ctlhi);
+       channel_set_bit(dw, CH_EN, dwc->mask);
+}
+
 /* Called with dwc->lock held and bh disabled */
 static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
 {
        struct dw_dma   *dw = to_dw_dma(dwc->chan.device);
+       unsigned long   was_soft_llp;
 
        /* ASSERT:  channel is idle */
        if (dma_readl(dw, CH_EN) & dwc->mask) {
@@ -242,6 +266,26 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
                return;
        }
 
+       if (dwc->nollp) {
+               was_soft_llp = test_and_set_bit(DW_DMA_IS_SOFT_LLP,
+                                               &dwc->flags);
+               if (was_soft_llp) {
+                       dev_err(chan2dev(&dwc->chan),
+                               "BUG: Attempted to start new LLP transfer "
+                               "inside ongoing one\n");
+                       return;
+               }
+
+               dwc_initialize(dwc);
+
+               dwc->tx_list = &first->tx_list;
+               dwc->tx_node_active = first->tx_list.next;
+
+               dwc_do_single_block(dwc, first);
+
+               return;
+       }
+
        dwc_initialize(dwc);
 
        channel_writel(dwc, LLP, first->txd.phys);
@@ -553,8 +597,36 @@ static void dw_dma_tasklet(unsigned long data)
                        dwc_handle_cyclic(dw, dwc, status_err, status_xfer);
                else if (status_err & (1 << i))
                        dwc_handle_error(dw, dwc);
-               else if (status_xfer & (1 << i))
+               else if (status_xfer & (1 << i)) {
+                       unsigned long flags;
+
+                       spin_lock_irqsave(&dwc->lock, flags);
+                       if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags)) {
+                               if (dwc->tx_node_active != dwc->tx_list) {
+                                       struct dw_desc *desc =
+                                               list_entry(dwc->tx_node_active,
+                                                          struct dw_desc,
+                                                          desc_node);
+
+                                       dma_writel(dw, CLEAR.XFER, dwc->mask);
+
+                                       /* move pointer to next descriptor */
+                                       dwc->tx_node_active =
+                                               dwc->tx_node_active->next;
+
+                                       dwc_do_single_block(dwc, desc);
+
+                                       spin_unlock_irqrestore(&dwc->lock, flags);
+                                       continue;
+                               } else {
+                                       /* we are done here */
+                                       clear_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags);
+                               }
+                       }
+                       spin_unlock_irqrestore(&dwc->lock, flags);
+
                        dwc_scan_descriptors(dw, dwc);
+               }
        }
 
        /*
@@ -636,6 +708,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
                size_t len, unsigned long flags)
 {
        struct dw_dma_chan      *dwc = to_dw_dma_chan(chan);
+       struct dw_dma_slave     *dws = chan->private;
        struct dw_desc          *desc;
        struct dw_desc          *first;
        struct dw_desc          *prev;
@@ -643,6 +716,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
        size_t                  offset;
        unsigned int            src_width;
        unsigned int            dst_width;
+       unsigned int            data_width;
        u32                     ctllo;
 
        dev_vdbg(chan2dev(chan),
@@ -655,7 +729,11 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
                return NULL;
        }
 
-       src_width = dst_width = dwc_fast_fls(src | dest | len);
+       data_width = min_t(unsigned int, dwc->dw->data_width[dwc_get_sms(dws)],
+                                        dwc->dw->data_width[dwc_get_dms(dws)]);
+
+       src_width = dst_width = min_t(unsigned int, data_width,
+                                     dwc_fast_fls(src | dest | len));
 
        ctllo = DWC_DEFAULT_CTLLO(chan)
                        | DWC_CTLL_DST_WIDTH(dst_width)
@@ -667,7 +745,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 
        for (offset = 0; offset < len; offset += xfer_count << src_width) {
                xfer_count = min_t(size_t, (len - offset) >> src_width,
-                               DWC_MAX_COUNT);
+                                          dwc->block_size);
 
                desc = dwc_desc_get(dwc);
                if (!desc)
@@ -725,6 +803,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
        dma_addr_t              reg;
        unsigned int            reg_width;
        unsigned int            mem_width;
+       unsigned int            data_width;
        unsigned int            i;
        struct scatterlist      *sg;
        size_t                  total_len = 0;
@@ -748,6 +827,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) :
                        DWC_CTLL_FC(DW_DMA_FC_D_M2P);
 
+               data_width = dwc->dw->data_width[dwc_get_sms(dws)];
+
                for_each_sg(sgl, sg, sg_len, i) {
                        struct dw_desc  *desc;
                        u32             len, dlen, mem;
@@ -755,7 +836,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                        mem = sg_dma_address(sg);
                        len = sg_dma_len(sg);
 
-                       mem_width = dwc_fast_fls(mem | len);
+                       mem_width = min_t(unsigned int,
+                                         data_width, dwc_fast_fls(mem | len));
 
 slave_sg_todev_fill_desc:
                        desc = dwc_desc_get(dwc);
@@ -768,8 +850,8 @@ slave_sg_todev_fill_desc:
                        desc->lli.sar = mem;
                        desc->lli.dar = reg;
                        desc->lli.ctllo = ctllo | DWC_CTLL_SRC_WIDTH(mem_width);
-                       if ((len >> mem_width) > DWC_MAX_COUNT) {
-                               dlen = DWC_MAX_COUNT << mem_width;
+                       if ((len >> mem_width) > dwc->block_size) {
+                               dlen = dwc->block_size << mem_width;
                                mem += dlen;
                                len -= dlen;
                        } else {
@@ -808,6 +890,8 @@ slave_sg_todev_fill_desc:
                ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) :
                        DWC_CTLL_FC(DW_DMA_FC_D_P2M);
 
+               data_width = dwc->dw->data_width[dwc_get_dms(dws)];
+
                for_each_sg(sgl, sg, sg_len, i) {
                        struct dw_desc  *desc;
                        u32             len, dlen, mem;
@@ -815,7 +899,8 @@ slave_sg_todev_fill_desc:
                        mem = sg_dma_address(sg);
                        len = sg_dma_len(sg);
 
-                       mem_width = dwc_fast_fls(mem | len);
+                       mem_width = min_t(unsigned int,
+                                         data_width, dwc_fast_fls(mem | len));
 
 slave_sg_fromdev_fill_desc:
                        desc = dwc_desc_get(dwc);
@@ -828,8 +913,8 @@ slave_sg_fromdev_fill_desc:
                        desc->lli.sar = reg;
                        desc->lli.dar = mem;
                        desc->lli.ctllo = ctllo | DWC_CTLL_DST_WIDTH(mem_width);
-                       if ((len >> reg_width) > DWC_MAX_COUNT) {
-                               dlen = DWC_MAX_COUNT << reg_width;
+                       if ((len >> reg_width) > dwc->block_size) {
+                               dlen = dwc->block_size << reg_width;
                                mem += dlen;
                                len -= dlen;
                        } else {
@@ -945,6 +1030,8 @@ static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
        } else if (cmd == DMA_TERMINATE_ALL) {
                spin_lock_irqsave(&dwc->lock, flags);
 
+               clear_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags);
+
                dwc_chan_disable(dw, dwc);
 
                dwc->paused = false;
@@ -1187,6 +1274,13 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
        unsigned long                   flags;
 
        spin_lock_irqsave(&dwc->lock, flags);
+       if (dwc->nollp) {
+               spin_unlock_irqrestore(&dwc->lock, flags);
+               dev_dbg(chan2dev(&dwc->chan),
+                               "channel doesn't support LLP transfers\n");
+               return ERR_PTR(-EINVAL);
+       }
+
        if (!list_empty(&dwc->queue) || !list_empty(&dwc->active_list)) {
                spin_unlock_irqrestore(&dwc->lock, flags);
                dev_dbg(chan2dev(&dwc->chan),
@@ -1212,7 +1306,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
        periods = buf_len / period_len;
 
        /* Check for too big/unaligned periods and unaligned DMA buffer. */
-       if (period_len > (DWC_MAX_COUNT << reg_width))
+       if (period_len > (dwc->block_size << reg_width))
                goto out_err;
        if (unlikely(period_len & ((1 << reg_width) - 1)))
                goto out_err;
@@ -1374,6 +1468,11 @@ static int __devinit dw_probe(struct platform_device *pdev)
        struct resource         *io;
        struct dw_dma           *dw;
        size_t                  size;
+       void __iomem            *regs;
+       bool                    autocfg;
+       unsigned int            dw_params;
+       unsigned int            nr_channels;
+       unsigned int            max_blk_size = 0;
        int                     irq;
        int                     err;
        int                     i;
@@ -1390,32 +1489,46 @@ static int __devinit dw_probe(struct platform_device *pdev)
        if (irq < 0)
                return irq;
 
-       size = sizeof(struct dw_dma);
-       size += pdata->nr_channels * sizeof(struct dw_dma_chan);
-       dw = kzalloc(size, GFP_KERNEL);
+       regs = devm_request_and_ioremap(&pdev->dev, io);
+       if (!regs)
+               return -EBUSY;
+
+       dw_params = dma_read_byaddr(regs, DW_PARAMS);
+       autocfg = dw_params >> DW_PARAMS_EN & 0x1;
+
+       if (autocfg)
+               nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 0x7) + 1;
+       else
+               nr_channels = pdata->nr_channels;
+
+       size = sizeof(struct dw_dma) + nr_channels * sizeof(struct dw_dma_chan);
+       dw = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
        if (!dw)
                return -ENOMEM;
 
-       if (!request_mem_region(io->start, DW_REGLEN, pdev->dev.driver->name)) {
-               err = -EBUSY;
-               goto err_kfree;
-       }
+       dw->clk = devm_clk_get(&pdev->dev, "hclk");
+       if (IS_ERR(dw->clk))
+               return PTR_ERR(dw->clk);
+       clk_prepare_enable(dw->clk);
 
-       dw->regs = ioremap(io->start, DW_REGLEN);
-       if (!dw->regs) {
-               err = -ENOMEM;
-               goto err_release_r;
-       }
+       dw->regs = regs;
+
+       /* get hardware configuration parameters */
+       if (autocfg) {
+               max_blk_size = dma_readl(dw, MAX_BLK_SIZE);
 
-       dw->clk = clk_get(&pdev->dev, "hclk");
-       if (IS_ERR(dw->clk)) {
-               err = PTR_ERR(dw->clk);
-               goto err_clk;
+               dw->nr_masters = (dw_params >> DW_PARAMS_NR_MASTER & 3) + 1;
+               for (i = 0; i < dw->nr_masters; i++) {
+                       dw->data_width[i] =
+                               (dw_params >> DW_PARAMS_DATA_WIDTH(i) & 3) + 2;
+               }
+       } else {
+               dw->nr_masters = pdata->nr_masters;
+               memcpy(dw->data_width, pdata->data_width, 4);
        }
-       clk_prepare_enable(dw->clk);
 
        /* Calculate all channel mask before DMA setup */
-       dw->all_chan_mask = (1 << pdata->nr_channels) - 1;
+       dw->all_chan_mask = (1 << nr_channels) - 1;
 
        /* force dma off, just in case */
        dw_dma_off(dw);
@@ -1423,17 +1536,19 @@ static int __devinit dw_probe(struct platform_device *pdev)
        /* disable BLOCK interrupts as well */
        channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
 
-       err = request_irq(irq, dw_dma_interrupt, 0, "dw_dmac", dw);
+       err = devm_request_irq(&pdev->dev, irq, dw_dma_interrupt, 0,
+                              "dw_dmac", dw);
        if (err)
-               goto err_irq;
+               return err;
 
        platform_set_drvdata(pdev, dw);
 
        tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw);
 
        INIT_LIST_HEAD(&dw->dma.channels);
-       for (i = 0; i < pdata->nr_channels; i++) {
+       for (i = 0; i < nr_channels; i++) {
                struct dw_dma_chan      *dwc = &dw->chan[i];
+               int                     r = nr_channels - i - 1;
 
                dwc->chan.device = &dw->dma;
                dma_cookie_init(&dwc->chan);
@@ -1445,7 +1560,7 @@ static int __devinit dw_probe(struct platform_device *pdev)
 
                /* 7 is highest priority & 0 is lowest. */
                if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING)
-                       dwc->priority = pdata->nr_channels - i - 1;
+                       dwc->priority = r;
                else
                        dwc->priority = i;
 
@@ -1458,6 +1573,32 @@ static int __devinit dw_probe(struct platform_device *pdev)
                INIT_LIST_HEAD(&dwc->free_list);
 
                channel_clear_bit(dw, CH_EN, dwc->mask);
+
+               dwc->dw = dw;
+
+               /* hardware configuration */
+               if (autocfg) {
+                       unsigned int dwc_params;
+
+                       dwc_params = dma_read_byaddr(regs + r * sizeof(u32),
+                                                    DWC_PARAMS);
+
+                       /* Decode maximum block size for given channel. The
+                        * stored 4 bit value represents blocks from 0x00 for 3
+                        * up to 0x0a for 4095. */
+                       dwc->block_size =
+                               (4 << ((max_blk_size >> 4 * i) & 0xf)) - 1;
+                       dwc->nollp =
+                               (dwc_params >> DWC_PARAMS_MBLK_EN & 0x1) == 0;
+               } else {
+                       dwc->block_size = pdata->block_size;
+
+                       /* Check if channel supports multi block transfer */
+                       channel_writel(dwc, LLP, 0xfffffffc);
+                       dwc->nollp =
+                               (channel_readl(dwc, LLP) & 0xfffffffc) == 0;
+                       channel_writel(dwc, LLP, 0);
+               }
        }
 
        /* Clear all interrupts on all channels. */
@@ -1486,35 +1627,21 @@ static int __devinit dw_probe(struct platform_device *pdev)
        dma_writel(dw, CFG, DW_CFG_DMA_EN);
 
        printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n",
-                       dev_name(&pdev->dev), pdata->nr_channels);
+                       dev_name(&pdev->dev), nr_channels);
 
        dma_async_device_register(&dw->dma);
 
        return 0;
-
-err_irq:
-       clk_disable_unprepare(dw->clk);
-       clk_put(dw->clk);
-err_clk:
-       iounmap(dw->regs);
-       dw->regs = NULL;
-err_release_r:
-       release_resource(io);
-err_kfree:
-       kfree(dw);
-       return err;
 }
 
 static int __devexit dw_remove(struct platform_device *pdev)
 {
        struct dw_dma           *dw = platform_get_drvdata(pdev);
        struct dw_dma_chan      *dwc, *_dwc;
-       struct resource         *io;
 
        dw_dma_off(dw);
        dma_async_device_unregister(&dw->dma);
 
-       free_irq(platform_get_irq(pdev, 0), dw);
        tasklet_kill(&dw->tasklet);
 
        list_for_each_entry_safe(dwc, _dwc, &dw->dma.channels,
@@ -1523,17 +1650,6 @@ static int __devexit dw_remove(struct platform_device *pdev)
                channel_clear_bit(dw, CH_EN, dwc->mask);
        }
 
-       clk_disable_unprepare(dw->clk);
-       clk_put(dw->clk);
-
-       iounmap(dw->regs);
-       dw->regs = NULL;
-
-       io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(io->start, DW_REGLEN);
-
-       kfree(dw);
-
        return 0;
 }
 
index 50830bee087a65eac6178e9111b72db9cbe0c49a..ff39fa6cd2bc443a7d96fd9d85be015f643704f5 100644 (file)
@@ -82,9 +82,39 @@ struct dw_dma_regs {
        DW_REG(ID);
        DW_REG(TEST);
 
+       /* reserved */
+       DW_REG(__reserved0);
+       DW_REG(__reserved1);
+
        /* optional encoded params, 0x3c8..0x3f7 */
+       u32     __reserved;
+
+       /* per-channel configuration registers */
+       u32     DWC_PARAMS[DW_DMA_MAX_NR_CHANNELS];
+       u32     MULTI_BLK_TYPE;
+       u32     MAX_BLK_SIZE;
+
+       /* top-level parameters */
+       u32     DW_PARAMS;
 };
 
+/* To access the registers in early stage of probe */
+#define dma_read_byaddr(addr, name) \
+       readl((addr) + offsetof(struct dw_dma_regs, name))
+
+/* Bitfields in DW_PARAMS */
+#define DW_PARAMS_NR_CHAN      8               /* number of channels */
+#define DW_PARAMS_NR_MASTER    11              /* number of AHB masters */
+#define DW_PARAMS_DATA_WIDTH(n)        (15 + 2 * (n))
+#define DW_PARAMS_DATA_WIDTH1  15              /* master 1 data width */
+#define DW_PARAMS_DATA_WIDTH2  17              /* master 2 data width */
+#define DW_PARAMS_DATA_WIDTH3  19              /* master 3 data width */
+#define DW_PARAMS_DATA_WIDTH4  21              /* master 4 data width */
+#define DW_PARAMS_EN           28              /* encoded parameters */
+
+/* Bitfields in DWC_PARAMS */
+#define DWC_PARAMS_MBLK_EN     11              /* multi block transfer */
+
 /* Bitfields in CTL_LO */
 #define DWC_CTLL_INT_EN                (1 << 0)        /* irqs enabled? */
 #define DWC_CTLL_DST_WIDTH(n)  ((n)<<1)        /* bytes per element */
@@ -140,10 +170,9 @@ struct dw_dma_regs {
 /* Bitfields in CFG */
 #define DW_CFG_DMA_EN          (1 << 0)
 
-#define DW_REGLEN              0x400
-
 enum dw_dmac_flags {
        DW_DMA_IS_CYCLIC = 0,
+       DW_DMA_IS_SOFT_LLP = 1,
 };
 
 struct dw_dma_chan {
@@ -154,6 +183,10 @@ struct dw_dma_chan {
        bool                    paused;
        bool                    initialized;
 
+       /* software emulation of the LLP transfers */
+       struct list_head        *tx_list;
+       struct list_head        *tx_node_active;
+
        spinlock_t              lock;
 
        /* these other elements are all protected by lock */
@@ -165,8 +198,15 @@ struct dw_dma_chan {
 
        unsigned int            descs_allocated;
 
+       /* hardware configuration */
+       unsigned int            block_size;
+       bool                    nollp;
+
        /* configuration passed via DMA_SLAVE_CONFIG */
        struct dma_slave_config dma_sconfig;
+
+       /* backlink to dw_dma */
+       struct dw_dma           *dw;
 };
 
 static inline struct dw_dma_chan_regs __iomem *
@@ -193,6 +233,10 @@ struct dw_dma {
 
        u8                      all_chan_mask;
 
+       /* hardware configuration */
+       unsigned char           nr_masters;
+       unsigned char           data_width[4];
+
        struct dw_dma_chan      chan[0];
 };
 
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
new file mode 100644 (file)
index 0000000..05aea3c
--- /dev/null
@@ -0,0 +1,671 @@
+/*
+ * TI EDMA DMA engine driver
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * 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/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <mach/edma.h>
+
+#include "dmaengine.h"
+#include "virt-dma.h"
+
+/*
+ * This will go away when the private EDMA API is folded
+ * into this driver and the platform device(s) are
+ * instantiated in the arch code. We can only get away
+ * with this simplification because DA8XX may not be built
+ * in the same kernel image with other DaVinci parts. This
+ * avoids having to sprinkle dmaengine driver platform devices
+ * and data throughout all the existing board files.
+ */
+#ifdef CONFIG_ARCH_DAVINCI_DA8XX
+#define EDMA_CTLRS     2
+#define EDMA_CHANS     32
+#else
+#define EDMA_CTLRS     1
+#define EDMA_CHANS     64
+#endif /* CONFIG_ARCH_DAVINCI_DA8XX */
+
+/* Max of 16 segments per channel to conserve PaRAM slots */
+#define MAX_NR_SG              16
+#define EDMA_MAX_SLOTS         MAX_NR_SG
+#define EDMA_DESCRIPTORS       16
+
+struct edma_desc {
+       struct virt_dma_desc            vdesc;
+       struct list_head                node;
+       int                             absync;
+       int                             pset_nr;
+       struct edmacc_param             pset[0];
+};
+
+struct edma_cc;
+
+struct edma_chan {
+       struct virt_dma_chan            vchan;
+       struct list_head                node;
+       struct edma_desc                *edesc;
+       struct edma_cc                  *ecc;
+       int                             ch_num;
+       bool                            alloced;
+       int                             slot[EDMA_MAX_SLOTS];
+       dma_addr_t                      addr;
+       int                             addr_width;
+       int                             maxburst;
+};
+
+struct edma_cc {
+       int                             ctlr;
+       struct dma_device               dma_slave;
+       struct edma_chan                slave_chans[EDMA_CHANS];
+       int                             num_slave_chans;
+       int                             dummy_slot;
+};
+
+static inline struct edma_cc *to_edma_cc(struct dma_device *d)
+{
+       return container_of(d, struct edma_cc, dma_slave);
+}
+
+static inline struct edma_chan *to_edma_chan(struct dma_chan *c)
+{
+       return container_of(c, struct edma_chan, vchan.chan);
+}
+
+static inline struct edma_desc
+*to_edma_desc(struct dma_async_tx_descriptor *tx)
+{
+       return container_of(tx, struct edma_desc, vdesc.tx);
+}
+
+static void edma_desc_free(struct virt_dma_desc *vdesc)
+{
+       kfree(container_of(vdesc, struct edma_desc, vdesc));
+}
+
+/* Dispatch a queued descriptor to the controller (caller holds lock) */
+static void edma_execute(struct edma_chan *echan)
+{
+       struct virt_dma_desc *vdesc = vchan_next_desc(&echan->vchan);
+       struct edma_desc *edesc;
+       int i;
+
+       if (!vdesc) {
+               echan->edesc = NULL;
+               return;
+       }
+
+       list_del(&vdesc->node);
+
+       echan->edesc = edesc = to_edma_desc(&vdesc->tx);
+
+       /* Write descriptor PaRAM set(s) */
+       for (i = 0; i < edesc->pset_nr; i++) {
+               edma_write_slot(echan->slot[i], &edesc->pset[i]);
+               dev_dbg(echan->vchan.chan.device->dev,
+                       "\n pset[%d]:\n"
+                       "  chnum\t%d\n"
+                       "  slot\t%d\n"
+                       "  opt\t%08x\n"
+                       "  src\t%08x\n"
+                       "  dst\t%08x\n"
+                       "  abcnt\t%08x\n"
+                       "  ccnt\t%08x\n"
+                       "  bidx\t%08x\n"
+                       "  cidx\t%08x\n"
+                       "  lkrld\t%08x\n",
+                       i, echan->ch_num, echan->slot[i],
+                       edesc->pset[i].opt,
+                       edesc->pset[i].src,
+                       edesc->pset[i].dst,
+                       edesc->pset[i].a_b_cnt,
+                       edesc->pset[i].ccnt,
+                       edesc->pset[i].src_dst_bidx,
+                       edesc->pset[i].src_dst_cidx,
+                       edesc->pset[i].link_bcntrld);
+               /* Link to the previous slot if not the last set */
+               if (i != (edesc->pset_nr - 1))
+                       edma_link(echan->slot[i], echan->slot[i+1]);
+               /* Final pset links to the dummy pset */
+               else
+                       edma_link(echan->slot[i], echan->ecc->dummy_slot);
+       }
+
+       edma_start(echan->ch_num);
+}
+
+static int edma_terminate_all(struct edma_chan *echan)
+{
+       unsigned long flags;
+       LIST_HEAD(head);
+
+       spin_lock_irqsave(&echan->vchan.lock, flags);
+
+       /*
+        * Stop DMA activity: we assume the callback will not be called
+        * after edma_dma() returns (even if it does, it will see
+        * echan->edesc is NULL and exit.)
+        */
+       if (echan->edesc) {
+               echan->edesc = NULL;
+               edma_stop(echan->ch_num);
+       }
+
+       vchan_get_all_descriptors(&echan->vchan, &head);
+       spin_unlock_irqrestore(&echan->vchan.lock, flags);
+       vchan_dma_desc_free_list(&echan->vchan, &head);
+
+       return 0;
+}
+
+
+static int edma_slave_config(struct edma_chan *echan,
+       struct dma_slave_config *config)
+{
+       if ((config->src_addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES) ||
+           (config->dst_addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES))
+               return -EINVAL;
+
+       if (config->direction == DMA_MEM_TO_DEV) {
+               if (config->dst_addr)
+                       echan->addr = config->dst_addr;
+               if (config->dst_addr_width)
+                       echan->addr_width = config->dst_addr_width;
+               if (config->dst_maxburst)
+                       echan->maxburst = config->dst_maxburst;
+       } else if (config->direction == DMA_DEV_TO_MEM) {
+               if (config->src_addr)
+                       echan->addr = config->src_addr;
+               if (config->src_addr_width)
+                       echan->addr_width = config->src_addr_width;
+               if (config->src_maxburst)
+                       echan->maxburst = config->src_maxburst;
+       }
+
+       return 0;
+}
+
+static int edma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+                       unsigned long arg)
+{
+       int ret = 0;
+       struct dma_slave_config *config;
+       struct edma_chan *echan = to_edma_chan(chan);
+
+       switch (cmd) {
+       case DMA_TERMINATE_ALL:
+               edma_terminate_all(echan);
+               break;
+       case DMA_SLAVE_CONFIG:
+               config = (struct dma_slave_config *)arg;
+               ret = edma_slave_config(echan, config);
+               break;
+       default:
+               ret = -ENOSYS;
+       }
+
+       return ret;
+}
+
+static struct dma_async_tx_descriptor *edma_prep_slave_sg(
+       struct dma_chan *chan, struct scatterlist *sgl,
+       unsigned int sg_len, enum dma_transfer_direction direction,
+       unsigned long tx_flags, void *context)
+{
+       struct edma_chan *echan = to_edma_chan(chan);
+       struct device *dev = chan->device->dev;
+       struct edma_desc *edesc;
+       struct scatterlist *sg;
+       int i;
+       int acnt, bcnt, ccnt, src, dst, cidx;
+       int src_bidx, dst_bidx, src_cidx, dst_cidx;
+
+       if (unlikely(!echan || !sgl || !sg_len))
+               return NULL;
+
+       if (echan->addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) {
+               dev_err(dev, "Undefined slave buswidth\n");
+               return NULL;
+       }
+
+       if (sg_len > MAX_NR_SG) {
+               dev_err(dev, "Exceeded max SG segments %d > %d\n",
+                       sg_len, MAX_NR_SG);
+               return NULL;
+       }
+
+       edesc = kzalloc(sizeof(*edesc) + sg_len *
+               sizeof(edesc->pset[0]), GFP_ATOMIC);
+       if (!edesc) {
+               dev_dbg(dev, "Failed to allocate a descriptor\n");
+               return NULL;
+       }
+
+       edesc->pset_nr = sg_len;
+
+       for_each_sg(sgl, sg, sg_len, i) {
+               /* Allocate a PaRAM slot, if needed */
+               if (echan->slot[i] < 0) {
+                       echan->slot[i] =
+                               edma_alloc_slot(EDMA_CTLR(echan->ch_num),
+                                               EDMA_SLOT_ANY);
+                       if (echan->slot[i] < 0) {
+                               dev_err(dev, "Failed to allocate slot\n");
+                               return NULL;
+                       }
+               }
+
+               acnt = echan->addr_width;
+
+               /*
+                * If the maxburst is equal to the fifo width, use
+                * A-synced transfers. This allows for large contiguous
+                * buffer transfers using only one PaRAM set.
+                */
+               if (echan->maxburst == 1) {
+                       edesc->absync = false;
+                       ccnt = sg_dma_len(sg) / acnt / (SZ_64K - 1);
+                       bcnt = sg_dma_len(sg) / acnt - ccnt * (SZ_64K - 1);
+                       if (bcnt)
+                               ccnt++;
+                       else
+                               bcnt = SZ_64K - 1;
+                       cidx = acnt;
+               /*
+                * If maxburst is greater than the fifo address_width,
+                * use AB-synced transfers where A count is the fifo
+                * address_width and B count is the maxburst. In this
+                * case, we are limited to transfers of C count frames
+                * of (address_width * maxburst) where C count is limited
+                * to SZ_64K-1. This places an upper bound on the length
+                * of an SG segment that can be handled.
+                */
+               } else {
+                       edesc->absync = true;
+                       bcnt = echan->maxburst;
+                       ccnt = sg_dma_len(sg) / (acnt * bcnt);
+                       if (ccnt > (SZ_64K - 1)) {
+                               dev_err(dev, "Exceeded max SG segment size\n");
+                               return NULL;
+                       }
+                       cidx = acnt * bcnt;
+               }
+
+               if (direction == DMA_MEM_TO_DEV) {
+                       src = sg_dma_address(sg);
+                       dst = echan->addr;
+                       src_bidx = acnt;
+                       src_cidx = cidx;
+                       dst_bidx = 0;
+                       dst_cidx = 0;
+               } else {
+                       src = echan->addr;
+                       dst = sg_dma_address(sg);
+                       src_bidx = 0;
+                       src_cidx = 0;
+                       dst_bidx = acnt;
+                       dst_cidx = cidx;
+               }
+
+               edesc->pset[i].opt = EDMA_TCC(EDMA_CHAN_SLOT(echan->ch_num));
+               /* Configure A or AB synchronized transfers */
+               if (edesc->absync)
+                       edesc->pset[i].opt |= SYNCDIM;
+               /* If this is the last set, enable completion interrupt flag */
+               if (i == sg_len - 1)
+                       edesc->pset[i].opt |= TCINTEN;
+
+               edesc->pset[i].src = src;
+               edesc->pset[i].dst = dst;
+
+               edesc->pset[i].src_dst_bidx = (dst_bidx << 16) | src_bidx;
+               edesc->pset[i].src_dst_cidx = (dst_cidx << 16) | src_cidx;
+
+               edesc->pset[i].a_b_cnt = bcnt << 16 | acnt;
+               edesc->pset[i].ccnt = ccnt;
+               edesc->pset[i].link_bcntrld = 0xffffffff;
+
+       }
+
+       return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags);
+}
+
+static void edma_callback(unsigned ch_num, u16 ch_status, void *data)
+{
+       struct edma_chan *echan = data;
+       struct device *dev = echan->vchan.chan.device->dev;
+       struct edma_desc *edesc;
+       unsigned long flags;
+
+       /* Stop the channel */
+       edma_stop(echan->ch_num);
+
+       switch (ch_status) {
+       case DMA_COMPLETE:
+               dev_dbg(dev, "transfer complete on channel %d\n", ch_num);
+
+               spin_lock_irqsave(&echan->vchan.lock, flags);
+
+               edesc = echan->edesc;
+               if (edesc) {
+                       edma_execute(echan);
+                       vchan_cookie_complete(&edesc->vdesc);
+               }
+
+               spin_unlock_irqrestore(&echan->vchan.lock, flags);
+
+               break;
+       case DMA_CC_ERROR:
+               dev_dbg(dev, "transfer error on channel %d\n", ch_num);
+               break;
+       default:
+               break;
+       }
+}
+
+/* Alloc channel resources */
+static int edma_alloc_chan_resources(struct dma_chan *chan)
+{
+       struct edma_chan *echan = to_edma_chan(chan);
+       struct device *dev = chan->device->dev;
+       int ret;
+       int a_ch_num;
+       LIST_HEAD(descs);
+
+       a_ch_num = edma_alloc_channel(echan->ch_num, edma_callback,
+                                       chan, EVENTQ_DEFAULT);
+
+       if (a_ch_num < 0) {
+               ret = -ENODEV;
+               goto err_no_chan;
+       }
+
+       if (a_ch_num != echan->ch_num) {
+               dev_err(dev, "failed to allocate requested channel %u:%u\n",
+                       EDMA_CTLR(echan->ch_num),
+                       EDMA_CHAN_SLOT(echan->ch_num));
+               ret = -ENODEV;
+               goto err_wrong_chan;
+       }
+
+       echan->alloced = true;
+       echan->slot[0] = echan->ch_num;
+
+       dev_info(dev, "allocated channel for %u:%u\n",
+                EDMA_CTLR(echan->ch_num), EDMA_CHAN_SLOT(echan->ch_num));
+
+       return 0;
+
+err_wrong_chan:
+       edma_free_channel(a_ch_num);
+err_no_chan:
+       return ret;
+}
+
+/* Free channel resources */
+static void edma_free_chan_resources(struct dma_chan *chan)
+{
+       struct edma_chan *echan = to_edma_chan(chan);
+       struct device *dev = chan->device->dev;
+       int i;
+
+       /* Terminate transfers */
+       edma_stop(echan->ch_num);
+
+       vchan_free_chan_resources(&echan->vchan);
+
+       /* Free EDMA PaRAM slots */
+       for (i = 1; i < EDMA_MAX_SLOTS; i++) {
+               if (echan->slot[i] >= 0) {
+                       edma_free_slot(echan->slot[i]);
+                       echan->slot[i] = -1;
+               }
+       }
+
+       /* Free EDMA channel */
+       if (echan->alloced) {
+               edma_free_channel(echan->ch_num);
+               echan->alloced = false;
+       }
+
+       dev_info(dev, "freeing channel for %u\n", echan->ch_num);
+}
+
+/* Send pending descriptor to hardware */
+static void edma_issue_pending(struct dma_chan *chan)
+{
+       struct edma_chan *echan = to_edma_chan(chan);
+       unsigned long flags;
+
+       spin_lock_irqsave(&echan->vchan.lock, flags);
+       if (vchan_issue_pending(&echan->vchan) && !echan->edesc)
+               edma_execute(echan);
+       spin_unlock_irqrestore(&echan->vchan.lock, flags);
+}
+
+static size_t edma_desc_size(struct edma_desc *edesc)
+{
+       int i;
+       size_t size;
+
+       if (edesc->absync)
+               for (size = i = 0; i < edesc->pset_nr; i++)
+                       size += (edesc->pset[i].a_b_cnt & 0xffff) *
+                               (edesc->pset[i].a_b_cnt >> 16) *
+                                edesc->pset[i].ccnt;
+       else
+               size = (edesc->pset[0].a_b_cnt & 0xffff) *
+                       (edesc->pset[0].a_b_cnt >> 16) +
+                       (edesc->pset[0].a_b_cnt & 0xffff) *
+                       (SZ_64K - 1) * edesc->pset[0].ccnt;
+
+       return size;
+}
+
+/* Check request completion status */
+static enum dma_status edma_tx_status(struct dma_chan *chan,
+                                     dma_cookie_t cookie,
+                                     struct dma_tx_state *txstate)
+{
+       struct edma_chan *echan = to_edma_chan(chan);
+       struct virt_dma_desc *vdesc;
+       enum dma_status ret;
+       unsigned long flags;
+
+       ret = dma_cookie_status(chan, cookie, txstate);
+       if (ret == DMA_SUCCESS || !txstate)
+               return ret;
+
+       spin_lock_irqsave(&echan->vchan.lock, flags);
+       vdesc = vchan_find_desc(&echan->vchan, cookie);
+       if (vdesc) {
+               txstate->residue = edma_desc_size(to_edma_desc(&vdesc->tx));
+       } else if (echan->edesc && echan->edesc->vdesc.tx.cookie == cookie) {
+               struct edma_desc *edesc = echan->edesc;
+               txstate->residue = edma_desc_size(edesc);
+       } else {
+               txstate->residue = 0;
+       }
+       spin_unlock_irqrestore(&echan->vchan.lock, flags);
+
+       return ret;
+}
+
+static void __init edma_chan_init(struct edma_cc *ecc,
+                                 struct dma_device *dma,
+                                 struct edma_chan *echans)
+{
+       int i, j;
+
+       for (i = 0; i < EDMA_CHANS; i++) {
+               struct edma_chan *echan = &echans[i];
+               echan->ch_num = EDMA_CTLR_CHAN(ecc->ctlr, i);
+               echan->ecc = ecc;
+               echan->vchan.desc_free = edma_desc_free;
+
+               vchan_init(&echan->vchan, dma);
+
+               INIT_LIST_HEAD(&echan->node);
+               for (j = 0; j < EDMA_MAX_SLOTS; j++)
+                       echan->slot[j] = -1;
+       }
+}
+
+static void edma_dma_init(struct edma_cc *ecc, struct dma_device *dma,
+                         struct device *dev)
+{
+       dma->device_prep_slave_sg = edma_prep_slave_sg;
+       dma->device_alloc_chan_resources = edma_alloc_chan_resources;
+       dma->device_free_chan_resources = edma_free_chan_resources;
+       dma->device_issue_pending = edma_issue_pending;
+       dma->device_tx_status = edma_tx_status;
+       dma->device_control = edma_control;
+       dma->dev = dev;
+
+       INIT_LIST_HEAD(&dma->channels);
+}
+
+static int __devinit edma_probe(struct platform_device *pdev)
+{
+       struct edma_cc *ecc;
+       int ret;
+
+       ecc = devm_kzalloc(&pdev->dev, sizeof(*ecc), GFP_KERNEL);
+       if (!ecc) {
+               dev_err(&pdev->dev, "Can't allocate controller\n");
+               return -ENOMEM;
+       }
+
+       ecc->ctlr = pdev->id;
+       ecc->dummy_slot = edma_alloc_slot(ecc->ctlr, EDMA_SLOT_ANY);
+       if (ecc->dummy_slot < 0) {
+               dev_err(&pdev->dev, "Can't allocate PaRAM dummy slot\n");
+               return -EIO;
+       }
+
+       dma_cap_zero(ecc->dma_slave.cap_mask);
+       dma_cap_set(DMA_SLAVE, ecc->dma_slave.cap_mask);
+
+       edma_dma_init(ecc, &ecc->dma_slave, &pdev->dev);
+
+       edma_chan_init(ecc, &ecc->dma_slave, ecc->slave_chans);
+
+       ret = dma_async_device_register(&ecc->dma_slave);
+       if (ret)
+               goto err_reg1;
+
+       platform_set_drvdata(pdev, ecc);
+
+       dev_info(&pdev->dev, "TI EDMA DMA engine driver\n");
+
+       return 0;
+
+err_reg1:
+       edma_free_slot(ecc->dummy_slot);
+       return ret;
+}
+
+static int __devexit edma_remove(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct edma_cc *ecc = dev_get_drvdata(dev);
+
+       dma_async_device_unregister(&ecc->dma_slave);
+       edma_free_slot(ecc->dummy_slot);
+
+       return 0;
+}
+
+static struct platform_driver edma_driver = {
+       .probe          = edma_probe,
+       .remove         = __devexit_p(edma_remove),
+       .driver = {
+               .name = "edma-dma-engine",
+               .owner = THIS_MODULE,
+       },
+};
+
+bool edma_filter_fn(struct dma_chan *chan, void *param)
+{
+       if (chan->device->dev->driver == &edma_driver.driver) {
+               struct edma_chan *echan = to_edma_chan(chan);
+               unsigned ch_req = *(unsigned *)param;
+               return ch_req == echan->ch_num;
+       }
+       return false;
+}
+EXPORT_SYMBOL(edma_filter_fn);
+
+static struct platform_device *pdev0, *pdev1;
+
+static const struct platform_device_info edma_dev_info0 = {
+       .name = "edma-dma-engine",
+       .id = 0,
+       .dma_mask = DMA_BIT_MASK(32),
+};
+
+static const struct platform_device_info edma_dev_info1 = {
+       .name = "edma-dma-engine",
+       .id = 1,
+       .dma_mask = DMA_BIT_MASK(32),
+};
+
+static int edma_init(void)
+{
+       int ret = platform_driver_register(&edma_driver);
+
+       if (ret == 0) {
+               pdev0 = platform_device_register_full(&edma_dev_info0);
+               if (IS_ERR(pdev0)) {
+                       platform_driver_unregister(&edma_driver);
+                       ret = PTR_ERR(pdev0);
+                       goto out;
+               }
+       }
+
+       if (EDMA_CTLRS == 2) {
+               pdev1 = platform_device_register_full(&edma_dev_info1);
+               if (IS_ERR(pdev1)) {
+                       platform_driver_unregister(&edma_driver);
+                       platform_device_unregister(pdev0);
+                       ret = PTR_ERR(pdev1);
+               }
+       }
+
+out:
+       return ret;
+}
+subsys_initcall(edma_init);
+
+static void __exit edma_exit(void)
+{
+       platform_device_unregister(pdev0);
+       if (pdev1)
+               platform_device_unregister(pdev1);
+       platform_driver_unregister(&edma_driver);
+}
+module_exit(edma_exit);
+
+MODULE_AUTHOR("Matt Porter <mporter@ti.com>");
+MODULE_DESCRIPTION("TI EDMA DMA engine driver");
+MODULE_LICENSE("GPL v2");
index 86895760b598ef61ca63ebce58f3c1f2e5093cbf..b9d66785144511ff294cb59096d6de1b766cbece 100644 (file)
@@ -434,12 +434,11 @@ static struct ioat_ring_ent *ioat2_alloc_ring_ent(struct dma_chan *chan, gfp_t f
                return NULL;
        memset(hw, 0, sizeof(*hw));
 
-       desc = kmem_cache_alloc(ioat2_cache, flags);
+       desc = kmem_cache_zalloc(ioat2_cache, flags);
        if (!desc) {
                pci_pool_free(dma->dma_pool, hw, phys);
                return NULL;
        }
-       memset(desc, 0, sizeof(*desc));
 
        dma_async_tx_descriptor_init(&desc->txd, chan);
        desc->txd.tx_submit = ioat2_tx_submit_unlock;
index 5e3a40f7994510d6b084815459e77f4690da8970..c0573061b45dfc5f45c40255d4a6d9c99a1fe882 100644 (file)
@@ -40,6 +40,17 @@ MODULE_VERSION(IOAT_DMA_VERSION);
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Intel Corporation");
 
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB0  0x0e20
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB1  0x0e21
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB2  0x0e22
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB3  0x0e23
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB4  0x0e24
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB5  0x0e25
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB6  0x0e26
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB7  0x0e27
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB8  0x0e2e
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB9  0x0e2f
+
 static struct pci_device_id ioat_pci_tbl[] = {
        /* I/OAT v1 platforms */
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT) },
@@ -83,6 +94,17 @@ static struct pci_device_id ioat_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB8) },
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB9) },
 
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB0) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB1) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB2) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB3) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB4) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB5) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB6) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB7) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB8) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB9) },
+
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, ioat_pci_tbl);
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
new file mode 100644 (file)
index 0000000..14da1f4
--- /dev/null
@@ -0,0 +1,875 @@
+/*
+ * Copyright 2012 Marvell International Ltd.
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/dmaengine.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/platform_data/mmp_dma.h>
+#include <linux/dmapool.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+
+#include "dmaengine.h"
+
+#define DCSR           0x0000
+#define DALGN          0x00a0
+#define DINT           0x00f0
+#define DDADR          0x0200
+#define DSADR          0x0204
+#define DTADR          0x0208
+#define DCMD           0x020c
+
+#define DCSR_RUN       (1 << 31)       /* Run Bit (read / write) */
+#define DCSR_NODESC    (1 << 30)       /* No-Descriptor Fetch (read / write) */
+#define DCSR_STOPIRQEN (1 << 29)       /* Stop Interrupt Enable (read / write) */
+#define DCSR_REQPEND   (1 << 8)        /* Request Pending (read-only) */
+#define DCSR_STOPSTATE (1 << 3)        /* Stop State (read-only) */
+#define DCSR_ENDINTR   (1 << 2)        /* End Interrupt (read / write) */
+#define DCSR_STARTINTR (1 << 1)        /* Start Interrupt (read / write) */
+#define DCSR_BUSERR    (1 << 0)        /* Bus Error Interrupt (read / write) */
+
+#define DCSR_EORIRQEN  (1 << 28)       /* End of Receive Interrupt Enable (R/W) */
+#define DCSR_EORJMPEN  (1 << 27)       /* Jump to next descriptor on EOR */
+#define DCSR_EORSTOPEN (1 << 26)       /* STOP on an EOR */
+#define DCSR_SETCMPST  (1 << 25)       /* Set Descriptor Compare Status */
+#define DCSR_CLRCMPST  (1 << 24)       /* Clear Descriptor Compare Status */
+#define DCSR_CMPST     (1 << 10)       /* The Descriptor Compare Status */
+#define DCSR_EORINTR   (1 << 9)        /* The end of Receive */
+
+#define DRCMR_MAPVLD   (1 << 7)        /* Map Valid (read / write) */
+#define DRCMR_CHLNUM   0x1f            /* mask for Channel Number (read / write) */
+
+#define DDADR_DESCADDR 0xfffffff0      /* Address of next descriptor (mask) */
+#define DDADR_STOP     (1 << 0)        /* Stop (read / write) */
+
+#define DCMD_INCSRCADDR        (1 << 31)       /* Source Address Increment Setting. */
+#define DCMD_INCTRGADDR        (1 << 30)       /* Target Address Increment Setting. */
+#define DCMD_FLOWSRC   (1 << 29)       /* Flow Control by the source. */
+#define DCMD_FLOWTRG   (1 << 28)       /* Flow Control by the target. */
+#define DCMD_STARTIRQEN        (1 << 22)       /* Start Interrupt Enable */
+#define DCMD_ENDIRQEN  (1 << 21)       /* End Interrupt Enable */
+#define DCMD_ENDIAN    (1 << 18)       /* Device Endian-ness. */
+#define DCMD_BURST8    (1 << 16)       /* 8 byte burst */
+#define DCMD_BURST16   (2 << 16)       /* 16 byte burst */
+#define DCMD_BURST32   (3 << 16)       /* 32 byte burst */
+#define DCMD_WIDTH1    (1 << 14)       /* 1 byte width */
+#define DCMD_WIDTH2    (2 << 14)       /* 2 byte width (HalfWord) */
+#define DCMD_WIDTH4    (3 << 14)       /* 4 byte width (Word) */
+#define DCMD_LENGTH    0x01fff         /* length mask (max = 8K - 1) */
+
+#define PDMA_ALIGNMENT         3
+#define PDMA_MAX_DESC_BYTES    0x1000
+
+struct mmp_pdma_desc_hw {
+       u32 ddadr;      /* Points to the next descriptor + flags */
+       u32 dsadr;      /* DSADR value for the current transfer */
+       u32 dtadr;      /* DTADR value for the current transfer */
+       u32 dcmd;       /* DCMD value for the current transfer */
+} __aligned(32);
+
+struct mmp_pdma_desc_sw {
+       struct mmp_pdma_desc_hw desc;
+       struct list_head node;
+       struct list_head tx_list;
+       struct dma_async_tx_descriptor async_tx;
+};
+
+struct mmp_pdma_phy;
+
+struct mmp_pdma_chan {
+       struct device *dev;
+       struct dma_chan chan;
+       struct dma_async_tx_descriptor desc;
+       struct mmp_pdma_phy *phy;
+       enum dma_transfer_direction dir;
+
+       /* channel's basic info */
+       struct tasklet_struct tasklet;
+       u32 dcmd;
+       u32 drcmr;
+       u32 dev_addr;
+
+       /* list for desc */
+       spinlock_t desc_lock;           /* Descriptor list lock */
+       struct list_head chain_pending; /* Link descriptors queue for pending */
+       struct list_head chain_running; /* Link descriptors queue for running */
+       bool idle;                      /* channel statue machine */
+
+       struct dma_pool *desc_pool;     /* Descriptors pool */
+};
+
+struct mmp_pdma_phy {
+       int idx;
+       void __iomem *base;
+       struct mmp_pdma_chan *vchan;
+};
+
+struct mmp_pdma_device {
+       int                             dma_channels;
+       void __iomem                    *base;
+       struct device                   *dev;
+       struct dma_device               device;
+       struct mmp_pdma_phy             *phy;
+};
+
+#define tx_to_mmp_pdma_desc(tx) container_of(tx, struct mmp_pdma_desc_sw, async_tx)
+#define to_mmp_pdma_desc(lh) container_of(lh, struct mmp_pdma_desc_sw, node)
+#define to_mmp_pdma_chan(dchan) container_of(dchan, struct mmp_pdma_chan, chan)
+#define to_mmp_pdma_dev(dmadev) container_of(dmadev, struct mmp_pdma_device, device)
+
+static void set_desc(struct mmp_pdma_phy *phy, dma_addr_t addr)
+{
+       u32 reg = (phy->idx << 4) + DDADR;
+
+       writel(addr, phy->base + reg);
+}
+
+static void enable_chan(struct mmp_pdma_phy *phy)
+{
+       u32 reg;
+
+       if (!phy->vchan)
+               return;
+
+       reg = phy->vchan->drcmr;
+       reg = (((reg) < 64) ? 0x0100 : 0x1100) + (((reg) & 0x3f) << 2);
+       writel(DRCMR_MAPVLD | phy->idx, phy->base + reg);
+
+       reg = (phy->idx << 2) + DCSR;
+       writel(readl(phy->base + reg) | DCSR_RUN,
+                                       phy->base + reg);
+}
+
+static void disable_chan(struct mmp_pdma_phy *phy)
+{
+       u32 reg;
+
+       if (phy) {
+               reg = (phy->idx << 2) + DCSR;
+               writel(readl(phy->base + reg) & ~DCSR_RUN,
+                                               phy->base + reg);
+       }
+}
+
+static int clear_chan_irq(struct mmp_pdma_phy *phy)
+{
+       u32 dcsr;
+       u32 dint = readl(phy->base + DINT);
+       u32 reg = (phy->idx << 2) + DCSR;
+
+       if (dint & BIT(phy->idx)) {
+               /* clear irq */
+               dcsr = readl(phy->base + reg);
+               writel(dcsr, phy->base + reg);
+               if ((dcsr & DCSR_BUSERR) && (phy->vchan))
+                       dev_warn(phy->vchan->dev, "DCSR_BUSERR\n");
+               return 0;
+       }
+       return -EAGAIN;
+}
+
+static irqreturn_t mmp_pdma_chan_handler(int irq, void *dev_id)
+{
+       struct mmp_pdma_phy *phy = dev_id;
+
+       if (clear_chan_irq(phy) == 0) {
+               tasklet_schedule(&phy->vchan->tasklet);
+               return IRQ_HANDLED;
+       } else
+               return IRQ_NONE;
+}
+
+static irqreturn_t mmp_pdma_int_handler(int irq, void *dev_id)
+{
+       struct mmp_pdma_device *pdev = dev_id;
+       struct mmp_pdma_phy *phy;
+       u32 dint = readl(pdev->base + DINT);
+       int i, ret;
+       int irq_num = 0;
+
+       while (dint) {
+               i = __ffs(dint);
+               dint &= (dint - 1);
+               phy = &pdev->phy[i];
+               ret = mmp_pdma_chan_handler(irq, phy);
+               if (ret == IRQ_HANDLED)
+                       irq_num++;
+       }
+
+       if (irq_num)
+               return IRQ_HANDLED;
+       else
+               return IRQ_NONE;
+}
+
+/* lookup free phy channel as descending priority */
+static struct mmp_pdma_phy *lookup_phy(struct mmp_pdma_chan *pchan)
+{
+       int prio, i;
+       struct mmp_pdma_device *pdev = to_mmp_pdma_dev(pchan->chan.device);
+       struct mmp_pdma_phy *phy;
+
+       /*
+        * dma channel priorities
+        * ch 0 - 3,  16 - 19  <--> (0)
+        * ch 4 - 7,  20 - 23  <--> (1)
+        * ch 8 - 11, 24 - 27  <--> (2)
+        * ch 12 - 15, 28 - 31  <--> (3)
+        */
+       for (prio = 0; prio <= (((pdev->dma_channels - 1) & 0xf) >> 2); prio++) {
+               for (i = 0; i < pdev->dma_channels; i++) {
+                       if (prio != ((i & 0xf) >> 2))
+                               continue;
+                       phy = &pdev->phy[i];
+                       if (!phy->vchan) {
+                               phy->vchan = pchan;
+                               return phy;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+/* desc->tx_list ==> pending list */
+static void append_pending_queue(struct mmp_pdma_chan *chan,
+                                       struct mmp_pdma_desc_sw *desc)
+{
+       struct mmp_pdma_desc_sw *tail =
+                               to_mmp_pdma_desc(chan->chain_pending.prev);
+
+       if (list_empty(&chan->chain_pending))
+               goto out_splice;
+
+       /* one irq per queue, even appended */
+       tail->desc.ddadr = desc->async_tx.phys;
+       tail->desc.dcmd &= ~DCMD_ENDIRQEN;
+
+       /* softly link to pending list */
+out_splice:
+       list_splice_tail_init(&desc->tx_list, &chan->chain_pending);
+}
+
+/**
+ * start_pending_queue - transfer any pending transactions
+ * pending list ==> running list
+ */
+static void start_pending_queue(struct mmp_pdma_chan *chan)
+{
+       struct mmp_pdma_desc_sw *desc;
+
+       /* still in running, irq will start the pending list */
+       if (!chan->idle) {
+               dev_dbg(chan->dev, "DMA controller still busy\n");
+               return;
+       }
+
+       if (list_empty(&chan->chain_pending)) {
+               /* chance to re-fetch phy channel with higher prio */
+               if (chan->phy) {
+                       chan->phy->vchan = NULL;
+                       chan->phy = NULL;
+               }
+               dev_dbg(chan->dev, "no pending list\n");
+               return;
+       }
+
+       if (!chan->phy) {
+               chan->phy = lookup_phy(chan);
+               if (!chan->phy) {
+                       dev_dbg(chan->dev, "no free dma channel\n");
+                       return;
+               }
+       }
+
+       /*
+        * pending -> running
+        * reintilize pending list
+        */
+       desc = list_first_entry(&chan->chain_pending,
+                               struct mmp_pdma_desc_sw, node);
+       list_splice_tail_init(&chan->chain_pending, &chan->chain_running);
+
+       /*
+        * Program the descriptor's address into the DMA controller,
+        * then start the DMA transaction
+        */
+       set_desc(chan->phy, desc->async_tx.phys);
+       enable_chan(chan->phy);
+       chan->idle = false;
+}
+
+
+/* desc->tx_list ==> pending list */
+static dma_cookie_t mmp_pdma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+       struct mmp_pdma_chan *chan = to_mmp_pdma_chan(tx->chan);
+       struct mmp_pdma_desc_sw *desc = tx_to_mmp_pdma_desc(tx);
+       struct mmp_pdma_desc_sw *child;
+       unsigned long flags;
+       dma_cookie_t cookie = -EBUSY;
+
+       spin_lock_irqsave(&chan->desc_lock, flags);
+
+       list_for_each_entry(child, &desc->tx_list, node) {
+               cookie = dma_cookie_assign(&child->async_tx);
+       }
+
+       append_pending_queue(chan, desc);
+
+       spin_unlock_irqrestore(&chan->desc_lock, flags);
+
+       return cookie;
+}
+
+struct mmp_pdma_desc_sw *mmp_pdma_alloc_descriptor(struct mmp_pdma_chan *chan)
+{
+       struct mmp_pdma_desc_sw *desc;
+       dma_addr_t pdesc;
+
+       desc = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc);
+       if (!desc) {
+               dev_err(chan->dev, "out of memory for link descriptor\n");
+               return NULL;
+       }
+
+       memset(desc, 0, sizeof(*desc));
+       INIT_LIST_HEAD(&desc->tx_list);
+       dma_async_tx_descriptor_init(&desc->async_tx, &chan->chan);
+       /* each desc has submit */
+       desc->async_tx.tx_submit = mmp_pdma_tx_submit;
+       desc->async_tx.phys = pdesc;
+
+       return desc;
+}
+
+/**
+ * mmp_pdma_alloc_chan_resources - Allocate resources for DMA channel.
+ *
+ * This function will create a dma pool for descriptor allocation.
+ * Request irq only when channel is requested
+ * Return - The number of allocated descriptors.
+ */
+
+static int mmp_pdma_alloc_chan_resources(struct dma_chan *dchan)
+{
+       struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan);
+
+       if (chan->desc_pool)
+               return 1;
+
+       chan->desc_pool =
+               dma_pool_create(dev_name(&dchan->dev->device), chan->dev,
+                                 sizeof(struct mmp_pdma_desc_sw),
+                                 __alignof__(struct mmp_pdma_desc_sw), 0);
+       if (!chan->desc_pool) {
+               dev_err(chan->dev, "unable to allocate descriptor pool\n");
+               return -ENOMEM;
+       }
+       if (chan->phy) {
+               chan->phy->vchan = NULL;
+               chan->phy = NULL;
+       }
+       chan->idle = true;
+       chan->dev_addr = 0;
+       return 1;
+}
+
+static void mmp_pdma_free_desc_list(struct mmp_pdma_chan *chan,
+                                 struct list_head *list)
+{
+       struct mmp_pdma_desc_sw *desc, *_desc;
+
+       list_for_each_entry_safe(desc, _desc, list, node) {
+               list_del(&desc->node);
+               dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+       }
+}
+
+static void mmp_pdma_free_chan_resources(struct dma_chan *dchan)
+{
+       struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan);
+       unsigned long flags;
+
+       spin_lock_irqsave(&chan->desc_lock, flags);
+       mmp_pdma_free_desc_list(chan, &chan->chain_pending);
+       mmp_pdma_free_desc_list(chan, &chan->chain_running);
+       spin_unlock_irqrestore(&chan->desc_lock, flags);
+
+       dma_pool_destroy(chan->desc_pool);
+       chan->desc_pool = NULL;
+       chan->idle = true;
+       chan->dev_addr = 0;
+       if (chan->phy) {
+               chan->phy->vchan = NULL;
+               chan->phy = NULL;
+       }
+       return;
+}
+
+static struct dma_async_tx_descriptor *
+mmp_pdma_prep_memcpy(struct dma_chan *dchan,
+       dma_addr_t dma_dst, dma_addr_t dma_src,
+       size_t len, unsigned long flags)
+{
+       struct mmp_pdma_chan *chan;
+       struct mmp_pdma_desc_sw *first = NULL, *prev = NULL, *new;
+       size_t copy = 0;
+
+       if (!dchan)
+               return NULL;
+
+       if (!len)
+               return NULL;
+
+       chan = to_mmp_pdma_chan(dchan);
+
+       if (!chan->dir) {
+               chan->dir = DMA_MEM_TO_MEM;
+               chan->dcmd = DCMD_INCTRGADDR | DCMD_INCSRCADDR;
+               chan->dcmd |= DCMD_BURST32;
+       }
+
+       do {
+               /* Allocate the link descriptor from DMA pool */
+               new = mmp_pdma_alloc_descriptor(chan);
+               if (!new) {
+                       dev_err(chan->dev, "no memory for desc\n");
+                       goto fail;
+               }
+
+               copy = min_t(size_t, len, PDMA_MAX_DESC_BYTES);
+
+               new->desc.dcmd = chan->dcmd | (DCMD_LENGTH & copy);
+               new->desc.dsadr = dma_src;
+               new->desc.dtadr = dma_dst;
+
+               if (!first)
+                       first = new;
+               else
+                       prev->desc.ddadr = new->async_tx.phys;
+
+               new->async_tx.cookie = 0;
+               async_tx_ack(&new->async_tx);
+
+               prev = new;
+               len -= copy;
+
+               if (chan->dir == DMA_MEM_TO_DEV) {
+                       dma_src += copy;
+               } else if (chan->dir == DMA_DEV_TO_MEM) {
+                       dma_dst += copy;
+               } else if (chan->dir == DMA_MEM_TO_MEM) {
+                       dma_src += copy;
+                       dma_dst += copy;
+               }
+
+               /* Insert the link descriptor to the LD ring */
+               list_add_tail(&new->node, &first->tx_list);
+       } while (len);
+
+       first->async_tx.flags = flags; /* client is in control of this ack */
+       first->async_tx.cookie = -EBUSY;
+
+       /* last desc and fire IRQ */
+       new->desc.ddadr = DDADR_STOP;
+       new->desc.dcmd |= DCMD_ENDIRQEN;
+
+       return &first->async_tx;
+
+fail:
+       if (first)
+               mmp_pdma_free_desc_list(chan, &first->tx_list);
+       return NULL;
+}
+
+static struct dma_async_tx_descriptor *
+mmp_pdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
+                        unsigned int sg_len, enum dma_transfer_direction dir,
+                        unsigned long flags, void *context)
+{
+       struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan);
+       struct mmp_pdma_desc_sw *first = NULL, *prev = NULL, *new = NULL;
+       size_t len, avail;
+       struct scatterlist *sg;
+       dma_addr_t addr;
+       int i;
+
+       if ((sgl == NULL) || (sg_len == 0))
+               return NULL;
+
+       for_each_sg(sgl, sg, sg_len, i) {
+               addr = sg_dma_address(sg);
+               avail = sg_dma_len(sgl);
+
+               do {
+                       len = min_t(size_t, avail, PDMA_MAX_DESC_BYTES);
+
+                       /* allocate and populate the descriptor */
+                       new = mmp_pdma_alloc_descriptor(chan);
+                       if (!new) {
+                               dev_err(chan->dev, "no memory for desc\n");
+                               goto fail;
+                       }
+
+                       new->desc.dcmd = chan->dcmd | (DCMD_LENGTH & len);
+                       if (dir == DMA_MEM_TO_DEV) {
+                               new->desc.dsadr = addr;
+                               new->desc.dtadr = chan->dev_addr;
+                       } else {
+                               new->desc.dsadr = chan->dev_addr;
+                               new->desc.dtadr = addr;
+                       }
+
+                       if (!first)
+                               first = new;
+                       else
+                               prev->desc.ddadr = new->async_tx.phys;
+
+                       new->async_tx.cookie = 0;
+                       async_tx_ack(&new->async_tx);
+                       prev = new;
+
+                       /* Insert the link descriptor to the LD ring */
+                       list_add_tail(&new->node, &first->tx_list);
+
+                       /* update metadata */
+                       addr += len;
+                       avail -= len;
+               } while (avail);
+       }
+
+       first->async_tx.cookie = -EBUSY;
+       first->async_tx.flags = flags;
+
+       /* last desc and fire IRQ */
+       new->desc.ddadr = DDADR_STOP;
+       new->desc.dcmd |= DCMD_ENDIRQEN;
+
+       return &first->async_tx;
+
+fail:
+       if (first)
+               mmp_pdma_free_desc_list(chan, &first->tx_list);
+       return NULL;
+}
+
+static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
+               unsigned long arg)
+{
+       struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan);
+       struct dma_slave_config *cfg = (void *)arg;
+       unsigned long flags;
+       int ret = 0;
+       u32 maxburst = 0, addr = 0;
+       enum dma_slave_buswidth width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
+
+       if (!dchan)
+               return -EINVAL;
+
+       switch (cmd) {
+       case DMA_TERMINATE_ALL:
+               disable_chan(chan->phy);
+               if (chan->phy) {
+                       chan->phy->vchan = NULL;
+                       chan->phy = NULL;
+               }
+               spin_lock_irqsave(&chan->desc_lock, flags);
+               mmp_pdma_free_desc_list(chan, &chan->chain_pending);
+               mmp_pdma_free_desc_list(chan, &chan->chain_running);
+               spin_unlock_irqrestore(&chan->desc_lock, flags);
+               chan->idle = true;
+               break;
+       case DMA_SLAVE_CONFIG:
+               if (cfg->direction == DMA_DEV_TO_MEM) {
+                       chan->dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC;
+                       maxburst = cfg->src_maxburst;
+                       width = cfg->src_addr_width;
+                       addr = cfg->src_addr;
+               } else if (cfg->direction == DMA_MEM_TO_DEV) {
+                       chan->dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG;
+                       maxburst = cfg->dst_maxburst;
+                       width = cfg->dst_addr_width;
+                       addr = cfg->dst_addr;
+               }
+
+               if (width == DMA_SLAVE_BUSWIDTH_1_BYTE)
+                       chan->dcmd |= DCMD_WIDTH1;
+               else if (width == DMA_SLAVE_BUSWIDTH_2_BYTES)
+                       chan->dcmd |= DCMD_WIDTH2;
+               else if (width == DMA_SLAVE_BUSWIDTH_4_BYTES)
+                       chan->dcmd |= DCMD_WIDTH4;
+
+               if (maxburst == 8)
+                       chan->dcmd |= DCMD_BURST8;
+               else if (maxburst == 16)
+                       chan->dcmd |= DCMD_BURST16;
+               else if (maxburst == 32)
+                       chan->dcmd |= DCMD_BURST32;
+
+               if (cfg) {
+                       chan->dir = cfg->direction;
+                       chan->drcmr = cfg->slave_id;
+               }
+               chan->dev_addr = addr;
+               break;
+       default:
+               return -ENOSYS;
+       }
+
+       return ret;
+}
+
+static enum dma_status mmp_pdma_tx_status(struct dma_chan *dchan,
+                       dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+       struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan);
+       enum dma_status ret;
+       unsigned long flags;
+
+       spin_lock_irqsave(&chan->desc_lock, flags);
+       ret = dma_cookie_status(dchan, cookie, txstate);
+       spin_unlock_irqrestore(&chan->desc_lock, flags);
+
+       return ret;
+}
+
+/**
+ * mmp_pdma_issue_pending - Issue the DMA start command
+ * pending list ==> running list
+ */
+static void mmp_pdma_issue_pending(struct dma_chan *dchan)
+{
+       struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan);
+       unsigned long flags;
+
+       spin_lock_irqsave(&chan->desc_lock, flags);
+       start_pending_queue(chan);
+       spin_unlock_irqrestore(&chan->desc_lock, flags);
+}
+
+/*
+ * dma_do_tasklet
+ * Do call back
+ * Start pending list
+ */
+static void dma_do_tasklet(unsigned long data)
+{
+       struct mmp_pdma_chan *chan = (struct mmp_pdma_chan *)data;
+       struct mmp_pdma_desc_sw *desc, *_desc;
+       LIST_HEAD(chain_cleanup);
+       unsigned long flags;
+
+       /* submit pending list; callback for each desc; free desc */
+
+       spin_lock_irqsave(&chan->desc_lock, flags);
+
+       /* update the cookie if we have some descriptors to cleanup */
+       if (!list_empty(&chan->chain_running)) {
+               dma_cookie_t cookie;
+
+               desc = to_mmp_pdma_desc(chan->chain_running.prev);
+               cookie = desc->async_tx.cookie;
+               dma_cookie_complete(&desc->async_tx);
+
+               dev_dbg(chan->dev, "completed_cookie=%d\n", cookie);
+       }
+
+       /*
+        * move the descriptors to a temporary list so we can drop the lock
+        * during the entire cleanup operation
+        */
+       list_splice_tail_init(&chan->chain_running, &chain_cleanup);
+
+       /* the hardware is now idle and ready for more */
+       chan->idle = true;
+
+       /* Start any pending transactions automatically */
+       start_pending_queue(chan);
+       spin_unlock_irqrestore(&chan->desc_lock, flags);
+
+       /* Run the callback for each descriptor, in order */
+       list_for_each_entry_safe(desc, _desc, &chain_cleanup, node) {
+               struct dma_async_tx_descriptor *txd = &desc->async_tx;
+
+               /* Remove from the list of transactions */
+               list_del(&desc->node);
+               /* Run the link descriptor callback function */
+               if (txd->callback)
+                       txd->callback(txd->callback_param);
+
+               dma_pool_free(chan->desc_pool, desc, txd->phys);
+       }
+}
+
+static int __devexit mmp_pdma_remove(struct platform_device *op)
+{
+       struct mmp_pdma_device *pdev = platform_get_drvdata(op);
+
+       dma_async_device_unregister(&pdev->device);
+       return 0;
+}
+
+static int __devinit mmp_pdma_chan_init(struct mmp_pdma_device *pdev,
+                                                       int idx, int irq)
+{
+       struct mmp_pdma_phy *phy  = &pdev->phy[idx];
+       struct mmp_pdma_chan *chan;
+       int ret;
+
+       chan = devm_kzalloc(pdev->dev,
+                       sizeof(struct mmp_pdma_chan), GFP_KERNEL);
+       if (chan == NULL)
+               return -ENOMEM;
+
+       phy->idx = idx;
+       phy->base = pdev->base;
+
+       if (irq) {
+               ret = devm_request_irq(pdev->dev, irq,
+                       mmp_pdma_chan_handler, IRQF_DISABLED, "pdma", phy);
+               if (ret) {
+                       dev_err(pdev->dev, "channel request irq fail!\n");
+                       return ret;
+               }
+       }
+
+       spin_lock_init(&chan->desc_lock);
+       chan->dev = pdev->dev;
+       chan->chan.device = &pdev->device;
+       tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan);
+       INIT_LIST_HEAD(&chan->chain_pending);
+       INIT_LIST_HEAD(&chan->chain_running);
+
+       /* register virt channel to dma engine */
+       list_add_tail(&chan->chan.device_node,
+                       &pdev->device.channels);
+
+       return 0;
+}
+
+static struct of_device_id mmp_pdma_dt_ids[] = {
+       { .compatible = "marvell,pdma-1.0", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, mmp_pdma_dt_ids);
+
+static int __devinit mmp_pdma_probe(struct platform_device *op)
+{
+       struct mmp_pdma_device *pdev;
+       const struct of_device_id *of_id;
+       struct mmp_dma_platdata *pdata = dev_get_platdata(&op->dev);
+       struct resource *iores;
+       int i, ret, irq = 0;
+       int dma_channels = 0, irq_num = 0;
+
+       pdev = devm_kzalloc(&op->dev, sizeof(*pdev), GFP_KERNEL);
+       if (!pdev)
+               return -ENOMEM;
+       pdev->dev = &op->dev;
+
+       iores = platform_get_resource(op, IORESOURCE_MEM, 0);
+       if (!iores)
+               return -EINVAL;
+
+       pdev->base = devm_request_and_ioremap(pdev->dev, iores);
+       if (!pdev->base)
+               return -EADDRNOTAVAIL;
+
+       of_id = of_match_device(mmp_pdma_dt_ids, pdev->dev);
+       if (of_id)
+               of_property_read_u32(pdev->dev->of_node,
+                               "#dma-channels", &dma_channels);
+       else if (pdata && pdata->dma_channels)
+               dma_channels = pdata->dma_channels;
+       else
+               dma_channels = 32;      /* default 32 channel */
+       pdev->dma_channels = dma_channels;
+
+       for (i = 0; i < dma_channels; i++) {
+               if (platform_get_irq(op, i) > 0)
+                       irq_num++;
+       }
+
+       pdev->phy = devm_kzalloc(pdev->dev,
+               dma_channels * sizeof(struct mmp_pdma_chan), GFP_KERNEL);
+       if (pdev->phy == NULL)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&pdev->device.channels);
+
+       if (irq_num != dma_channels) {
+               /* all chan share one irq, demux inside */
+               irq = platform_get_irq(op, 0);
+               ret = devm_request_irq(pdev->dev, irq,
+                       mmp_pdma_int_handler, IRQF_DISABLED, "pdma", pdev);
+               if (ret)
+                       return ret;
+       }
+
+       for (i = 0; i < dma_channels; i++) {
+               irq = (irq_num != dma_channels) ? 0 : platform_get_irq(op, i);
+               ret = mmp_pdma_chan_init(pdev, i, irq);
+               if (ret)
+                       return ret;
+       }
+
+       dma_cap_set(DMA_SLAVE, pdev->device.cap_mask);
+       dma_cap_set(DMA_MEMCPY, pdev->device.cap_mask);
+       dma_cap_set(DMA_SLAVE, pdev->device.cap_mask);
+       pdev->device.dev = &op->dev;
+       pdev->device.device_alloc_chan_resources = mmp_pdma_alloc_chan_resources;
+       pdev->device.device_free_chan_resources = mmp_pdma_free_chan_resources;
+       pdev->device.device_tx_status = mmp_pdma_tx_status;
+       pdev->device.device_prep_dma_memcpy = mmp_pdma_prep_memcpy;
+       pdev->device.device_prep_slave_sg = mmp_pdma_prep_slave_sg;
+       pdev->device.device_issue_pending = mmp_pdma_issue_pending;
+       pdev->device.device_control = mmp_pdma_control;
+       pdev->device.copy_align = PDMA_ALIGNMENT;
+
+       if (pdev->dev->coherent_dma_mask)
+               dma_set_mask(pdev->dev, pdev->dev->coherent_dma_mask);
+       else
+               dma_set_mask(pdev->dev, DMA_BIT_MASK(64));
+
+       ret = dma_async_device_register(&pdev->device);
+       if (ret) {
+               dev_err(pdev->device.dev, "unable to register\n");
+               return ret;
+       }
+
+       dev_info(pdev->device.dev, "initialized\n");
+       return 0;
+}
+
+static const struct platform_device_id mmp_pdma_id_table[] = {
+       { "mmp-pdma", },
+       { },
+};
+
+static struct platform_driver mmp_pdma_driver = {
+       .driver         = {
+               .name   = "mmp-pdma",
+               .owner  = THIS_MODULE,
+               .of_match_table = mmp_pdma_dt_ids,
+       },
+       .id_table       = mmp_pdma_id_table,
+       .probe          = mmp_pdma_probe,
+       .remove         = __devexit_p(mmp_pdma_remove),
+};
+
+module_platform_driver(mmp_pdma_driver);
+
+MODULE_DESCRIPTION("MARVELL MMP Periphera DMA Driver");
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_LICENSE("GPL v2");
index 6d9c82e891d7c722505fe50507bd34218cb6bc2d..f3e8d71bcbc7018f12974197268a6cdf66ebd53b 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/device.h>
 #include <mach/regs-icu.h>
 #include <linux/platform_data/dma-mmp_tdma.h>
+#include <linux/of_device.h>
 
 #include "dmaengine.h"
 
@@ -127,7 +128,6 @@ struct mmp_tdma_device {
        void __iomem                    *base;
        struct dma_device               device;
        struct mmp_tdma_chan            *tdmac[TDMA_CHANNEL_NUM];
-       int                             irq;
 };
 
 #define to_mmp_tdma_chan(dchan) container_of(dchan, struct mmp_tdma_chan, chan)
@@ -492,7 +492,7 @@ static int __devinit mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
                return -ENOMEM;
        }
        if (irq)
-               tdmac->irq = irq + idx;
+               tdmac->irq = irq;
        tdmac->dev         = tdev->dev;
        tdmac->chan.device = &tdev->device;
        tdmac->idx         = idx;
@@ -505,34 +505,43 @@ static int __devinit mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
        /* add the channel to tdma_chan list */
        list_add_tail(&tdmac->chan.device_node,
                        &tdev->device.channels);
-
        return 0;
 }
 
+static struct of_device_id mmp_tdma_dt_ids[] = {
+       { .compatible = "marvell,adma-1.0", .data = (void *)MMP_AUD_TDMA},
+       { .compatible = "marvell,pxa910-squ", .data = (void *)PXA910_SQU},
+       {}
+};
+MODULE_DEVICE_TABLE(of, mmp_tdma_dt_ids);
+
 static int __devinit mmp_tdma_probe(struct platform_device *pdev)
 {
-       const struct platform_device_id *id = platform_get_device_id(pdev);
-       enum mmp_tdma_type type = id->driver_data;
+       enum mmp_tdma_type type;
+       const struct of_device_id *of_id;
        struct mmp_tdma_device *tdev;
        struct resource *iores;
        int i, ret;
-       int irq = 0;
+       int irq = 0, irq_num = 0;
        int chan_num = TDMA_CHANNEL_NUM;
 
+       of_id = of_match_device(mmp_tdma_dt_ids, &pdev->dev);
+       if (of_id)
+               type = (enum mmp_tdma_type) of_id->data;
+       else
+               type = platform_get_device_id(pdev)->driver_data;
+
        /* always have couple channels */
        tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL);
        if (!tdev)
                return -ENOMEM;
 
        tdev->dev = &pdev->dev;
-       iores = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!iores)
-               return -EINVAL;
 
-       if (resource_size(iores) != chan_num)
-               tdev->irq = iores->start;
-       else
-               irq = iores->start;
+       for (i = 0; i < chan_num; i++) {
+               if (platform_get_irq(pdev, i) > 0)
+                       irq_num++;
+       }
 
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!iores)
@@ -542,25 +551,26 @@ static int __devinit mmp_tdma_probe(struct platform_device *pdev)
        if (!tdev->base)
                return -EADDRNOTAVAIL;
 
-       if (tdev->irq) {
-               ret = devm_request_irq(&pdev->dev, tdev->irq,
+       INIT_LIST_HEAD(&tdev->device.channels);
+
+       if (irq_num != chan_num) {
+               irq = platform_get_irq(pdev, 0);
+               ret = devm_request_irq(&pdev->dev, irq,
                        mmp_tdma_int_handler, IRQF_DISABLED, "tdma", tdev);
                if (ret)
                        return ret;
        }
 
-       dma_cap_set(DMA_SLAVE, tdev->device.cap_mask);
-       dma_cap_set(DMA_CYCLIC, tdev->device.cap_mask);
-
-       INIT_LIST_HEAD(&tdev->device.channels);
-
        /* initialize channel parameters */
        for (i = 0; i < chan_num; i++) {
+               irq = (irq_num != chan_num) ? 0 : platform_get_irq(pdev, i);
                ret = mmp_tdma_chan_init(tdev, i, irq, type);
                if (ret)
                        return ret;
        }
 
+       dma_cap_set(DMA_SLAVE, tdev->device.cap_mask);
+       dma_cap_set(DMA_CYCLIC, tdev->device.cap_mask);
        tdev->device.dev = &pdev->dev;
        tdev->device.device_alloc_chan_resources =
                                        mmp_tdma_alloc_chan_resources;
@@ -595,6 +605,7 @@ static struct platform_driver mmp_tdma_driver = {
        .driver         = {
                .name   = "mmp-tdma",
                .owner  = THIS_MODULE,
+               .of_match_table = mmp_tdma_dt_ids,
        },
        .id_table       = mmp_tdma_id_table,
        .probe          = mmp_tdma_probe,
index 734a4eb84d6579675110033eeda6676ff40c4c91..9f02e794b12b00d4ed75d62a67bd255f321992ee 100644 (file)
@@ -101,7 +101,8 @@ struct mxs_dma_ccw {
        u32             pio_words[MXS_PIO_WORDS];
 };
 
-#define NUM_CCW        (int)(PAGE_SIZE / sizeof(struct mxs_dma_ccw))
+#define CCW_BLOCK_SIZE (4 * PAGE_SIZE)
+#define NUM_CCW        (int)(CCW_BLOCK_SIZE / sizeof(struct mxs_dma_ccw))
 
 struct mxs_dma_chan {
        struct mxs_dma_engine           *mxs_dma;
@@ -354,14 +355,15 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
 
        mxs_chan->chan_irq = data->chan_irq;
 
-       mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev, PAGE_SIZE,
-                               &mxs_chan->ccw_phys, GFP_KERNEL);
+       mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev,
+                               CCW_BLOCK_SIZE, &mxs_chan->ccw_phys,
+                               GFP_KERNEL);
        if (!mxs_chan->ccw) {
                ret = -ENOMEM;
                goto err_alloc;
        }
 
-       memset(mxs_chan->ccw, 0, PAGE_SIZE);
+       memset(mxs_chan->ccw, 0, CCW_BLOCK_SIZE);
 
        if (mxs_chan->chan_irq != NO_IRQ) {
                ret = request_irq(mxs_chan->chan_irq, mxs_dma_int_handler,
@@ -387,7 +389,7 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
 err_clk:
        free_irq(mxs_chan->chan_irq, mxs_dma);
 err_irq:
-       dma_free_coherent(mxs_dma->dma_device.dev, PAGE_SIZE,
+       dma_free_coherent(mxs_dma->dma_device.dev, CCW_BLOCK_SIZE,
                        mxs_chan->ccw, mxs_chan->ccw_phys);
 err_alloc:
        return ret;
@@ -402,7 +404,7 @@ static void mxs_dma_free_chan_resources(struct dma_chan *chan)
 
        free_irq(mxs_chan->chan_irq, mxs_dma);
 
-       dma_free_coherent(mxs_dma->dma_device.dev, PAGE_SIZE,
+       dma_free_coherent(mxs_dma->dma_device.dev, CCW_BLOCK_SIZE,
                        mxs_chan->ccw, mxs_chan->ccw_phys);
 
        clk_disable_unprepare(mxs_dma->clk);
index 169c0dbd71aef5d171ca9b5ec9af8626939366b0..665668b6f2b14f7d6df5179d5ae37576336d1ea6 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/dmaengine.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl330.h>
-#include <linux/pm_runtime.h>
 #include <linux/scatterlist.h>
 #include <linux/of.h>
 
@@ -586,8 +585,6 @@ struct dma_pl330_dmac {
 
        /* Peripheral channels connected to this DMAC */
        struct dma_pl330_chan *peripherals; /* keep at end */
-
-       struct clk *clk;
 };
 
 struct dma_pl330_desc {
@@ -2395,7 +2392,7 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
        pch->pl330_chid = pl330_request_channel(&pdmac->pif);
        if (!pch->pl330_chid) {
                spin_unlock_irqrestore(&pch->lock, flags);
-               return 0;
+               return -ENOMEM;
        }
 
        tasklet_init(&pch->task, pl330_tasklet, (unsigned long) pch);
@@ -2889,29 +2886,17 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
                goto probe_err1;
        }
 
-       pdmac->clk = clk_get(&adev->dev, "dma");
-       if (IS_ERR(pdmac->clk)) {
-               dev_err(&adev->dev, "Cannot get operation clock.\n");
-               ret = -EINVAL;
-               goto probe_err2;
-       }
-
        amba_set_drvdata(adev, pdmac);
 
-#ifndef CONFIG_PM_RUNTIME
-       /* enable dma clk */
-       clk_enable(pdmac->clk);
-#endif
-
        irq = adev->irq[0];
        ret = request_irq(irq, pl330_irq_handler, 0,
                        dev_name(&adev->dev), pi);
        if (ret)
-               goto probe_err3;
+               goto probe_err2;
 
        ret = pl330_add(pi);
        if (ret)
-               goto probe_err4;
+               goto probe_err3;
 
        INIT_LIST_HEAD(&pdmac->desc_pool);
        spin_lock_init(&pdmac->pool_lock);
@@ -2933,7 +2918,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
        if (!pdmac->peripherals) {
                ret = -ENOMEM;
                dev_err(&adev->dev, "unable to allocate pdmac->peripherals\n");
-               goto probe_err5;
+               goto probe_err4;
        }
 
        for (i = 0; i < num_chan; i++) {
@@ -2961,6 +2946,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
                if (pi->pcfg.num_peri) {
                        dma_cap_set(DMA_SLAVE, pd->cap_mask);
                        dma_cap_set(DMA_CYCLIC, pd->cap_mask);
+                       dma_cap_set(DMA_PRIVATE, pd->cap_mask);
                }
        }
 
@@ -2976,7 +2962,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_err5;
+               goto probe_err4;
        }
 
        dev_info(&adev->dev,
@@ -2989,15 +2975,10 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 
        return 0;
 
-probe_err5:
-       pl330_del(pi);
 probe_err4:
-       free_irq(irq, pi);
+       pl330_del(pi);
 probe_err3:
-#ifndef CONFIG_PM_RUNTIME
-       clk_disable(pdmac->clk);
-#endif
-       clk_put(pdmac->clk);
+       free_irq(irq, pi);
 probe_err2:
        iounmap(pi->base);
 probe_err1:
@@ -3044,10 +3025,6 @@ static int __devexit pl330_remove(struct amba_device *adev)
        res = &adev->res;
        release_mem_region(res->start, resource_size(res));
 
-#ifndef CONFIG_PM_RUNTIME
-       clk_disable(pdmac->clk);
-#endif
-
        kfree(pdmac);
 
        return 0;
@@ -3063,49 +3040,10 @@ static struct amba_id pl330_ids[] = {
 
 MODULE_DEVICE_TABLE(amba, pl330_ids);
 
-#ifdef CONFIG_PM_RUNTIME
-static int pl330_runtime_suspend(struct device *dev)
-{
-       struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
-
-       if (!pdmac) {
-               dev_err(dev, "failed to get dmac\n");
-               return -ENODEV;
-       }
-
-       clk_disable(pdmac->clk);
-
-       return 0;
-}
-
-static int pl330_runtime_resume(struct device *dev)
-{
-       struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
-
-       if (!pdmac) {
-               dev_err(dev, "failed to get dmac\n");
-               return -ENODEV;
-       }
-
-       clk_enable(pdmac->clk);
-
-       return 0;
-}
-#else
-#define pl330_runtime_suspend  NULL
-#define pl330_runtime_resume   NULL
-#endif /* CONFIG_PM_RUNTIME */
-
-static const struct dev_pm_ops pl330_pm_ops = {
-       .runtime_suspend = pl330_runtime_suspend,
-       .runtime_resume = pl330_runtime_resume,
-};
-
 static struct amba_driver pl330_driver = {
        .drv = {
                .owner = THIS_MODULE,
                .name = "dma-pl330",
-               .pm = &pl330_pm_ops,
        },
        .id_table = pl330_ids,
        .probe = pl330_probe,
index 3eed8b35b0f19d51f025a5de2dc656b9fe3f211c..64385cde044b3feefcc49001edbf0e9ee647bd0d 100644 (file)
@@ -570,21 +570,19 @@ static int __devinit sirfsoc_dma_probe(struct platform_device *op)
 
        if (of_property_read_u32(dn, "cell-index", &id)) {
                dev_err(dev, "Fail to get DMAC index\n");
-               ret = -ENODEV;
-               goto free_mem;
+               return -ENODEV;
        }
 
        sdma->irq = irq_of_parse_and_map(dn, 0);
        if (sdma->irq == NO_IRQ) {
                dev_err(dev, "Error mapping IRQ!\n");
-               ret = -EINVAL;
-               goto free_mem;
+               return -EINVAL;
        }
 
        ret = of_address_to_resource(dn, 0, &res);
        if (ret) {
                dev_err(dev, "Error parsing memory region!\n");
-               goto free_mem;
+               goto irq_dispose;
        }
 
        regs_start = res.start;
@@ -597,12 +595,11 @@ static int __devinit sirfsoc_dma_probe(struct platform_device *op)
                goto irq_dispose;
        }
 
-       ret = devm_request_irq(dev, sdma->irq, &sirfsoc_dma_irq, 0, DRV_NAME,
-               sdma);
+       ret = request_irq(sdma->irq, &sirfsoc_dma_irq, 0, DRV_NAME, sdma);
        if (ret) {
                dev_err(dev, "Error requesting IRQ!\n");
                ret = -EINVAL;
-               goto unmap_mem;
+               goto irq_dispose;
        }
 
        dma = &sdma->dma;
@@ -652,13 +649,9 @@ static int __devinit sirfsoc_dma_probe(struct platform_device *op)
        return 0;
 
 free_irq:
-       devm_free_irq(dev, sdma->irq, sdma);
+       free_irq(sdma->irq, sdma);
 irq_dispose:
        irq_dispose_mapping(sdma->irq);
-unmap_mem:
-       iounmap(sdma->base);
-free_mem:
-       devm_kfree(dev, sdma);
        return ret;
 }
 
@@ -668,10 +661,8 @@ static int __devexit sirfsoc_dma_remove(struct platform_device *op)
        struct sirfsoc_dma *sdma = dev_get_drvdata(dev);
 
        dma_async_device_unregister(&sdma->dma);
-       devm_free_irq(dev, sdma->irq, sdma);
+       free_irq(sdma->irq, sdma);
        irq_dispose_mapping(sdma->irq);
-       iounmap(sdma->base);
-       devm_kfree(dev, sdma);
        return 0;
 }
 
index eee8d9b9a20bcdfde84eaa75dc05617b0524dd36..ae55091c22728a4342af8b3f288ecb4b013628c2 100644 (file)
@@ -2921,19 +2921,23 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
        struct d40_base *base = NULL;
        int num_log_chans = 0;
        int num_phy_chans;
+       int clk_ret = -EINVAL;
        int i;
        u32 pid;
        u32 cid;
        u8 rev;
 
        clk = clk_get(&pdev->dev, NULL);
-
        if (IS_ERR(clk)) {
                d40_err(&pdev->dev, "No matching clock found\n");
                goto failure;
        }
 
-       clk_enable(clk);
+       clk_ret = clk_prepare_enable(clk);
+       if (clk_ret) {
+               d40_err(&pdev->dev, "Failed to prepare/enable clock\n");
+               goto failure;
+       }
 
        /* Get IO for DMAC base address */
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base");
@@ -3063,10 +3067,10 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
        return base;
 
 failure:
-       if (!IS_ERR(clk)) {
-               clk_disable(clk);
+       if (!clk_ret)
+               clk_disable_unprepare(clk);
+       if (!IS_ERR(clk))
                clk_put(clk);
-       }
        if (virtbase)
                iounmap(virtbase);
        if (res)
index 45fbeed1c1a5e56d621254399d4b7c63b93861df..528c62dd4b00e1b52928ff66f3a54e7ae206680f 100644 (file)
@@ -169,6 +169,7 @@ typedef void (*dma_isr_handler)(struct tegra_dma_channel *tdc,
 /* tegra_dma_channel: Channel specific information */
 struct tegra_dma_channel {
        struct dma_chan         dma_chan;
+       char                    name[30];
        bool                    config_init;
        int                     id;
        int                     irq;
@@ -475,8 +476,7 @@ static void tegra_dma_abort_all(struct tegra_dma_channel *tdc)
        while (!list_empty(&tdc->pending_sg_req)) {
                sgreq = list_first_entry(&tdc->pending_sg_req,
                                                typeof(*sgreq), node);
-               list_del(&sgreq->node);
-               list_add_tail(&sgreq->node, &tdc->free_sg_req);
+               list_move_tail(&sgreq->node, &tdc->free_sg_req);
                if (sgreq->last_sg) {
                        dma_desc = sgreq->dma_desc;
                        dma_desc->dma_status = DMA_ERROR;
@@ -570,8 +570,7 @@ static void handle_cont_sngl_cycle_dma_done(struct tegra_dma_channel *tdc,
 
        /* If not last req then put at end of pending list */
        if (!list_is_last(&sgreq->node, &tdc->pending_sg_req)) {
-               list_del(&sgreq->node);
-               list_add_tail(&sgreq->node, &tdc->pending_sg_req);
+               list_move_tail(&sgreq->node, &tdc->pending_sg_req);
                sgreq->configured = false;
                st = handle_continuous_head_request(tdc, sgreq, to_terminate);
                if (!st)
@@ -1284,7 +1283,6 @@ static int __devinit tegra_dma_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&tdma->dma_dev.channels);
        for (i = 0; i < cdata->nr_channels; i++) {
                struct tegra_dma_channel *tdc = &tdma->channels[i];
-               char irq_name[30];
 
                tdc->chan_base_offset = TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET +
                                        i * TEGRA_APBDMA_CHANNEL_REGISTER_SIZE;
@@ -1296,9 +1294,9 @@ static int __devinit tegra_dma_probe(struct platform_device *pdev)
                        goto err_irq;
                }
                tdc->irq = res->start;
-               snprintf(irq_name, sizeof(irq_name), "apbdma.%d", i);
+               snprintf(tdc->name, sizeof(tdc->name), "apbdma.%d", i);
                ret = devm_request_irq(&pdev->dev, tdc->irq,
-                               tegra_dma_isr, 0, irq_name, tdc);
+                               tegra_dma_isr, 0, tdc->name, tdc);
                if (ret) {
                        dev_err(&pdev->dev,
                                "request_irq failed with err %d channel %d\n",
index 2783f69dada644e47779ab868965748887141462..f8d22872d75324e4dd0b2727308804f8a139eefe 100644 (file)
@@ -473,8 +473,8 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
        client->bus_reset_closure = a->bus_reset_closure;
        if (a->bus_reset != 0) {
                fill_bus_reset_event(&bus_reset, client);
-               ret = copy_to_user(u64_to_uptr(a->bus_reset),
-                                  &bus_reset, sizeof(bus_reset));
+               /* unaligned size of bus_reset is 36 bytes */
+               ret = copy_to_user(u64_to_uptr(a->bus_reset), &bus_reset, 36);
        }
        if (ret == 0 && list_empty(&client->link))
                list_add_tail(&client->link, &client->device->client_list);
index a32837951dd28e0d562ef88862f0cb6d1e171c4a..130a2b510d4aebe1c9852b96457aea52e9857a15 100644 (file)
@@ -19,8 +19,8 @@
 #include <linux/clk.h>
 #include <linux/pm_runtime.h>
 
+#include <video/samsung_fimd.h>
 #include <drm/exynos_drm.h>
-#include <plat/regs-fb-v4.h>
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fbdev.h"
index a1ea034611d5cb03c08f72a7149e97b02b94dadf..db7c549431026f8ad56eeeb6d1062ff3063aa4a9 100644 (file)
@@ -101,23 +101,6 @@ nouveau_parent_create_(struct nouveau_object *parent,
        return 0;
 }
 
-int
-_nouveau_parent_ctor(struct nouveau_object *parent,
-                    struct nouveau_object *engine,
-                    struct nouveau_oclass *oclass, void *data, u32 size,
-                    struct nouveau_object **pobject)
-{
-       struct nouveau_parent *object;
-       int ret;
-
-       ret = nouveau_parent_create(parent, engine, oclass, 0, NULL, 0, &object);
-       *pobject = nv_object(object);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
 void
 nouveau_parent_destroy(struct nouveau_parent *parent)
 {
index d3aa251a5eb6b12d54cf801d192f0aff551be9c9..3c2e940eb0f83525f5d61b9acd7825f37ed7ba5b 100644 (file)
@@ -50,9 +50,6 @@ int  nouveau_parent_create_(struct nouveau_object *, struct nouveau_object *,
                            int size, void **);
 void nouveau_parent_destroy(struct nouveau_parent *);
 
-int  _nouveau_parent_ctor(struct nouveau_object *, struct nouveau_object *,
-                         struct nouveau_oclass *, void *, u32,
-                         struct nouveau_object **);
 void _nouveau_parent_dtor(struct nouveau_object *);
 #define _nouveau_parent_init _nouveau_object_init
 #define _nouveau_parent_fini _nouveau_object_fini
index 49bff901544c7b7a591ea7eaadaf9ddffdda6e9e..c24ec8ab3db441204480cdc18fb3d86a84b256d8 100644 (file)
@@ -26,7 +26,7 @@ void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *);
 struct nouveau_timer {
        struct nouveau_subdev base;
        u64  (*read)(struct nouveau_timer *);
-       void (*alarm)(struct nouveau_timer *, u32 time, struct nouveau_alarm *);
+       void (*alarm)(struct nouveau_timer *, u64 time, struct nouveau_alarm *);
 };
 
 static inline struct nouveau_timer *
index 2fbb6df697cdc2268fa911d70a45443bfbcba509..dcb5c2befc928a716425ace89149cec8a808c2e3 100644 (file)
@@ -185,23 +185,22 @@ static void
 nouveau_bios_shadow_acpi(struct nouveau_bios *bios)
 {
        struct pci_dev *pdev = nv_device(bios)->pdev;
-       int cnt = 65536 / 4096;
-       int ret;
+       int ret, cnt, i;
+       u8  data[3];
 
        if (!nouveau_acpi_rom_supported(pdev))
                return;
 
-       bios->data = kmalloc(65536, GFP_KERNEL);
        bios->size = 0;
-       if (!bios->data)
-               return;
-
-       while (cnt--) {
-               ret = nouveau_acpi_get_bios_chunk(bios->data, bios->size, 4096);
-               if (ret != 4096)
-                       return;
+       if (nouveau_acpi_get_bios_chunk(data, 0, 3) == 3)
+               bios->size = data[2] * 512;
 
-               bios->size += 4096;
+       bios->data = kmalloc(bios->size, GFP_KERNEL);
+       for (i = 0; bios->data && i < bios->size; i += cnt) {
+               cnt = min((bios->size - i), (u32)4096);
+               ret = nouveau_acpi_get_bios_chunk(bios->data, i, cnt);
+               if (ret != cnt)
+                       break;
        }
 }
 
index fd181fbceddb9313cc58e1c7b04b77659c41eff8..f4147f67eda687da04a128ec49ea9de2e40a15bd 100644 (file)
@@ -90,6 +90,7 @@ nv50_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        priv->base.pll_set = nv50_clock_pll_set;
+       priv->base.pll_calc = nv04_clock_pll_calc;
        return 0;
 }
 
index f87a7a3eb4e7c4c55548aed7bf398b6a8be83bad..9360ddd469e727cae0f053dd1a0cd7e96c894283 100644 (file)
@@ -92,7 +92,7 @@ nv50_fan_pwm_clock(struct nouveau_therm *therm)
                if (nv_rd32(therm, 0xc040) & 0x800000) {
                        /* Use the HOST clock (100 MHz)
                        * Where does this constant(2.4) comes from? */
-                       pwm_clock = (100000000 >> pwm_div) / 10 / 24;
+                       pwm_clock = (100000000 >> pwm_div) * 10 / 24;
                } else {
                        /* Where does this constant(20) comes from? */
                        pwm_clock = (crystal * 1000) >> pwm_div;
index 49976be4d73b12671eb0f3d29facdc266ea71bfe..c26ca9bef6717b18521208a2c48b2e7423d06b86 100644 (file)
@@ -85,7 +85,7 @@ nv04_timer_alarm_trigger(struct nouveau_timer *ptimer)
 }
 
 static void
-nv04_timer_alarm(struct nouveau_timer *ptimer, u32 time,
+nv04_timer_alarm(struct nouveau_timer *ptimer, u64 time,
                 struct nouveau_alarm *alarm)
 {
        struct nv04_timer_priv *priv = (void *)ptimer;
index 23ab3c496b0505bb1ed3c2f0e43dfe2ef1a139a8..1672e2a5db46865cd2849927517c528f287c3314 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/kdev_t.h>
 #include <linux/sched.h>
 #include <linux/time.h>
+#include <linux/err.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_bus.h>
 
index 8b24d1a4a2b47ed67c58fab6781e274045d33aa3..dafa477715e327fcb324c86e51dba46e1afeb450 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/jiffies.h>
 
 /* Addresses to scan */
 static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
index fe72c69a2d68b2f7b1d9858c455aafa74f4e4133..517f1856c706ba2f809d9a9eb6cf04b6fde925d2 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/delay.h>
 #include <linux/mutex.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
index baee482aedfc716de5c674867b34f554148fa4d6..98a7d81e25c5f18de577c31db321481c0b0d225d 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
-#include <linux/delay.h>
 #include <linux/log2.h>
 #include <linux/slab.h>
 
index 861c756e95366ceb6a3fcc4e7a5dfa5b838feb9a..989e54c3925224a84bbf8bc55ac900a53fdf49ad 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
+#include <linux/jiffies.h>
 
 /* Indexes for the sysfs hooks */
 
index 8f3f6f2c45fd1a5ba95664a4ba92a6ffe7e6323c..b41baffa20f0287ecb69de92ffbc66944535048f 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/leds.h>
 #include <linux/hwmon.h>
 #include <linux/workqueue.h>
+#include <linux/err.h>
 
 /* data port used by Apple SMC */
 #define APPLESMC_DATA_PORT     0x300
index cccb0e9d45b46562d090065e5e65d6d9e48c2811..56dbcfb3e30170346f16826a37cff51b641e8ef2 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/dmi.h>
+#include <linux/jiffies.h>
+#include <linux/err.h>
 
 #include <acpi/acpi.h>
 #include <acpi/acpixf.h>
index fc65f2d3ec913c68d901d6ca264ed53488445aae..b8d01c5f57131f0489659c2bdf3e31346bc64f90 100644 (file)
@@ -12,7 +12,6 @@
  *
  */
 
-#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
index 68ab94bde3f1d56c0acfbc4ab928ab8d08bf56eb..142e1cb8dea7e6ed641243588d525d6405d2124d 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/err.h>
 #include <linux/sysfs.h>
 #include <linux/mutex.h>
+#include <linux/jiffies.h>
 
 #define THERMAL_PID_REG                0xfd
 #define THERMAL_SMSC_ID_REG    0xfe
index ada12a98a97c82b6f305fb5c2934d10fdb236675..a98c917b5888f219ad219ebb7ed7b20d7d937dea 100644 (file)
@@ -18,7 +18,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
index e8ee75f554724390eaa3750e6b8259b02c8f35d4..9a675efaa78d65dd8e3ae8dde751b0fbf951f2ab 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/mutex.h>
 #include <linux/device.h>
 #include <linux/delay.h>
+#include <linux/jiffies.h>
 
 /**
  * struct hih6130 - HIH-6130 device specific data
index a18882cc073d34f0318afea85c65ed7b813a000c..46141abaafba469ff1630f6665e0225d3268799c 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/jiffies.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
-#include <linux/delay.h>
 #include <linux/log2.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
index 37f17e0d9d5d85a5c4e20024812b5b97dc1b36c8..a14f634248e72c9c7574bcc6593ac835d66eb19a 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/platform_device.h>
 #include <linux/math64.h>
 #include <linux/time.h>
+#include <linux/err.h>
 
 #define REFRESH_INTERVAL       (HZ)
 #define IPMI_TIMEOUT           (30 * HZ)
index 41dbf8161ed7b4fb1bc29811c61f006152c9a41c..b622a93ec32cea4622d72037ee41cfd3612d2b38 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/jiffies.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
+#include <linux/err.h>
 
 #define REFRESH_INTERVAL       (2 * HZ)
 #define DRVNAME                        "ibmpex"
index 70717d4a5e8934e8d530fabf1d5833f8c8f3e817..2b726346f8faa976ddca5b22332cc4a31013e84c 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/jiffies.h>
 
 #include <linux/platform_data/ina2xx.h>
 
index 49a69c5b3b8d336fcc4fd882c0f82d4fe71d3ceb..e8c7fb0bbf953e4bd3788a334df6517cc214374e 100644 (file)
@@ -22,7 +22,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
index bd75d2415432dfefada86bff1471a9cc016cc032..41df29f59b0e5dd011f8258c228b14650a174f5f 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/jiffies.h>
 
 /*
  * This driver supports various Lineage Compact Power Line DC/DC and AC/DC
index 2282d77e83e8ee117a6ffc4baeea24b8d3580498..71626f3c874239eba685e098f65d324707e6f946 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/jiffies.h>
 
 /*
  * The LM92 and MAX6635 have 2 two-state pins for address selection,
index c3d4255ed154f7b8d090b64d67aac5870022f5a3..1a003f73e4e4a8b96d4a87aa0dacecfb7ed15eff 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/delay.h>
+#include <linux/jiffies.h>
 
 /* LM93 REGISTER ADDRESSES */
 
index 8496baa08bc8349183e537e4f61e0d2db03c7cd4..4319a94f549d2bdd83541f3e0a293c1c419597c4 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/jiffies.h>
 
 /* chip registers */
 #define LTC4151_SENSE_H        0x00
index 98b3d04f98b70bee2713914031c4173451f5517a..e8876108a6b3278a9e447912f3a3a5a9e1baf73a 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/jiffies.h>
 
 /* Here are names of the chip's registers (a.k.a. commands) */
 enum ltc4215_cmd {
index 52075914eb0bb1adb7a225a9f500de3869b4a125..3653f79dc2de0870f4d642a8e556e525ed8bac95 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/jiffies.h>
 #include <linux/i2c/ltc4245.h>
 
 /* Here are names of the chip's registers (a.k.a. commands) */
index 77476a575c4e6340b5987ff7a50e600c42c55b13..84a2d2872b20c4172a73a045ec1c1c6223dcd27e 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/jiffies.h>
 
 /* chip registers */
 #define LTC4261_STATUS 0x00    /* readonly */
index 019427d7a5fd8be8f3bc1fbc1550f375778f34fa..e0019c69d1bbcd19b209446146356a82ba7926bb 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
-#include <linux/delay.h>
 #include <linux/jiffies.h>
 
 enum chips { max16065, max16066, max16067, max16068, max16070, max16071 };
index 6c11ec214071eb272d2f498796d422312621217f..445e5d40ac82c5760c90dfa7fbcf3f32893ac52c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * max1619.c - Part of lm_sensors, Linux kernel modules for hardware
  *             monitoring
- * Copyright (C) 2003-2004 Alexey Fisher <fishor@mail.ru>
+ * Copyright (C) 2003-2004 Oleksij Rempel <bug-track@fisher-privat.net>
  *                         Jean Delvare <khali@linux-fr.org>
  *
  * Based on the lm90 driver. The MAX1619 is a sensor chip made by Maxim.
@@ -357,7 +357,7 @@ static struct max1619_data *max1619_update_device(struct device *dev)
 
 module_i2c_driver(max1619_driver);
 
-MODULE_AUTHOR("Alexey Fisher <fishor@mail.ru> and "
+MODULE_AUTHOR("Oleksij Rempel <bug-track@fisher-privat.net> and "
        "Jean Delvare <khali@linux-fr.org>");
 MODULE_DESCRIPTION("MAX1619 sensor driver");
 MODULE_LICENSE("GPL");
index bf236c0782b74e5f7f3de7509f1fad5298aa9344..223461a6d70f974ebeec806bc4c3cc8cb780088f 100644 (file)
@@ -7,7 +7,7 @@
  * Derived from:
  *
  *  Based on the max1619 driver.
- *  Copyright (C) 2003-2004 Alexey Fisher <fishor@mail.ru>
+ *  Copyright (C) 2003-2004 Oleksij Rempel <bug-track@fisher-privat.net>
  *                          Jean Delvare <khali@linux-fr.org>
  *
  * The MAX6642 is a sensor chip made by Maxim.
index 29b319db573efed8c8d5ec38fce66a36cb265ed8..7d19b1bb9ce6acf7de556c93fefb685501a195e1 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
-#include <linux/delay.h>
+#include <linux/jiffies.h>
 #include <linux/i2c/pmbus.h>
 #include "pmbus.h"
 
index fe11b95670bdd5a483bc2cb4d46e86b0a66a5ad5..bcecd025fcc442a9edcbcaf9c3fc41519b1308b5 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/init.h>
 #include <linux/err.h>
index c2565d04cd4a104df117c32c65878d236f8522ec..5f67546950b1ebce2c4e59a92acded014445195a 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/device.h>
+#include <linux/jiffies.h>
 
 /* I2C command bytes */
 #define SHT21_TRIG_T_MEASUREMENT_HM  0xe3
index cbc51fb30dba12f0c217cd038386f21aa7be52ba..d9e1b7de78da7798b2a7103282ad4c7d176aaaaf 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/delay.h>
+#include <linux/jiffies.h>
 
 /* Internal reference voltage (VREF, x 1000 */
 #define SMM665_VREF_ADC_X1000  1250
index 080c2637048093e5924d6cc7042e08056c538408..3c2c48d904e658736605ee95e5b21f08cd1ccf98 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/jiffies.h>
 
 MODULE_LICENSE("GPL");
 
index 4e1ff82c63e0063abbf8e07644842c7692f4a492..b8777e54190a4768033334813ac681cc8fed7e54 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/device.h>
+#include <linux/jiffies.h>
 
 #define        DRIVER_NAME "tmp102"
 
index c315c59f61fe3fa86b982b19eec3315de0686ec6..44136bb6d045469de09f4eaf302a8085f8b07eb7 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/io.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
 
 #define DRV_MODULE_VERSION     "0.1"
 
index 93ea81a4bf35758988ac7f817ee6dfae9978be05..39ab7bcc616e7a9e8733ce9bbbcc7e3cf6b0b970 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/jiffies.h>
 
 #define NUMBER_OF_VIN          10
 #define NUMBER_OF_FANIN                5
index 06d6f56d4f699eecbcb1aea81c7b719428b65853..053645279f381b453396053dfb71294346604717 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
+#include <linux/jiffies.h>
 
 /* Addresses to scan */
 static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
index 4fc47e062071a2efa892bc0aff6903e4ef2d521d..99799fd1d917ce5a451f6a14cbf2c6da72f6a2e6 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/kref.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
+#include <linux/jiffies.h>
 
 /* Default values */
 #define WATCHDOG_TIMEOUT 2     /* 2 minute default timeout */
index b813c646c7ca7b743ef039491d93440496e33244..55a4f4894531fa8a284116b080bea427a2e8e8ea 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
-#include <linux/delay.h>
+#include <linux/jiffies.h>
 
 /* Addresses to scan */
 static const unsigned short normal_i2c[] = {
index c99c8a0473cf13257d9abeb548aa548536d7c8d1..f0e8286c3c70ed7c1c2a57a73b19cc06fec8a193 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/jiffies.h>
 
 /* Addresses to scan */
 static const unsigned short normal_i2c[] = { 0x2e, 0x2f, I2C_CLIENT_END };
index 6f5f98d69af7c26b2fd7b895106e11745ce7d155..f892a424009b8123c3cb0ceb3dae75359cceaef9 100644 (file)
@@ -46,14 +46,19 @@ static int i2c_debug;
 #define pca_set_con(adap, val) pca_outw(adap, I2C_PCA_CON, val)
 #define pca_get_con(adap) pca_inw(adap, I2C_PCA_CON)
 #define pca_wait(adap) adap->wait_for_completion(adap->data)
-#define pca_reset(adap) adap->reset_chip(adap->data)
 
-static void pca9665_reset(void *pd)
+static void pca_reset(struct i2c_algo_pca_data *adap)
 {
-       struct i2c_algo_pca_data *adap = pd;
-       pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IPRESET);
-       pca_outw(adap, I2C_PCA_IND, 0xA5);
-       pca_outw(adap, I2C_PCA_IND, 0x5A);
+       if (adap->chip == I2C_PCA_CHIP_9665) {
+               /* Ignore the reset function from the module,
+                * we can use the parallel bus reset.
+                */
+               pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IPRESET);
+               pca_outw(adap, I2C_PCA_IND, 0xA5);
+               pca_outw(adap, I2C_PCA_IND, 0x5A);
+       } else {
+               adap->reset_chip(adap->data);
+       }
 }
 
 /*
@@ -378,11 +383,12 @@ static unsigned int pca_probe_chip(struct i2c_adapter *adap)
        pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IADR);
        if (pca_inw(pca_data, I2C_PCA_IND) == 0xAA) {
                printk(KERN_INFO "%s: PCA9665 detected.\n", adap->name);
-               return I2C_PCA_CHIP_9665;
+               pca_data->chip = I2C_PCA_CHIP_9665;
        } else {
                printk(KERN_INFO "%s: PCA9564 detected.\n", adap->name);
-               return I2C_PCA_CHIP_9564;
+               pca_data->chip = I2C_PCA_CHIP_9564;
        }
+       return pca_data->chip;
 }
 
 static int pca_init(struct i2c_adapter *adap)
@@ -456,11 +462,6 @@ static int pca_init(struct i2c_adapter *adap)
                 */
                int raise_fall_time;
 
-               /* Ignore the reset function from the module,
-                * we can use the parallel bus reset
-                */
-               pca_data->reset_chip = pca9665_reset;
-
                if (pca_data->i2c_clock > 1265800) {
                        printk(KERN_WARNING "%s: I2C clock speed too high."
                                " Using 1265.8kHz.\n", adap->name);
index ff01c389e2dacc984cf9ac5afb16407ad81dfbe4..65dd599a02620211b8db7a1ef6bfd1d8f9cdda30 100644 (file)
@@ -294,18 +294,21 @@ comment "I2C system bus drivers (mostly embedded / system-on-chip)"
 
 config I2C_AT91
        tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
-       depends on ARCH_AT91 && EXPERIMENTAL && BROKEN
+       depends on ARCH_AT91 && EXPERIMENTAL
        help
          This supports the use of the I2C interface on Atmel AT91
          processors.
 
-         This driver is BROKEN because the controller which it uses
-         will easily trigger RX overrun and TX underrun errors.  Using
-         low I2C clock rates may partially work around those issues
-         on some systems.  Another serious problem is that there is no
-         documented way to issue repeated START conditions, as needed
+         A serious problem is that there is no documented way to issue
+         repeated START conditions for more than two messages, as needed
          to support combined I2C messages.  Use the i2c-gpio driver
-         unless your system can cope with those limitations.
+         unless your system can cope with this limitation.
+
+         Caution! at91rm9200, at91sam9261, at91sam9260, at91sam9263 devices
+         don't have clock stretching in transmission mode. For that reason,
+         you can encounter underrun issues causing premature stop sendings if
+         the latency to fill the transmission register is too long. If you
+         are facing this situation, use the i2c-gpio driver.
 
 config I2C_AU1550
        tristate "Au1550/Au1200/Au1300 SMBus interface"
@@ -718,6 +721,16 @@ config I2C_XLR
          This driver can also be built as a module.  If so, the module
          will be called i2c-xlr.
 
+config I2C_RCAR
+       tristate "Renesas R-Car I2C Controller"
+       depends on ARCH_SHMOBILE && I2C
+       help
+         If you say yes to this option, support will be included for the
+         R-Car I2C controller.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-rcar.
+
 comment "External I2C/SMBus adapter drivers"
 
 config I2C_DIOLAN_U2C
index 37c4182cc98bb28520eeb1ce579bb3b601cffc01..2d33d62952c112adfb62bde5f08a342a37466c78 100644 (file)
@@ -71,6 +71,7 @@ obj-$(CONFIG_I2C_VERSATILE)   += i2c-versatile.o
 obj-$(CONFIG_I2C_OCTEON)       += i2c-octeon.o
 obj-$(CONFIG_I2C_XILINX)       += i2c-xiic.o
 obj-$(CONFIG_I2C_XLR)          += i2c-xlr.o
+obj-$(CONFIG_I2C_RCAR)         += i2c-rcar.o
 
 # External I2C/SMBus adapter drivers
 obj-$(CONFIG_I2C_DIOLAN_U2C)   += i2c-diolan-u2c.o
index e24484beef078d9e3069b32066cd9c865ed25f22..aa59a254be2c3e3755a377d0c0c1f02dfa6c797d 100644 (file)
 /*
-    i2c Support for Atmel's AT91 Two-Wire Interface (TWI)
-
-    Copyright (C) 2004 Rick Bronson
-    Converted to 2.6 by Andrew Victor <andrew@sanpeople.com>
-
-    Borrowed heavily from original work by:
-    Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.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.
-*/
+ *  i2c Support for Atmel's AT91 Two-Wire Interface (TWI)
+ *
+ *  Copyright (C) 2011 Weinmann Medical GmbH
+ *  Author: Nikolaus Voss <n.voss@weinmann.de>
+ *
+ *  Evolved from original work by:
+ *  Copyright (C) 2004 Rick Bronson
+ *  Converted to 2.6 by Andrew Victor <andrew@sanpeople.com>
+ *
+ *  Borrowed heavily from original work by:
+ *  Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
 #include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/delay.h>
 #include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_i2c.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define TWI_CLK_HZ             100000                  /* max 400 Kbits/s */
+#define AT91_I2C_TIMEOUT       msecs_to_jiffies(100)   /* transfer timeout */
+
+/* AT91 TWI register definitions */
+#define        AT91_TWI_CR             0x0000  /* Control Register */
+#define        AT91_TWI_START          0x0001  /* Send a Start Condition */
+#define        AT91_TWI_STOP           0x0002  /* Send a Stop Condition */
+#define        AT91_TWI_MSEN           0x0004  /* Master Transfer Enable */
+#define        AT91_TWI_SVDIS          0x0020  /* Slave Transfer Disable */
+#define        AT91_TWI_SWRST          0x0080  /* Software Reset */
+
+#define        AT91_TWI_MMR            0x0004  /* Master Mode Register */
+#define        AT91_TWI_IADRSZ_1       0x0100  /* Internal Device Address Size */
+#define        AT91_TWI_MREAD          0x1000  /* Master Read Direction */
+
+#define        AT91_TWI_IADR           0x000c  /* Internal Address Register */
+
+#define        AT91_TWI_CWGR           0x0010  /* Clock Waveform Generator Reg */
+
+#define        AT91_TWI_SR             0x0020  /* Status Register */
+#define        AT91_TWI_TXCOMP         0x0001  /* Transmission Complete */
+#define        AT91_TWI_RXRDY          0x0002  /* Receive Holding Register Ready */
+#define        AT91_TWI_TXRDY          0x0004  /* Transmit Holding Register Ready */
 
-#include <mach/at91_twi.h>
-#include <mach/board.h>
-#include <mach/cpu.h>
+#define        AT91_TWI_OVRE           0x0040  /* Overrun Error */
+#define        AT91_TWI_UNRE           0x0080  /* Underrun Error */
+#define        AT91_TWI_NACK           0x0100  /* Not Acknowledged */
 
-#define TWI_CLOCK              100000          /* Hz. max 400 Kbits/sec */
+#define        AT91_TWI_IER            0x0024  /* Interrupt Enable Register */
+#define        AT91_TWI_IDR            0x0028  /* Interrupt Disable Register */
+#define        AT91_TWI_IMR            0x002c  /* Interrupt Mask Register */
+#define        AT91_TWI_RHR            0x0030  /* Receive Holding Register */
+#define        AT91_TWI_THR            0x0034  /* Transmit Holding Register */
 
+struct at91_twi_pdata {
+       unsigned        clk_max_div;
+       unsigned        clk_offset;
+       bool            has_unre_flag;
+};
+
+struct at91_twi_dev {
+       struct device           *dev;
+       void __iomem            *base;
+       struct completion       cmd_complete;
+       struct clk              *clk;
+       u8                      *buf;
+       size_t                  buf_len;
+       struct i2c_msg          *msg;
+       int                     irq;
+       unsigned                transfer_status;
+       struct i2c_adapter      adapter;
+       unsigned                twi_cwgr_reg;
+       struct at91_twi_pdata   *pdata;
+};
 
-static struct clk *twi_clk;
-static void __iomem *twi_base;
+static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg)
+{
+       return readl_relaxed(dev->base + reg);
+}
+
+static void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, unsigned val)
+{
+       writel_relaxed(val, dev->base + reg);
+}
 
-#define at91_twi_read(reg)             __raw_readl(twi_base + (reg))
-#define at91_twi_write(reg, val)       __raw_writel((val), twi_base + (reg))
+static void at91_disable_twi_interrupts(struct at91_twi_dev *dev)
+{
+       at91_twi_write(dev, AT91_TWI_IDR,
+                      AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY);
+}
 
+static void at91_init_twi_bus(struct at91_twi_dev *dev)
+{
+       at91_disable_twi_interrupts(dev);
+       at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SWRST);
+       at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_MSEN);
+       at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SVDIS);
+       at91_twi_write(dev, AT91_TWI_CWGR, dev->twi_cwgr_reg);
+}
 
 /*
- * Initialize the TWI hardware registers.
+ * Calculate symmetric clock as stated in datasheet:
+ * twi_clk = F_MAIN / (2 * (cdiv * (1 << ckdiv) + offset))
  */
-static void __devinit at91_twi_hwinit(void)
+static void __devinit at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
 {
-       unsigned long cdiv, ckdiv;
-
-       at91_twi_write(AT91_TWI_IDR, 0xffffffff);       /* Disable all interrupts */
-       at91_twi_write(AT91_TWI_CR, AT91_TWI_SWRST);    /* Reset peripheral */
-       at91_twi_write(AT91_TWI_CR, AT91_TWI_MSEN);     /* Set Master mode */
-
-       /* Calcuate clock dividers */
-       cdiv = (clk_get_rate(twi_clk) / (2 * TWI_CLOCK)) - 3;
-       cdiv = cdiv + 1;        /* round up */
-       ckdiv = 0;
-       while (cdiv > 255) {
-               ckdiv++;
-               cdiv = cdiv >> 1;
+       int ckdiv, cdiv, div;
+       struct at91_twi_pdata *pdata = dev->pdata;
+       int offset = pdata->clk_offset;
+       int max_ckdiv = pdata->clk_max_div;
+
+       div = max(0, (int)DIV_ROUND_UP(clk_get_rate(dev->clk),
+                                      2 * twi_clk) - offset);
+       ckdiv = fls(div >> 8);
+       cdiv = div >> ckdiv;
+
+       if (ckdiv > max_ckdiv) {
+               dev_warn(dev->dev, "%d exceeds ckdiv max value which is %d.\n",
+                        ckdiv, max_ckdiv);
+               ckdiv = max_ckdiv;
+               cdiv = 255;
        }
 
-       if (cpu_is_at91rm9200()) {                      /* AT91RM9200 Errata #22 */
-               if (ckdiv > 5) {
-                       printk(KERN_ERR "AT91 I2C: Invalid TWI_CLOCK value!\n");
-                       ckdiv = 5;
-               }
-       }
+       dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv;
+       dev_dbg(dev->dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv);
+}
 
-       at91_twi_write(AT91_TWI_CWGR, (ckdiv << 16) | (cdiv << 8) | cdiv);
+static void at91_twi_write_next_byte(struct at91_twi_dev *dev)
+{
+       if (dev->buf_len <= 0)
+               return;
+
+       at91_twi_write(dev, AT91_TWI_THR, *dev->buf);
+
+       /* send stop when last byte has been written */
+       if (--dev->buf_len == 0)
+               at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
+
+       dev_dbg(dev->dev, "wrote 0x%x, to go %d\n", *dev->buf, dev->buf_len);
+
+       ++dev->buf;
 }
 
-/*
- * Poll the i2c status register until the specified bit is set.
- * Returns 0 if timed out (100 msec).
- */
-static short at91_poll_status(unsigned long bit)
+static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
 {
-       int loop_cntr = 10000;
+       if (dev->buf_len <= 0)
+               return;
+
+       *dev->buf = at91_twi_read(dev, AT91_TWI_RHR) & 0xff;
+       --dev->buf_len;
+
+       /* handle I2C_SMBUS_BLOCK_DATA */
+       if (unlikely(dev->msg->flags & I2C_M_RECV_LEN)) {
+               dev->msg->flags &= ~I2C_M_RECV_LEN;
+               dev->buf_len += *dev->buf;
+               dev->msg->len = dev->buf_len + 1;
+               dev_dbg(dev->dev, "received block length %d\n", dev->buf_len);
+       }
+
+       /* send stop if second but last byte has been read */
+       if (dev->buf_len == 1)
+               at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
 
-       do {
-               udelay(10);
-       } while (!(at91_twi_read(AT91_TWI_SR) & bit) && (--loop_cntr > 0));
+       dev_dbg(dev->dev, "read 0x%x, to go %d\n", *dev->buf, dev->buf_len);
 
-       return (loop_cntr > 0);
+       ++dev->buf;
 }
 
-static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
+static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
 {
-       /* Send Start */
-       at91_twi_write(AT91_TWI_CR, AT91_TWI_START);
-
-       /* Read data */
-       while (length--) {
-               if (!length)    /* need to send Stop before reading last byte */
-                       at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP);
-               if (!at91_poll_status(AT91_TWI_RXRDY)) {
-                       dev_dbg(&adap->dev, "RXRDY timeout\n");
-                       return -ETIMEDOUT;
-               }
-               *buf++ = (at91_twi_read(AT91_TWI_RHR) & 0xff);
+       struct at91_twi_dev *dev = dev_id;
+       const unsigned status = at91_twi_read(dev, AT91_TWI_SR);
+       const unsigned irqstatus = status & at91_twi_read(dev, AT91_TWI_IMR);
+
+       if (!irqstatus)
+               return IRQ_NONE;
+       else if (irqstatus & AT91_TWI_RXRDY)
+               at91_twi_read_next_byte(dev);
+       else if (irqstatus & AT91_TWI_TXRDY)
+               at91_twi_write_next_byte(dev);
+
+       /* catch error flags */
+       dev->transfer_status |= status;
+
+       if (irqstatus & AT91_TWI_TXCOMP) {
+               at91_disable_twi_interrupts(dev);
+               complete(&dev->cmd_complete);
        }
 
-       return 0;
+       return IRQ_HANDLED;
 }
 
-static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length)
+static int at91_do_twi_transfer(struct at91_twi_dev *dev)
 {
-       /* Load first byte into transmitter */
-       at91_twi_write(AT91_TWI_THR, *buf++);
+       int ret;
+       bool has_unre_flag = dev->pdata->has_unre_flag;
 
-       /* Send Start */
-       at91_twi_write(AT91_TWI_CR, AT91_TWI_START);
+       dev_dbg(dev->dev, "transfer: %s %d bytes.\n",
+               (dev->msg->flags & I2C_M_RD) ? "read" : "write", dev->buf_len);
 
-       do {
-               if (!at91_poll_status(AT91_TWI_TXRDY)) {
-                       dev_dbg(&adap->dev, "TXRDY timeout\n");
-                       return -ETIMEDOUT;
-               }
+       INIT_COMPLETION(dev->cmd_complete);
+       dev->transfer_status = 0;
+       if (dev->msg->flags & I2C_M_RD) {
+               unsigned start_flags = AT91_TWI_START;
 
-               length--;       /* byte was transmitted */
+               if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) {
+                       dev_err(dev->dev, "RXRDY still set!");
+                       at91_twi_read(dev, AT91_TWI_RHR);
+               }
 
-               if (length > 0)         /* more data to send? */
-                       at91_twi_write(AT91_TWI_THR, *buf++);
-       } while (length);
+               /* if only one byte is to be read, immediately stop transfer */
+               if (dev->buf_len <= 1 && !(dev->msg->flags & I2C_M_RECV_LEN))
+                       start_flags |= AT91_TWI_STOP;
+               at91_twi_write(dev, AT91_TWI_CR, start_flags);
+               at91_twi_write(dev, AT91_TWI_IER,
+                              AT91_TWI_TXCOMP | AT91_TWI_RXRDY);
+       } else {
+               at91_twi_write_next_byte(dev);
+               at91_twi_write(dev, AT91_TWI_IER,
+                              AT91_TWI_TXCOMP | AT91_TWI_TXRDY);
+       }
 
-       /* Send Stop */
-       at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP);
+       ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
+                                                       dev->adapter.timeout);
+       if (ret == 0) {
+               dev_err(dev->dev, "controller timed out\n");
+               at91_init_twi_bus(dev);
+               return -ETIMEDOUT;
+       }
+       if (dev->transfer_status & AT91_TWI_NACK) {
+               dev_dbg(dev->dev, "received nack\n");
+               return -EREMOTEIO;
+       }
+       if (dev->transfer_status & AT91_TWI_OVRE) {
+               dev_err(dev->dev, "overrun while reading\n");
+               return -EIO;
+       }
+       if (has_unre_flag && dev->transfer_status & AT91_TWI_UNRE) {
+               dev_err(dev->dev, "underrun while writing\n");
+               return -EIO;
+       }
+       dev_dbg(dev->dev, "transfer complete\n");
 
        return 0;
 }
 
-/*
- * Generic i2c master transfer entrypoint.
- *
- * Note: We do not use Atmel's feature of storing the "internal device address".
- * Instead the "internal device address" has to be written using a separate
- * i2c message.
- * http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2004-September/024411.html
- */
-static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num)
+static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
 {
-       int i, ret;
+       struct at91_twi_dev *dev = i2c_get_adapdata(adap);
+       int ret;
+       unsigned int_addr_flag = 0;
+       struct i2c_msg *m_start = msg;
 
        dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num);
 
-       for (i = 0; i < num; i++) {
-               dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
-                       pmsg->flags & I2C_M_RD ? "read" : "writ",
-                       pmsg->len, pmsg->len > 1 ? "s" : "",
-                       pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr);
-
-               at91_twi_write(AT91_TWI_MMR, (pmsg->addr << 16)
-                       | ((pmsg->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0));
-
-               if (pmsg->len && pmsg->buf) {   /* sanity check */
-                       if (pmsg->flags & I2C_M_RD)
-                               ret = xfer_read(adap, pmsg->buf, pmsg->len);
-                       else
-                               ret = xfer_write(adap, pmsg->buf, pmsg->len);
-
-                       if (ret)
-                               return ret;
-
-                       /* Wait until transfer is finished */
-                       if (!at91_poll_status(AT91_TWI_TXCOMP)) {
-                               dev_dbg(&adap->dev, "TXCOMP timeout\n");
-                               return -ETIMEDOUT;
-                       }
+       /*
+        * The hardware can handle at most two messages concatenated by a
+        * repeated start via it's internal address feature.
+        */
+       if (num > 2) {
+               dev_err(dev->dev,
+                       "cannot handle more than two concatenated messages.\n");
+               return 0;
+       } else if (num == 2) {
+               int internal_address = 0;
+               int i;
+
+               if (msg->flags & I2C_M_RD) {
+                       dev_err(dev->dev, "first transfer must be write.\n");
+                       return -EINVAL;
                }
-               dev_dbg(&adap->dev, "transfer complete\n");
-               pmsg++;         /* next message */
+               if (msg->len > 3) {
+                       dev_err(dev->dev, "first message size must be <= 3.\n");
+                       return -EINVAL;
+               }
+
+               /* 1st msg is put into the internal address, start with 2nd */
+               m_start = &msg[1];
+               for (i = 0; i < msg->len; ++i) {
+                       const unsigned addr = msg->buf[msg->len - 1 - i];
+
+                       internal_address |= addr << (8 * i);
+                       int_addr_flag += AT91_TWI_IADRSZ_1;
+               }
+               at91_twi_write(dev, AT91_TWI_IADR, internal_address);
        }
-       return i;
+
+       at91_twi_write(dev, AT91_TWI_MMR, (m_start->addr << 16) | int_addr_flag
+                      | ((m_start->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0));
+
+       dev->buf_len = m_start->len;
+       dev->buf = m_start->buf;
+       dev->msg = m_start;
+
+       ret = at91_do_twi_transfer(dev);
+
+       return (ret < 0) ? ret : num;
 }
 
-/*
- * Return list of supported functionality.
- */
-static u32 at91_func(struct i2c_adapter *adapter)
+static u32 at91_twi_func(struct i2c_adapter *adapter)
 {
-       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
+               | I2C_FUNC_SMBUS_READ_BLOCK_DATA;
 }
 
-static struct i2c_algorithm at91_algorithm = {
-       .master_xfer    = at91_xfer,
-       .functionality  = at91_func,
+static struct i2c_algorithm at91_twi_algorithm = {
+       .master_xfer    = at91_twi_xfer,
+       .functionality  = at91_twi_func,
 };
 
-/*
- * Main initialization routine.
- */
-static int __devinit at91_i2c_probe(struct platform_device *pdev)
-{
-       struct i2c_adapter *adapter;
-       struct resource *res;
-       int rc;
+static struct at91_twi_pdata at91rm9200_config = {
+       .clk_max_div = 5,
+       .clk_offset = 3,
+       .has_unre_flag = true,
+};
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENXIO;
+static struct at91_twi_pdata at91sam9261_config = {
+       .clk_max_div = 5,
+       .clk_offset = 4,
+       .has_unre_flag = false,
+};
 
-       if (!request_mem_region(res->start, resource_size(res), "at91_i2c"))
-               return -EBUSY;
+static struct at91_twi_pdata at91sam9260_config = {
+       .clk_max_div = 7,
+       .clk_offset = 4,
+       .has_unre_flag = false,
+};
+
+static struct at91_twi_pdata at91sam9g20_config = {
+       .clk_max_div = 7,
+       .clk_offset = 4,
+       .has_unre_flag = false,
+};
+
+static struct at91_twi_pdata at91sam9g10_config = {
+       .clk_max_div = 7,
+       .clk_offset = 4,
+       .has_unre_flag = false,
+};
 
-       twi_base = ioremap(res->start, resource_size(res));
-       if (!twi_base) {
-               rc = -ENOMEM;
-               goto fail0;
+static struct at91_twi_pdata at91sam9x5_config = {
+       .clk_max_div = 7,
+       .clk_offset = 4,
+       .has_unre_flag = false,
+};
+
+static const struct platform_device_id at91_twi_devtypes[] = {
+       {
+               .name = "i2c-at91rm9200",
+               .driver_data = (unsigned long) &at91rm9200_config,
+       }, {
+               .name = "i2c-at91sam9261",
+               .driver_data = (unsigned long) &at91sam9261_config,
+       }, {
+               .name = "i2c-at91sam9260",
+               .driver_data = (unsigned long) &at91sam9260_config,
+       }, {
+               .name = "i2c-at91sam9g20",
+               .driver_data = (unsigned long) &at91sam9g20_config,
+       }, {
+               .name = "i2c-at91sam9g10",
+               .driver_data = (unsigned long) &at91sam9g10_config,
+       }, {
+               /* sentinel */
        }
+};
 
-       twi_clk = clk_get(NULL, "twi_clk");
-       if (IS_ERR(twi_clk)) {
-               dev_err(&pdev->dev, "no clock defined\n");
-               rc = -ENODEV;
-               goto fail1;
+#if defined(CONFIG_OF)
+static const struct of_device_id atmel_twi_dt_ids[] = {
+       {
+               .compatible = "atmel,at91sam9260-i2c",
+               .data = &at91sam9260_config,
+       } , {
+               .compatible = "atmel,at91sam9g20-i2c",
+               .data = &at91sam9g20_config,
+       } , {
+               .compatible = "atmel,at91sam9g10-i2c",
+               .data = &at91sam9g10_config,
+       }, {
+               .compatible = "atmel,at91sam9x5-i2c",
+               .data = &at91sam9x5_config,
+       }, {
+               /* sentinel */
        }
+};
+MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids);
+#else
+#define atmel_twi_dt_ids NULL
+#endif
 
-       adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
-       if (adapter == NULL) {
-               dev_err(&pdev->dev, "can't allocate inteface!\n");
-               rc = -ENOMEM;
-               goto fail2;
+static struct at91_twi_pdata * __devinit at91_twi_get_driver_data(
+                                       struct platform_device *pdev)
+{
+       if (pdev->dev.of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(atmel_twi_dt_ids, pdev->dev.of_node);
+               if (!match)
+                       return NULL;
+               return match->data;
        }
-       snprintf(adapter->name, sizeof(adapter->name), "AT91");
-       adapter->algo = &at91_algorithm;
-       adapter->class = I2C_CLASS_HWMON;
-       adapter->dev.parent = &pdev->dev;
-       /* adapter->id == 0 ... only one TWI controller for now */
+       return (struct at91_twi_pdata *) platform_get_device_id(pdev)->driver_data;
+}
+
+static int __devinit at91_twi_probe(struct platform_device *pdev)
+{
+       struct at91_twi_dev *dev;
+       struct resource *mem;
+       int rc;
+
+       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+       init_completion(&dev->cmd_complete);
+       dev->dev = &pdev->dev;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem)
+               return -ENODEV;
+
+       dev->pdata = at91_twi_get_driver_data(pdev);
+       if (!dev->pdata)
+               return -ENODEV;
 
-       platform_set_drvdata(pdev, adapter);
+       dev->base = devm_request_and_ioremap(&pdev->dev, mem);
+       if (!dev->base)
+               return -EBUSY;
 
-       clk_enable(twi_clk);            /* enable peripheral clock */
-       at91_twi_hwinit();              /* initialize TWI controller */
+       dev->irq = platform_get_irq(pdev, 0);
+       if (dev->irq < 0)
+               return dev->irq;
 
-       rc = i2c_add_numbered_adapter(adapter);
+       rc = devm_request_irq(&pdev->dev, dev->irq, atmel_twi_interrupt, 0,
+                        dev_name(dev->dev), dev);
        if (rc) {
-               dev_err(&pdev->dev, "Adapter %s registration failed\n",
-                               adapter->name);
-               goto fail3;
+               dev_err(dev->dev, "Cannot get irq %d: %d\n", dev->irq, rc);
+               return rc;
        }
 
-       dev_info(&pdev->dev, "AT91 i2c bus driver.\n");
-       return 0;
+       platform_set_drvdata(pdev, dev);
 
-fail3:
-       platform_set_drvdata(pdev, NULL);
-       kfree(adapter);
-       clk_disable(twi_clk);
-fail2:
-       clk_put(twi_clk);
-fail1:
-       iounmap(twi_base);
-fail0:
-       release_mem_region(res->start, resource_size(res));
+       dev->clk = devm_clk_get(dev->dev, NULL);
+       if (IS_ERR(dev->clk)) {
+               dev_err(dev->dev, "no clock defined\n");
+               return -ENODEV;
+       }
+       clk_prepare_enable(dev->clk);
+
+       at91_calc_twi_clock(dev, TWI_CLK_HZ);
+       at91_init_twi_bus(dev);
+
+       snprintf(dev->adapter.name, sizeof(dev->adapter.name), "AT91");
+       i2c_set_adapdata(&dev->adapter, dev);
+       dev->adapter.owner = THIS_MODULE;
+       dev->adapter.class = I2C_CLASS_HWMON;
+       dev->adapter.algo = &at91_twi_algorithm;
+       dev->adapter.dev.parent = dev->dev;
+       dev->adapter.nr = pdev->id;
+       dev->adapter.timeout = AT91_I2C_TIMEOUT;
+       dev->adapter.dev.of_node = pdev->dev.of_node;
+
+       rc = i2c_add_numbered_adapter(&dev->adapter);
+       if (rc) {
+               dev_err(dev->dev, "Adapter %s registration failed\n",
+                       dev->adapter.name);
+               clk_disable_unprepare(dev->clk);
+               return rc;
+       }
 
-       return rc;
+       of_i2c_register_devices(&dev->adapter);
+
+       dev_info(dev->dev, "AT91 i2c bus driver.\n");
+       return 0;
 }
 
-static int __devexit at91_i2c_remove(struct platform_device *pdev)
+static int __devexit at91_twi_remove(struct platform_device *pdev)
 {
-       struct i2c_adapter *adapter = platform_get_drvdata(pdev);
-       struct resource *res;
+       struct at91_twi_dev *dev = platform_get_drvdata(pdev);
        int rc;
 
-       rc = i2c_del_adapter(adapter);
-       platform_set_drvdata(pdev, NULL);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       iounmap(twi_base);
-       release_mem_region(res->start, resource_size(res));
-
-       clk_disable(twi_clk);           /* disable peripheral clock */
-       clk_put(twi_clk);
+       rc = i2c_del_adapter(&dev->adapter);
+       clk_disable_unprepare(dev->clk);
 
        return rc;
 }
 
 #ifdef CONFIG_PM
 
-/* NOTE: could save a few mA by keeping clock off outside of at91_xfer... */
-
-static int at91_i2c_suspend(struct device *dev)
+static int at91_twi_runtime_suspend(struct device *dev)
 {
-       clk_disable(twi_clk);
+       struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
+
+       clk_disable(twi_dev->clk);
+
        return 0;
 }
 
-static int at91_i2c_resume(struct device *dev)
+static int at91_twi_runtime_resume(struct device *dev)
 {
-       return clk_enable(twi_clk);
+       struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
+
+       return clk_enable(twi_dev->clk);
 }
 
-static SIMPLE_DEV_PM_OPS(at91_i2c_pm, at91_i2c_suspend, at91_i2c_resume);
-#define AT91_I2C_PM    (&at91_i2c_pm)
+static const struct dev_pm_ops at91_twi_pm = {
+       .runtime_suspend        = at91_twi_runtime_suspend,
+       .runtime_resume         = at91_twi_runtime_resume,
+};
 
+#define at91_twi_pm_ops (&at91_twi_pm)
 #else
-#define AT91_I2C_PM    NULL
+#define at91_twi_pm_ops NULL
 #endif
 
-static struct platform_driver at91_i2c_driver = {
-       .probe          = at91_i2c_probe,
-       .remove         = __devexit_p(at91_i2c_remove),
+static struct platform_driver at91_twi_driver = {
+       .probe          = at91_twi_probe,
+       .remove         = __devexit_p(at91_twi_remove),
+       .id_table       = at91_twi_devtypes,
        .driver         = {
                .name   = "at91_i2c",
                .owner  = THIS_MODULE,
-               .pm     = AT91_I2C_PM,
+               .of_match_table = atmel_twi_dt_ids,
+               .pm     = at91_twi_pm_ops,
        },
 };
 
-module_platform_driver(at91_i2c_driver);
+static int __init at91_twi_init(void)
+{
+       return platform_driver_register(&at91_twi_driver);
+}
+
+static void __exit at91_twi_exit(void)
+{
+       platform_driver_unregister(&at91_twi_driver);
+}
+
+subsys_initcall(at91_twi_init);
+module_exit(at91_twi_exit);
 
-MODULE_AUTHOR("Rick Bronson");
+MODULE_AUTHOR("Nikolaus Voss <n.voss@weinmann.de>");
 MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:at91_i2c");
index 79a2542d8c41564b1c2b7a337e23a8a0282cda4f..6a0a5531944994803b94cbbe95b8badf7bdbb42c 100644 (file)
@@ -38,6 +38,8 @@
 #include <linux/slab.h>
 #include <linux/cpufreq.h>
 #include <linux/gpio.h>
+#include <linux/of_i2c.h>
+#include <linux/of_device.h>
 
 #include <mach/hardware.h>
 #include <linux/platform_data/i2c-davinci.h>
@@ -114,6 +116,7 @@ struct davinci_i2c_dev {
        struct completion       xfr_complete;
        struct notifier_block   freq_transition;
 #endif
+       struct davinci_i2c_platform_data *pdata;
 };
 
 /* default platform data to use if not supplied in the platform_device */
@@ -155,7 +158,7 @@ static void generic_i2c_clock_pulse(unsigned int scl_pin)
 static void i2c_recover_bus(struct davinci_i2c_dev *dev)
 {
        u32 flag = 0;
-       struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
+       struct davinci_i2c_platform_data *pdata = dev->pdata;
 
        dev_err(dev->dev, "initiating i2c bus recovery\n");
        /* Send NACK to the slave */
@@ -163,8 +166,7 @@ static void i2c_recover_bus(struct davinci_i2c_dev *dev)
        flag |=  DAVINCI_I2C_MDR_NACK;
        /* write the data into mode register */
        davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
-       if (pdata)
-               generic_i2c_clock_pulse(pdata->scl_pin);
+       generic_i2c_clock_pulse(pdata->scl_pin);
        /* Send STOP */
        flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
        flag |= DAVINCI_I2C_MDR_STP;
@@ -187,7 +189,7 @@ static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev,
 
 static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
 {
-       struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
+       struct davinci_i2c_platform_data *pdata = dev->pdata;
        u16 psc;
        u32 clk;
        u32 d;
@@ -235,10 +237,7 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
  */
 static int i2c_davinci_init(struct davinci_i2c_dev *dev)
 {
-       struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
-
-       if (!pdata)
-               pdata = &davinci_i2c_platform_data_default;
+       struct davinci_i2c_platform_data *pdata = dev->pdata;
 
        /* put I2C into reset */
        davinci_i2c_reset_ctrl(dev, 0);
@@ -260,6 +259,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
        dev_dbg(dev->dev, "bus_freq = %dkHz, bus_delay = %d\n",
                pdata->bus_freq, pdata->bus_delay);
 
+
        /* Take the I2C module out of reset: */
        davinci_i2c_reset_ctrl(dev, 1);
 
@@ -308,13 +308,11 @@ static int
 i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
 {
        struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
-       struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
+       struct davinci_i2c_platform_data *pdata = dev->pdata;
        u32 flag;
        u16 w;
        int r;
 
-       if (!pdata)
-               pdata = &davinci_i2c_platform_data_default;
        /* Introduce a delay, required for some boards (e.g Davinci EVM) */
        if (pdata->bus_delay)
                udelay(pdata->bus_delay);
@@ -635,6 +633,12 @@ static struct i2c_algorithm i2c_davinci_algo = {
        .functionality  = i2c_davinci_func,
 };
 
+static const struct of_device_id davinci_i2c_of_match[] = {
+       {.compatible = "ti,davinci-i2c", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, davinci_i2c_of_match);
+
 static int davinci_i2c_probe(struct platform_device *pdev)
 {
        struct davinci_i2c_dev *dev;
@@ -674,14 +678,33 @@ static int davinci_i2c_probe(struct platform_device *pdev)
 #endif
        dev->dev = get_device(&pdev->dev);
        dev->irq = irq->start;
+       dev->pdata = dev->dev->platform_data;
        platform_set_drvdata(pdev, dev);
 
+       if (!dev->pdata && pdev->dev.of_node) {
+               u32 prop;
+
+               dev->pdata = devm_kzalloc(&pdev->dev,
+                       sizeof(struct davinci_i2c_platform_data), GFP_KERNEL);
+               if (!dev->pdata) {
+                       r = -ENOMEM;
+                       goto err_free_mem;
+               }
+               memcpy(dev->pdata, &davinci_i2c_platform_data_default,
+                       sizeof(struct davinci_i2c_platform_data));
+               if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+                       &prop))
+                       dev->pdata->bus_freq = prop / 1000;
+       } else if (!dev->pdata) {
+               dev->pdata = &davinci_i2c_platform_data_default;
+       }
+
        dev->clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(dev->clk)) {
                r = -ENODEV;
                goto err_free_mem;
        }
-       clk_enable(dev->clk);
+       clk_prepare_enable(dev->clk);
 
        dev->base = ioremap(mem->start, resource_size(mem));
        if (!dev->base) {
@@ -711,6 +734,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
        adap->algo = &i2c_davinci_algo;
        adap->dev.parent = &pdev->dev;
        adap->timeout = DAVINCI_I2C_TIMEOUT;
+       adap->dev.of_node = pdev->dev.of_node;
 
        adap->nr = pdev->id;
        r = i2c_add_numbered_adapter(adap);
@@ -718,6 +742,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "failure adding adapter\n");
                goto err_free_irq;
        }
+       of_i2c_register_devices(adap);
 
        return 0;
 
@@ -726,7 +751,7 @@ err_free_irq:
 err_unuse_clocks:
        iounmap(dev->base);
 err_mem_ioremap:
-       clk_disable(dev->clk);
+       clk_disable_unprepare(dev->clk);
        clk_put(dev->clk);
        dev->clk = NULL;
 err_free_mem:
@@ -750,7 +775,7 @@ static int davinci_i2c_remove(struct platform_device *pdev)
        i2c_del_adapter(&dev->adapter);
        put_device(&pdev->dev);
 
-       clk_disable(dev->clk);
+       clk_disable_unprepare(dev->clk);
        clk_put(dev->clk);
        dev->clk = NULL;
 
@@ -772,7 +797,7 @@ static int davinci_i2c_suspend(struct device *dev)
 
        /* put I2C into reset */
        davinci_i2c_reset_ctrl(i2c_dev, 0);
-       clk_disable(i2c_dev->clk);
+       clk_disable_unprepare(i2c_dev->clk);
 
        return 0;
 }
@@ -782,7 +807,7 @@ static int davinci_i2c_resume(struct device *dev)
        struct platform_device *pdev = to_platform_device(dev);
        struct davinci_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
 
-       clk_enable(i2c_dev->clk);
+       clk_prepare_enable(i2c_dev->clk);
        /* take I2C out of reset */
        davinci_i2c_reset_ctrl(i2c_dev, 1);
 
@@ -809,6 +834,7 @@ static struct platform_driver davinci_i2c_driver = {
                .name   = "i2c_davinci",
                .owner  = THIS_MODULE,
                .pm     = davinci_i2c_pm_ops,
+               .of_match_table = of_match_ptr(davinci_i2c_of_match),
        },
 };
 
index b7907ba7448aad13ccaa399ffc8cd34b05e3f48d..2ef162d148cbacbc63269bf89774c81aba34983c 100644 (file)
@@ -272,9 +272,9 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
 
        /* dev_dbg() can't be used, because adapter is not yet registered */
 #ifdef CONFIG_I2C_DEBUG_BUS
-       printk(KERN_DEBUG "I2C: <%s> I2C_CLK=%d, REQ DIV=%d\n",
+       dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n",
                __func__, i2c_clk_rate, div);
-       printk(KERN_DEBUG "I2C: <%s> IFDR[IC]=0x%x, REAL DIV=%d\n",
+       dev_dbg(&i2c_imx->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n",
                __func__, i2c_clk_div[i][1], i2c_clk_div[i][0]);
 #endif
 }
@@ -564,7 +564,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
                resource_size(res), res->start);
        dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n",
                i2c_imx->adapter.name);
-       dev_dbg(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
+       dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
 
        return 0;   /* Return OK */
 }
index 57f7703ce2e8cfbba6af7665b8cfde11e8d0fb9e..ca86430cb4a27e1374841f454d5bb5e70ad18b79 100644 (file)
@@ -576,7 +576,23 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
                            mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
                }
        }
-       mpc_i2c_stop(i2c);
+       mpc_i2c_stop(i2c); /* Initiate STOP */
+       orig_jiffies = jiffies;
+       /* Wait until STOP is seen, allow up to 1 s */
+       while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) {
+               if (time_after(jiffies, orig_jiffies + HZ)) {
+                       u8 status = readb(i2c->base + MPC_I2C_SR);
+
+                       dev_dbg(i2c->dev, "timeout\n");
+                       if ((status & (CSR_MCF | CSR_MBB | CSR_RXAK)) != 0) {
+                               writeb(status & ~CSR_MAL,
+                                      i2c->base + MPC_I2C_SR);
+                               mpc_i2c_fixup(i2c);
+                       }
+                       return -EIO;
+               }
+               cond_resched();
+       }
        return (ret < 0) ? ret : num;
 }
 
index 51f05b8520edb3f95b983d5002859afd386586e4..1f58197062cfe120b8987236044afbeec5e397df 100644 (file)
@@ -7,8 +7,6 @@
  *
  * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
  *
- * TODO: add dma-support if platform-support for it is available
- *
  * 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
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_i2c.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/fsl/mxs-dma.h>
 
 #define DRIVER_NAME "mxs-i2c"
 
+static bool use_pioqueue;
+module_param(use_pioqueue, bool, 0);
+MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
+
 #define MXS_I2C_CTRL0          (0x00)
 #define MXS_I2C_CTRL0_SET      (0x04)
 
@@ -146,6 +151,16 @@ struct mxs_i2c_dev {
        u32 cmd_err;
        struct i2c_adapter adapter;
        const struct mxs_i2c_speed_config *speed;
+
+       /* DMA support components */
+       bool                            dma_mode;
+       int                             dma_channel;
+       struct dma_chan                 *dmach;
+       struct mxs_dma_data             dma_data;
+       uint32_t                        pio_data[2];
+       uint32_t                        addr_data;
+       struct scatterlist              sg_io[2];
+       bool                            dma_read;
 };
 
 static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
@@ -157,7 +172,11 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
        writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
 
        writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
-       writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
+       if (i2c->dma_mode)
+               writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
+                       i2c->regs + MXS_I2C_QUEUECTRL_CLR);
+       else
+               writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
                        i2c->regs + MXS_I2C_QUEUECTRL_SET);
 }
 
@@ -248,6 +267,150 @@ static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len)
        return 0;
 }
 
+static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c)
+{
+       if (i2c->dma_read) {
+               dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
+               dma_unmap_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
+       } else {
+               dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
+       }
+}
+
+static void mxs_i2c_dma_irq_callback(void *param)
+{
+       struct mxs_i2c_dev *i2c = param;
+
+       complete(&i2c->cmd_complete);
+       mxs_i2c_dma_finish(i2c);
+}
+
+static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
+                       struct i2c_msg *msg, uint32_t flags)
+{
+       struct dma_async_tx_descriptor *desc;
+       struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
+
+       if (msg->flags & I2C_M_RD) {
+               i2c->dma_read = 1;
+               i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_READ;
+
+               /*
+                * SELECT command.
+                */
+
+               /* Queue the PIO register write transfer. */
+               i2c->pio_data[0] = MXS_CMD_I2C_SELECT;
+               desc = dmaengine_prep_slave_sg(i2c->dmach,
+                                       (struct scatterlist *)&i2c->pio_data[0],
+                                       1, DMA_TRANS_NONE, 0);
+               if (!desc) {
+                       dev_err(i2c->dev,
+                               "Failed to get PIO reg. write descriptor.\n");
+                       goto select_init_pio_fail;
+               }
+
+               /* Queue the DMA data transfer. */
+               sg_init_one(&i2c->sg_io[0], &i2c->addr_data, 1);
+               dma_map_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
+               desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[0], 1,
+                                       DMA_MEM_TO_DEV,
+                                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               if (!desc) {
+                       dev_err(i2c->dev,
+                               "Failed to get DMA data write descriptor.\n");
+                       goto select_init_dma_fail;
+               }
+
+               /*
+                * READ command.
+                */
+
+               /* Queue the PIO register write transfer. */
+               i2c->pio_data[1] = flags | MXS_CMD_I2C_READ |
+                               MXS_I2C_CTRL0_XFER_COUNT(msg->len);
+               desc = dmaengine_prep_slave_sg(i2c->dmach,
+                                       (struct scatterlist *)&i2c->pio_data[1],
+                                       1, DMA_TRANS_NONE, DMA_PREP_INTERRUPT);
+               if (!desc) {
+                       dev_err(i2c->dev,
+                               "Failed to get PIO reg. write descriptor.\n");
+                       goto select_init_dma_fail;
+               }
+
+               /* Queue the DMA data transfer. */
+               sg_init_one(&i2c->sg_io[1], msg->buf, msg->len);
+               dma_map_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
+               desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[1], 1,
+                                       DMA_DEV_TO_MEM,
+                                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               if (!desc) {
+                       dev_err(i2c->dev,
+                               "Failed to get DMA data write descriptor.\n");
+                       goto read_init_dma_fail;
+               }
+       } else {
+               i2c->dma_read = 0;
+               i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_WRITE;
+
+               /*
+                * WRITE command.
+                */
+
+               /* Queue the PIO register write transfer. */
+               i2c->pio_data[0] = flags | MXS_CMD_I2C_WRITE |
+                               MXS_I2C_CTRL0_XFER_COUNT(msg->len + 1);
+               desc = dmaengine_prep_slave_sg(i2c->dmach,
+                                       (struct scatterlist *)&i2c->pio_data[0],
+                                       1, DMA_TRANS_NONE, 0);
+               if (!desc) {
+                       dev_err(i2c->dev,
+                               "Failed to get PIO reg. write descriptor.\n");
+                       goto write_init_pio_fail;
+               }
+
+               /* Queue the DMA data transfer. */
+               sg_init_table(i2c->sg_io, 2);
+               sg_set_buf(&i2c->sg_io[0], &i2c->addr_data, 1);
+               sg_set_buf(&i2c->sg_io[1], msg->buf, msg->len);
+               dma_map_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
+               desc = dmaengine_prep_slave_sg(i2c->dmach, i2c->sg_io, 2,
+                                       DMA_MEM_TO_DEV,
+                                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               if (!desc) {
+                       dev_err(i2c->dev,
+                               "Failed to get DMA data write descriptor.\n");
+                       goto write_init_dma_fail;
+               }
+       }
+
+       /*
+        * The last descriptor must have this callback,
+        * to finish the DMA transaction.
+        */
+       desc->callback = mxs_i2c_dma_irq_callback;
+       desc->callback_param = i2c;
+
+       /* Start the transfer. */
+       dmaengine_submit(desc);
+       dma_async_issue_pending(i2c->dmach);
+       return 0;
+
+/* Read failpath. */
+read_init_dma_fail:
+       dma_unmap_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
+select_init_dma_fail:
+       dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
+select_init_pio_fail:
+       return -EINVAL;
+
+/* Write failpath. */
+write_init_dma_fail:
+       dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
+write_init_pio_fail:
+       return -EINVAL;
+}
+
 /*
  * Low level master read/write transaction.
  */
@@ -258,6 +421,8 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
        int ret;
        int flags;
 
+       flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0;
+
        dev_dbg(i2c->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
                msg->addr, msg->len, msg->flags, stop);
 
@@ -267,23 +432,29 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
        init_completion(&i2c->cmd_complete);
        i2c->cmd_err = 0;
 
-       flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0;
-
-       if (msg->flags & I2C_M_RD)
-               mxs_i2c_pioq_setup_read(i2c, msg->addr, msg->len, flags);
-       else
-               mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf, msg->len,
-                                       flags);
+       if (i2c->dma_mode) {
+               ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
+               if (ret)
+                       return ret;
+       } else {
+               if (msg->flags & I2C_M_RD) {
+                       mxs_i2c_pioq_setup_read(i2c, msg->addr,
+                                               msg->len, flags);
+               } else {
+                       mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf,
+                                               msg->len, flags);
+               }
 
-       writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
+               writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
                        i2c->regs + MXS_I2C_QUEUECTRL_SET);
+       }
 
        ret = wait_for_completion_timeout(&i2c->cmd_complete,
                                                msecs_to_jiffies(1000));
        if (ret == 0)
                goto timeout;
 
-       if ((!i2c->cmd_err) && (msg->flags & I2C_M_RD)) {
+       if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) {
                ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len);
                if (ret)
                        goto timeout;
@@ -301,6 +472,8 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
 
 timeout:
        dev_dbg(i2c->dev, "Timeout!\n");
+       if (i2c->dma_mode)
+               mxs_i2c_dma_finish(i2c);
        mxs_i2c_reset(i2c);
        return -ETIMEDOUT;
 }
@@ -342,11 +515,13 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
                /* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
                i2c->cmd_err = -EIO;
 
-       is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
-               MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
+       if (!i2c->dma_mode) {
+               is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
+                       MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
 
-       if (is_last_cmd || i2c->cmd_err)
-               complete(&i2c->cmd_complete);
+               if (is_last_cmd || i2c->cmd_err)
+                       complete(&i2c->cmd_complete);
+       }
 
        writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);
 
@@ -358,6 +533,21 @@ static const struct i2c_algorithm mxs_i2c_algo = {
        .functionality = mxs_i2c_func,
 };
 
+static bool mxs_i2c_dma_filter(struct dma_chan *chan, void *param)
+{
+       struct mxs_i2c_dev *i2c = param;
+
+       if (!mxs_dma_is_apbx(chan))
+               return false;
+
+       if (chan->chan_id != i2c->dma_channel)
+               return false;
+
+       chan->private = &i2c->dma_data;
+
+       return true;
+}
+
 static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
 {
        uint32_t speed;
@@ -365,6 +555,26 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
        struct device_node *node = dev->of_node;
        int ret;
 
+       /*
+        * The MXS I2C DMA mode is prefered and enabled by default.
+        * The PIO mode is still supported, but should be used only
+        * for debuging purposes etc.
+        */
+       i2c->dma_mode = !use_pioqueue;
+       if (!i2c->dma_mode)
+               dev_info(dev, "Using PIOQUEUE mode for I2C transfers!\n");
+
+       /*
+        * TODO: This is a temporary solution and should be changed
+        * to use generic DMA binding later when the helpers get in.
+        */
+       ret = of_property_read_u32(node, "fsl,i2c-dma-channel",
+                                  &i2c->dma_channel);
+       if (ret) {
+               dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n");
+               i2c->dma_mode = 0;
+       }
+
        ret = of_property_read_u32(node, "clock-frequency", &speed);
        if (ret)
                dev_warn(dev, "No I2C speed selected, using 100kHz\n");
@@ -384,7 +594,8 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
        struct pinctrl *pinctrl;
        struct resource *res;
        resource_size_t res_size;
-       int err, irq;
+       int err, irq, dmairq;
+       dma_cap_mask_t mask;
 
        pinctrl = devm_pinctrl_get_select_default(dev);
        if (IS_ERR(pinctrl))
@@ -395,7 +606,10 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
+       irq = platform_get_irq(pdev, 0);
+       dmairq = platform_get_irq(pdev, 1);
+
+       if (!res || irq < 0 || dmairq < 0)
                return -ENOENT;
 
        res_size = resource_size(res);
@@ -406,10 +620,6 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
        if (!i2c->regs)
                return -EBUSY;
 
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
-
        err = devm_request_irq(dev, irq, mxs_i2c_isr, 0, dev_name(dev), i2c);
        if (err)
                return err;
@@ -423,6 +633,18 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
                        return err;
        }
 
+       /* Setup the DMA */
+       if (i2c->dma_mode) {
+               dma_cap_zero(mask);
+               dma_cap_set(DMA_SLAVE, mask);
+               i2c->dma_data.chan_irq = dmairq;
+               i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
+               if (!i2c->dmach) {
+                       dev_err(dev, "Failed to request dma\n");
+                       return -ENODEV;
+               }
+       }
+
        platform_set_drvdata(pdev, i2c);
 
        /* Do reset to enforce correct startup after pinmuxing */
@@ -458,6 +680,9 @@ static int __devexit mxs_i2c_remove(struct platform_device *pdev)
        if (ret)
                return -EBUSY;
 
+       if (i2c->dmach)
+               dma_release_channel(i2c->dmach);
+
        writel(MXS_I2C_CTRL0_SFTRST, i2c->regs + MXS_I2C_CTRL0_SET);
 
        platform_set_drvdata(pdev, NULL);
index 61b00edacb08179894c83b91d1f0cbe39a768b37..698d7acb0f083c10ea2028ad895e58043105f44e 100644 (file)
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/platform_data/i2c-nomadik.h>
+#include <linux/of.h>
+#include <linux/of_i2c.h>
 
 #define DRIVER_NAME "nmk-i2c"
 
@@ -146,7 +147,6 @@ struct i2c_nmk_client {
  * @stop: stop condition.
  * @xfer_complete: acknowledge completion for a I2C message.
  * @result: controller propogated result.
- * @regulator: pointer to i2c regulator.
  * @busy: Busy doing transfer.
  */
 struct nmk_i2c_dev {
@@ -160,7 +160,6 @@ struct nmk_i2c_dev {
        int                             stop;
        struct completion               xfer_complete;
        int                             result;
-       struct regulator                *regulator;
        bool                            busy;
 };
 
@@ -643,8 +642,6 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
 
        dev->busy = true;
 
-       if (dev->regulator)
-               regulator_enable(dev->regulator);
        pm_runtime_get_sync(&dev->adev->dev);
 
        clk_enable(dev->clk);
@@ -676,8 +673,6 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
 out:
        clk_disable(dev->clk);
        pm_runtime_put_sync(&dev->adev->dev);
-       if (dev->regulator)
-               regulator_disable(dev->regulator);
 
        dev->busy = false;
 
@@ -920,18 +915,42 @@ static struct nmk_i2c_controller u8500_i2c = {
        .sm             = I2C_FREQ_MODE_FAST,
 };
 
+static void nmk_i2c_of_probe(struct device_node *np,
+                       struct nmk_i2c_controller *pdata)
+{
+       of_property_read_u32(np, "clock-frequency", &pdata->clk_freq);
+
+       /* This driver only supports 'standard' and 'fast' modes of operation. */
+       if (pdata->clk_freq <= 100000)
+               pdata->sm = I2C_FREQ_MODE_STANDARD;
+       else
+               pdata->sm = I2C_FREQ_MODE_FAST;
+}
+
 static atomic_t adapter_id = ATOMIC_INIT(0);
 
 static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
 {
        int ret = 0;
        struct nmk_i2c_controller *pdata = adev->dev.platform_data;
+       struct device_node *np = adev->dev.of_node;
        struct nmk_i2c_dev      *dev;
        struct i2c_adapter *adap;
 
-       if (!pdata)
-               /* No i2c configuration found, using the default. */
-               pdata = &u8500_i2c;
+       if (!pdata) {
+               if (np) {
+                       pdata = devm_kzalloc(&adev->dev, sizeof(*pdata), GFP_KERNEL);
+                       if (!pdata) {
+                               ret = -ENOMEM;
+                               goto err_no_mem;
+                       }
+                       /* Provide the default configuration as a base. */
+                       memcpy(pdata, &u8500_i2c, sizeof(struct nmk_i2c_controller));
+                       nmk_i2c_of_probe(np, pdata);
+               } else
+                       /* No i2c configuration found, using the default. */
+                       pdata = &u8500_i2c;
+       }
 
        dev = kzalloc(sizeof(struct nmk_i2c_dev), GFP_KERNEL);
        if (!dev) {
@@ -957,12 +976,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
                goto err_irq;
        }
 
-       dev->regulator = regulator_get(&adev->dev, "v-i2c");
-       if (IS_ERR(dev->regulator)) {
-               dev_warn(&adev->dev, "could not get i2c regulator\n");
-               dev->regulator = NULL;
-       }
-
        pm_suspend_ignore_children(&adev->dev, true);
 
        dev->clk = clk_get(&adev->dev, NULL);
@@ -973,6 +986,7 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
        }
 
        adap = &dev->adap;
+       adap->dev.of_node = np;
        adap->dev.parent = &adev->dev;
        adap->owner     = THIS_MODULE;
        adap->class     = I2C_CLASS_HWMON | I2C_CLASS_SPD;
@@ -1002,6 +1016,8 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
                goto err_add_adap;
        }
 
+       of_i2c_register_devices(adap);
+
        pm_runtime_put(&adev->dev);
 
        return 0;
@@ -1009,8 +1025,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
  err_add_adap:
        clk_put(dev->clk);
  err_no_clk:
-       if (dev->regulator)
-               regulator_put(dev->regulator);
        free_irq(dev->irq, dev);
  err_irq:
        iounmap(dev->virtbase);
@@ -1038,8 +1052,6 @@ static int nmk_i2c_remove(struct amba_device *adev)
        if (res)
                release_mem_region(res->start, resource_size(res));
        clk_put(dev->clk);
-       if (dev->regulator)
-               regulator_put(dev->regulator);
        pm_runtime_disable(&adev->dev);
        amba_set_drvdata(adev, NULL);
        kfree(dev);
index a0e49f6aaf96eaa81ac712a4a279fafbdf13af95..db31eaed6ea59b32083df49f757c1fc949c60303 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/slab.h>
 #include <linux/i2c-omap.h>
 #include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
 
 /* I2C controller revisions */
 #define OMAP_I2C_OMAP1_REV_2           0x20
@@ -55,6 +56,9 @@
 /* timeout waiting for the controller to respond */
 #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
 
+/* timeout for pm runtime autosuspend */
+#define OMAP_I2C_PM_TIMEOUT            1000    /* ms */
+
 /* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
 enum {
        OMAP_I2C_REV_REG = 0,
@@ -176,15 +180,15 @@ enum {
 #define I2C_OMAP_ERRATA_I462           (1 << 1)
 
 struct omap_i2c_dev {
+       spinlock_t              lock;           /* IRQ synchronization */
        struct device           *dev;
        void __iomem            *base;          /* virtual */
        int                     irq;
        int                     reg_shift;      /* bit shift for I2C register addresses */
        struct completion       cmd_complete;
        struct resource         *ioarea;
-       u32                     latency;        /* maximum mpu wkup latency */
-       void                    (*set_mpu_wkup_lat)(struct device *dev,
-                                                   long latency);
+       u32                     latency;        /* maximum MPU wkup latency */
+       struct pm_qos_request   pm_qos_request;
        u32                     speed;          /* Speed of bus in kHz */
        u32                     dtrev;          /* extra revision from DT */
        u32                     flags;
@@ -193,12 +197,14 @@ struct omap_i2c_dev {
        u8                      *regs;
        size_t                  buf_len;
        struct i2c_adapter      adapter;
+       u8                      threshold;
        u8                      fifo_size;      /* use as flag and value
                                                 * fifo_size==0 implies no fifo
                                                 * if set, should be trsh+1
                                                 */
        u8                      rev;
        unsigned                b_hw:1;         /* bad h/w fixes */
+       unsigned                receiver:1;     /* true when we're in receiver mode */
        u16                     iestate;        /* Saved interrupt register */
        u16                     pscstate;
        u16                     scllstate;
@@ -417,13 +423,6 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
        omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
        omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
 
-       if (dev->fifo_size) {
-               /* Note: setup required fifo size - 1. RTRSH and XTRSH */
-               buf = (dev->fifo_size - 1) << 8 | OMAP_I2C_BUF_RXFIF_CLR |
-                       (dev->fifo_size - 1) | OMAP_I2C_BUF_TXFIF_CLR;
-               omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf);
-       }
-
        /* Take the I2C module out of reset: */
        omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
 
@@ -461,6 +460,43 @@ static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)
        return 0;
 }
 
+static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx)
+{
+       u16             buf;
+
+       if (dev->flags & OMAP_I2C_FLAG_NO_FIFO)
+               return;
+
+       /*
+        * Set up notification threshold based on message size. We're doing
+        * this to try and avoid draining feature as much as possible. Whenever
+        * we have big messages to transfer (bigger than our total fifo size)
+        * then we might use draining feature to transfer the remaining bytes.
+        */
+
+       dev->threshold = clamp(size, (u8) 1, dev->fifo_size);
+
+       buf = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG);
+
+       if (is_rx) {
+               /* Clear RX Threshold */
+               buf &= ~(0x3f << 8);
+               buf |= ((dev->threshold - 1) << 8) | OMAP_I2C_BUF_RXFIF_CLR;
+       } else {
+               /* Clear TX Threshold */
+               buf &= ~0x3f;
+               buf |= (dev->threshold - 1) | OMAP_I2C_BUF_TXFIF_CLR;
+       }
+
+       omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf);
+
+       if (dev->rev < OMAP_I2C_REV_ON_3630_4430)
+               dev->b_hw = 1; /* Enable hardware fixes */
+
+       /* calculate wakeup latency constraint for MPU */
+       dev->latency = (1000000 * dev->threshold) / (1000 * dev->speed / 8);
+}
+
 /*
  * Low level master read/write transaction.
  */
@@ -477,6 +513,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
        if (msg->len == 0)
                return -EINVAL;
 
+       dev->receiver = !!(msg->flags & I2C_M_RD);
+       omap_i2c_resize_fifo(dev, msg->len, dev->receiver);
+
        omap_i2c_write_reg(dev, OMAP_I2C_SA_REG, msg->addr);
 
        /* REVISIT: Could the STB bit of I2C_CON be used with probing? */
@@ -590,8 +629,16 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        if (r < 0)
                goto out;
 
-       if (dev->set_mpu_wkup_lat != NULL)
-               dev->set_mpu_wkup_lat(dev->dev, dev->latency);
+       /*
+        * When waiting for completion of a i2c transfer, we need to
+        * set a wake up latency constraint for the MPU. This is to
+        * ensure quick enough wakeup from idle, when transfer
+        * completes.
+        */
+       if (dev->latency)
+               pm_qos_add_request(&dev->pm_qos_request,
+                                  PM_QOS_CPU_DMA_LATENCY,
+                                  dev->latency);
 
        for (i = 0; i < num; i++) {
                r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
@@ -599,15 +646,16 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
                        break;
        }
 
-       if (dev->set_mpu_wkup_lat != NULL)
-               dev->set_mpu_wkup_lat(dev->dev, -1);
+       if (dev->latency)
+               pm_qos_remove_request(&dev->pm_qos_request);
 
        if (r == 0)
                r = num;
 
        omap_i2c_wait_for_bb(dev);
 out:
-       pm_runtime_put(dev->dev);
+       pm_runtime_mark_last_busy(dev->dev);
+       pm_runtime_put_autosuspend(dev->dev);
        return r;
 }
 
@@ -725,186 +773,252 @@ omap_i2c_omap1_isr(int this_irq, void *dev_id)
  * data to DATA_REG. Otherwise some data bytes can be lost while transferring
  * them from the memory to the I2C interface.
  */
-static int errata_omap3_i462(struct omap_i2c_dev *dev, u16 *stat, int *err)
+static int errata_omap3_i462(struct omap_i2c_dev *dev)
 {
        unsigned long timeout = 10000;
+       u16 stat;
 
-       while (--timeout && !(*stat & OMAP_I2C_STAT_XUDF)) {
-               if (*stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) {
-                       omap_i2c_ack_stat(dev, *stat & (OMAP_I2C_STAT_XRDY |
+       do {
+               stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+               if (stat & OMAP_I2C_STAT_XUDF)
+                       break;
+
+               if (stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) {
+                       omap_i2c_ack_stat(dev, (OMAP_I2C_STAT_XRDY |
                                                        OMAP_I2C_STAT_XDR));
-                       return -ETIMEDOUT;
+                       if (stat & OMAP_I2C_STAT_NACK) {
+                               dev->cmd_err |= OMAP_I2C_STAT_NACK;
+                               omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
+                       }
+
+                       if (stat & OMAP_I2C_STAT_AL) {
+                               dev_err(dev->dev, "Arbitration lost\n");
+                               dev->cmd_err |= OMAP_I2C_STAT_AL;
+                               omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
+                       }
+
+                       return -EIO;
                }
 
                cpu_relax();
-               *stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
-       }
+       } while (--timeout);
 
        if (!timeout) {
                dev_err(dev->dev, "timeout waiting on XUDF bit\n");
                return 0;
        }
 
-       *err |= OMAP_I2C_STAT_XUDF;
        return 0;
 }
 
+static void omap_i2c_receive_data(struct omap_i2c_dev *dev, u8 num_bytes,
+               bool is_rdr)
+{
+       u16             w;
+
+       while (num_bytes--) {
+               w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
+               *dev->buf++ = w;
+               dev->buf_len--;
+
+               /*
+                * Data reg in 2430, omap3 and
+                * omap4 is 8 bit wide
+                */
+               if (dev->flags & OMAP_I2C_FLAG_16BIT_DATA_REG) {
+                       *dev->buf++ = w >> 8;
+                       dev->buf_len--;
+               }
+       }
+}
+
+static int omap_i2c_transmit_data(struct omap_i2c_dev *dev, u8 num_bytes,
+               bool is_xdr)
+{
+       u16             w;
+
+       while (num_bytes--) {
+               w = *dev->buf++;
+               dev->buf_len--;
+
+               /*
+                * Data reg in 2430, omap3 and
+                * omap4 is 8 bit wide
+                */
+               if (dev->flags & OMAP_I2C_FLAG_16BIT_DATA_REG) {
+                       w |= *dev->buf++ << 8;
+                       dev->buf_len--;
+               }
+
+               if (dev->errata & I2C_OMAP_ERRATA_I462) {
+                       int ret;
+
+                       ret = errata_omap3_i462(dev);
+                       if (ret < 0)
+                               return ret;
+               }
+
+               omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+       }
+
+       return 0;
+}
+
+static irqreturn_t
+omap_i2c_isr(int irq, void *dev_id)
+{
+       struct omap_i2c_dev *dev = dev_id;
+       irqreturn_t ret = IRQ_HANDLED;
+       u16 mask;
+       u16 stat;
+
+       spin_lock(&dev->lock);
+       mask = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
+       stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+
+       if (stat & mask)
+               ret = IRQ_WAKE_THREAD;
+
+       spin_unlock(&dev->lock);
+
+       return ret;
+}
+
 static irqreturn_t
-omap_i2c_isr(int this_irq, void *dev_id)
+omap_i2c_isr_thread(int this_irq, void *dev_id)
 {
        struct omap_i2c_dev *dev = dev_id;
+       unsigned long flags;
        u16 bits;
-       u16 stat, w;
-       int err, count = 0;
+       u16 stat;
+       int err = 0, count = 0;
+
+       spin_lock_irqsave(&dev->lock, flags);
+       do {
+               bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
+               stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+               stat &= bits;
+
+               /* If we're in receiver mode, ignore XDR/XRDY */
+               if (dev->receiver)
+                       stat &= ~(OMAP_I2C_STAT_XDR | OMAP_I2C_STAT_XRDY);
+               else
+                       stat &= ~(OMAP_I2C_STAT_RDR | OMAP_I2C_STAT_RRDY);
 
-       if (pm_runtime_suspended(dev->dev))
-               return IRQ_NONE;
+               if (!stat) {
+                       /* my work here is done */
+                       goto out;
+               }
 
-       bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
-       while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG))) & bits) {
                dev_dbg(dev->dev, "IRQ (ISR = 0x%04x)\n", stat);
                if (count++ == 100) {
                        dev_warn(dev->dev, "Too much work in one IRQ\n");
                        break;
                }
 
-               err = 0;
-complete:
-               /*
-                * Ack the stat in one go, but [R/X]DR and [R/X]RDY should be
-                * acked after the data operation is complete.
-                * Ref: TRM SWPU114Q Figure 18-31
-                */
-               omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat &
-                               ~(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
-                               OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
-
-               if (stat & OMAP_I2C_STAT_NACK)
+               if (stat & OMAP_I2C_STAT_NACK) {
                        err |= OMAP_I2C_STAT_NACK;
+                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
+                       break;
+               }
 
                if (stat & OMAP_I2C_STAT_AL) {
                        dev_err(dev->dev, "Arbitration lost\n");
                        err |= OMAP_I2C_STAT_AL;
+                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL);
+                       break;
                }
+
                /*
                 * ProDB0017052: Clear ARDY bit twice
                 */
                if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
                                        OMAP_I2C_STAT_AL)) {
-                       omap_i2c_ack_stat(dev, stat &
-                               (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
-                               OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR |
-                               OMAP_I2C_STAT_ARDY));
-                       omap_i2c_complete_cmd(dev, err);
-                       return IRQ_HANDLED;
+                       omap_i2c_ack_stat(dev, (OMAP_I2C_STAT_RRDY |
+                                               OMAP_I2C_STAT_RDR |
+                                               OMAP_I2C_STAT_XRDY |
+                                               OMAP_I2C_STAT_XDR |
+                                               OMAP_I2C_STAT_ARDY));
+                       break;
                }
-               if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) {
+
+               if (stat & OMAP_I2C_STAT_RDR) {
                        u8 num_bytes = 1;
 
+                       if (dev->fifo_size)
+                               num_bytes = dev->buf_len;
+
+                       omap_i2c_receive_data(dev, num_bytes, true);
+
                        if (dev->errata & I2C_OMAP_ERRATA_I207)
                                i2c_omap_errata_i207(dev, stat);
 
-                       if (dev->fifo_size) {
-                               if (stat & OMAP_I2C_STAT_RRDY)
-                                       num_bytes = dev->fifo_size;
-                               else    /* read RXSTAT on RDR interrupt */
-                                       num_bytes = (omap_i2c_read_reg(dev,
-                                                       OMAP_I2C_BUFSTAT_REG)
-                                                       >> 8) & 0x3F;
-                       }
-                       while (num_bytes) {
-                               num_bytes--;
-                               w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
-                               if (dev->buf_len) {
-                                       *dev->buf++ = w;
-                                       dev->buf_len--;
-                                       /*
-                                        * Data reg in 2430, omap3 and
-                                        * omap4 is 8 bit wide
-                                        */
-                                       if (dev->flags &
-                                                OMAP_I2C_FLAG_16BIT_DATA_REG) {
-                                               if (dev->buf_len) {
-                                                       *dev->buf++ = w >> 8;
-                                                       dev->buf_len--;
-                                               }
-                                       }
-                               } else {
-                                       if (stat & OMAP_I2C_STAT_RRDY)
-                                               dev_err(dev->dev,
-                                                       "RRDY IRQ while no data"
-                                                               " requested\n");
-                                       if (stat & OMAP_I2C_STAT_RDR)
-                                               dev_err(dev->dev,
-                                                       "RDR IRQ while no data"
-                                                               " requested\n");
-                                       break;
-                               }
-                       }
-                       omap_i2c_ack_stat(dev,
-                               stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR));
+                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR);
+                       break;
+               }
+
+               if (stat & OMAP_I2C_STAT_RRDY) {
+                       u8 num_bytes = 1;
+
+                       if (dev->threshold)
+                               num_bytes = dev->threshold;
+
+                       omap_i2c_receive_data(dev, num_bytes, false);
+                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
                        continue;
                }
-               if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
+
+               if (stat & OMAP_I2C_STAT_XDR) {
                        u8 num_bytes = 1;
-                       if (dev->fifo_size) {
-                               if (stat & OMAP_I2C_STAT_XRDY)
-                                       num_bytes = dev->fifo_size;
-                               else    /* read TXSTAT on XDR interrupt */
-                                       num_bytes = omap_i2c_read_reg(dev,
-                                                       OMAP_I2C_BUFSTAT_REG)
-                                                       & 0x3F;
-                       }
-                       while (num_bytes) {
-                               num_bytes--;
-                               w = 0;
-                               if (dev->buf_len) {
-                                       w = *dev->buf++;
-                                       dev->buf_len--;
-                                       /*
-                                        * Data reg in 2430, omap3 and
-                                        * omap4 is 8 bit wide
-                                        */
-                                       if (dev->flags &
-                                                OMAP_I2C_FLAG_16BIT_DATA_REG) {
-                                               if (dev->buf_len) {
-                                                       w |= *dev->buf++ << 8;
-                                                       dev->buf_len--;
-                                               }
-                                       }
-                               } else {
-                                       if (stat & OMAP_I2C_STAT_XRDY)
-                                               dev_err(dev->dev,
-                                                       "XRDY IRQ while no "
-                                                       "data to send\n");
-                                       if (stat & OMAP_I2C_STAT_XDR)
-                                               dev_err(dev->dev,
-                                                       "XDR IRQ while no "
-                                                       "data to send\n");
-                                       break;
-                               }
-
-                               if ((dev->errata & I2C_OMAP_ERRATA_I462) &&
-                                   errata_omap3_i462(dev, &stat, &err))
-                                       goto complete;
-
-                               omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
-                       }
-                       omap_i2c_ack_stat(dev,
-                               stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
+                       int ret;
+
+                       if (dev->fifo_size)
+                               num_bytes = dev->buf_len;
+
+                       ret = omap_i2c_transmit_data(dev, num_bytes, true);
+                       if (ret < 0)
+                               break;
+
+                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XDR);
+                       break;
+               }
+
+               if (stat & OMAP_I2C_STAT_XRDY) {
+                       u8 num_bytes = 1;
+                       int ret;
+
+                       if (dev->threshold)
+                               num_bytes = dev->threshold;
+
+                       ret = omap_i2c_transmit_data(dev, num_bytes, false);
+                       if (ret < 0)
+                               break;
+
+                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY);
                        continue;
                }
+
                if (stat & OMAP_I2C_STAT_ROVR) {
                        dev_err(dev->dev, "Receive overrun\n");
-                       dev->cmd_err |= OMAP_I2C_STAT_ROVR;
+                       err |= OMAP_I2C_STAT_ROVR;
+                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_ROVR);
+                       break;
                }
+
                if (stat & OMAP_I2C_STAT_XUDF) {
                        dev_err(dev->dev, "Transmit underflow\n");
-                       dev->cmd_err |= OMAP_I2C_STAT_XUDF;
+                       err |= OMAP_I2C_STAT_XUDF;
+                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XUDF);
+                       break;
                }
-       }
+       } while (stat);
+
+       omap_i2c_complete_cmd(dev, err);
+
+out:
+       spin_unlock_irqrestore(&dev->lock, flags);
 
-       return count ? IRQ_HANDLED : IRQ_NONE;
+       return IRQ_HANDLED;
 }
 
 static const struct i2c_algorithm omap_i2c_algo = {
@@ -943,12 +1057,12 @@ omap_i2c_probe(struct platform_device *pdev)
 {
        struct omap_i2c_dev     *dev;
        struct i2c_adapter      *adap;
-       struct resource         *mem, *irq, *ioarea;
+       struct resource         *mem;
        const struct omap_i2c_bus_platform_data *pdata =
                pdev->dev.platform_data;
        struct device_node      *node = pdev->dev.of_node;
        const struct of_device_id *match;
-       irq_handler_t isr;
+       int irq;
        int r;
 
        /* NOTE: driver uses the static register mapping */
@@ -957,23 +1071,23 @@ omap_i2c_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "no mem resource?\n");
                return -ENODEV;
        }
-       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!irq) {
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
                dev_err(&pdev->dev, "no irq resource?\n");
-               return -ENODEV;
+               return irq;
        }
 
-       ioarea = request_mem_region(mem->start, resource_size(mem),
-                       pdev->name);
-       if (!ioarea) {
-               dev_err(&pdev->dev, "I2C region already claimed\n");
-               return -EBUSY;
+       dev = devm_kzalloc(&pdev->dev, sizeof(struct omap_i2c_dev), GFP_KERNEL);
+       if (!dev) {
+               dev_err(&pdev->dev, "Menory allocation failed\n");
+               return -ENOMEM;
        }
 
-       dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL);
-       if (!dev) {
-               r = -ENOMEM;
-               goto err_release_region;
+       dev->base = devm_request_and_ioremap(&pdev->dev, mem);
+       if (!dev->base) {
+               dev_err(&pdev->dev, "I2C region already claimed\n");
+               return -ENOMEM;
        }
 
        match = of_match_device(of_match_ptr(omap_i2c_of_match), &pdev->dev);
@@ -990,17 +1104,13 @@ omap_i2c_probe(struct platform_device *pdev)
        } else if (pdata != NULL) {
                dev->speed = pdata->clkrate;
                dev->flags = pdata->flags;
-               dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
                dev->dtrev = pdata->rev;
        }
 
        dev->dev = &pdev->dev;
-       dev->irq = irq->start;
-       dev->base = ioremap(mem->start, resource_size(mem));
-       if (!dev->base) {
-               r = -ENOMEM;
-               goto err_free_mem;
-       }
+       dev->irq = irq;
+
+       spin_lock_init(&dev->lock);
 
        platform_set_drvdata(pdev, dev);
        init_completion(&dev->cmd_complete);
@@ -1013,6 +1123,9 @@ omap_i2c_probe(struct platform_device *pdev)
                dev->regs = (u8 *)reg_map_ip_v1;
 
        pm_runtime_enable(dev->dev);
+       pm_runtime_set_autosuspend_delay(dev->dev, OMAP_I2C_PM_TIMEOUT);
+       pm_runtime_use_autosuspend(dev->dev);
+
        r = pm_runtime_get_sync(dev->dev);
        if (IS_ERR_VALUE(r))
                goto err_free_mem;
@@ -1042,32 +1155,31 @@ omap_i2c_probe(struct platform_device *pdev)
 
                dev->fifo_size = (dev->fifo_size / 2);
 
-               if (dev->rev >= OMAP_I2C_REV_ON_3630_4430)
-                       dev->b_hw = 0; /* Disable hardware fixes */
-               else
+               if (dev->rev < OMAP_I2C_REV_ON_3630_4430)
                        dev->b_hw = 1; /* Enable hardware fixes */
 
                /* calculate wakeup latency constraint for MPU */
-               if (dev->set_mpu_wkup_lat != NULL)
-                       dev->latency = (1000000 * dev->fifo_size) /
-                                      (1000 * dev->speed / 8);
+               dev->latency = (1000000 * dev->fifo_size) /
+                              (1000 * dev->speed / 8);
        }
 
        /* reset ASAP, clearing any IRQs */
        omap_i2c_init(dev);
 
-       isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr :
-                                                                  omap_i2c_isr;
-       r = request_irq(dev->irq, isr, IRQF_NO_SUSPEND, pdev->name, dev);
+       if (dev->rev < OMAP_I2C_OMAP1_REV_2)
+               r = devm_request_irq(&pdev->dev, dev->irq, omap_i2c_omap1_isr,
+                               IRQF_NO_SUSPEND, pdev->name, dev);
+       else
+               r = devm_request_threaded_irq(&pdev->dev, dev->irq,
+                               omap_i2c_isr, omap_i2c_isr_thread,
+                               IRQF_NO_SUSPEND | IRQF_ONESHOT,
+                               pdev->name, dev);
 
        if (r) {
                dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
                goto err_unuse_clocks;
        }
 
-       dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", pdev->id,
-                dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
-
        adap = &dev->adapter;
        i2c_set_adapdata(adap, dev);
        adap->owner = THIS_MODULE;
@@ -1082,27 +1194,25 @@ omap_i2c_probe(struct platform_device *pdev)
        r = i2c_add_numbered_adapter(adap);
        if (r) {
                dev_err(dev->dev, "failure adding adapter\n");
-               goto err_free_irq;
+               goto err_unuse_clocks;
        }
 
+       dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", adap->nr,
+                dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
+
        of_i2c_register_devices(adap);
 
-       pm_runtime_put(dev->dev);
+       pm_runtime_mark_last_busy(dev->dev);
+       pm_runtime_put_autosuspend(dev->dev);
 
        return 0;
 
-err_free_irq:
-       free_irq(dev->irq, dev);
 err_unuse_clocks:
        omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
        pm_runtime_put(dev->dev);
-       iounmap(dev->base);
        pm_runtime_disable(&pdev->dev);
 err_free_mem:
        platform_set_drvdata(pdev, NULL);
-       kfree(dev);
-err_release_region:
-       release_mem_region(mem->start, resource_size(mem));
 
        return r;
 }
@@ -1110,12 +1220,10 @@ err_release_region:
 static int __devexit omap_i2c_remove(struct platform_device *pdev)
 {
        struct omap_i2c_dev     *dev = platform_get_drvdata(pdev);
-       struct resource         *mem;
        int ret;
 
        platform_set_drvdata(pdev, NULL);
 
-       free_irq(dev->irq, dev);
        i2c_del_adapter(&dev->adapter);
        ret = pm_runtime_get_sync(&pdev->dev);
        if (IS_ERR_VALUE(ret))
@@ -1124,10 +1232,6 @@ static int __devexit omap_i2c_remove(struct platform_device *pdev)
        omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
        pm_runtime_put(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
-       iounmap(dev->base);
-       kfree(dev);
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(mem->start, resource_size(mem));
        return 0;
 }
 
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
new file mode 100644 (file)
index 0000000..f9399d1
--- /dev/null
@@ -0,0 +1,709 @@
+/*
+ *  drivers/i2c/busses/i2c-rcar.c
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This file is based on the drivers/i2c/busses/i2c-sh7760.c
+ * (c) 2005-2008 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau@msc-ge.com>
+ *
+ * This file used out-of-tree driver i2c-rcar.c
+ * Copyright (C) 2011-2012 Renesas Electronics 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
+ *
+ * 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
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/i2c/i2c-rcar.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+/* register offsets */
+#define ICSCR  0x00    /* slave ctrl */
+#define ICMCR  0x04    /* master ctrl */
+#define ICSSR  0x08    /* slave status */
+#define ICMSR  0x0C    /* master status */
+#define ICSIER 0x10    /* slave irq enable */
+#define ICMIER 0x14    /* master irq enable */
+#define ICCCR  0x18    /* clock dividers */
+#define ICSAR  0x1C    /* slave address */
+#define ICMAR  0x20    /* master address */
+#define ICRXTX 0x24    /* data port */
+
+/* ICMCR */
+#define MDBS   (1 << 7)        /* non-fifo mode switch */
+#define FSCL   (1 << 6)        /* override SCL pin */
+#define FSDA   (1 << 5)        /* override SDA pin */
+#define OBPC   (1 << 4)        /* override pins */
+#define MIE    (1 << 3)        /* master if enable */
+#define TSBE   (1 << 2)
+#define FSB    (1 << 1)        /* force stop bit */
+#define ESG    (1 << 0)        /* en startbit gen */
+
+/* ICMSR */
+#define MNR    (1 << 6)        /* nack received */
+#define MAL    (1 << 5)        /* arbitration lost */
+#define MST    (1 << 4)        /* sent a stop */
+#define MDE    (1 << 3)
+#define MDT    (1 << 2)
+#define MDR    (1 << 1)
+#define MAT    (1 << 0)        /* slave addr xfer done */
+
+/* ICMIE */
+#define MNRE   (1 << 6)        /* nack irq en */
+#define MALE   (1 << 5)        /* arblos irq en */
+#define MSTE   (1 << 4)        /* stop irq en */
+#define MDEE   (1 << 3)
+#define MDTE   (1 << 2)
+#define MDRE   (1 << 1)
+#define MATE   (1 << 0)        /* address sent irq en */
+
+
+enum {
+       RCAR_BUS_PHASE_ADDR,
+       RCAR_BUS_PHASE_DATA,
+       RCAR_BUS_PHASE_STOP,
+};
+
+enum {
+       RCAR_IRQ_CLOSE,
+       RCAR_IRQ_OPEN_FOR_SEND,
+       RCAR_IRQ_OPEN_FOR_RECV,
+       RCAR_IRQ_OPEN_FOR_STOP,
+};
+
+/*
+ * flags
+ */
+#define ID_LAST_MSG    (1 << 0)
+#define ID_IOERROR     (1 << 1)
+#define ID_DONE                (1 << 2)
+#define ID_ARBLOST     (1 << 3)
+#define ID_NACK                (1 << 4)
+
+struct rcar_i2c_priv {
+       void __iomem *io;
+       struct i2c_adapter adap;
+       struct i2c_msg  *msg;
+
+       spinlock_t lock;
+       wait_queue_head_t wait;
+
+       int pos;
+       int irq;
+       u32 icccr;
+       u32 flags;
+};
+
+#define rcar_i2c_priv_to_dev(p)                ((p)->adap.dev.parent)
+#define rcar_i2c_is_recv(p)            ((p)->msg->flags & I2C_M_RD)
+
+#define rcar_i2c_flags_set(p, f)       ((p)->flags |= (f))
+#define rcar_i2c_flags_has(p, f)       ((p)->flags & (f))
+
+#define LOOP_TIMEOUT   1024
+
+/*
+ *             basic functions
+ */
+static void rcar_i2c_write(struct rcar_i2c_priv *priv, int reg, u32 val)
+{
+       writel(val, priv->io + reg);
+}
+
+static u32 rcar_i2c_read(struct rcar_i2c_priv *priv, int reg)
+{
+       return readl(priv->io + reg);
+}
+
+static void rcar_i2c_init(struct rcar_i2c_priv *priv)
+{
+       /*
+        * reset slave mode.
+        * slave mode is not used on this driver
+        */
+       rcar_i2c_write(priv, ICSIER, 0);
+       rcar_i2c_write(priv, ICSAR, 0);
+       rcar_i2c_write(priv, ICSCR, 0);
+       rcar_i2c_write(priv, ICSSR, 0);
+
+       /* reset master mode */
+       rcar_i2c_write(priv, ICMIER, 0);
+       rcar_i2c_write(priv, ICMCR, 0);
+       rcar_i2c_write(priv, ICMSR, 0);
+       rcar_i2c_write(priv, ICMAR, 0);
+}
+
+static void rcar_i2c_irq_mask(struct rcar_i2c_priv *priv, int open)
+{
+       u32 val = MNRE | MALE | MSTE | MATE; /* default */
+
+       switch (open) {
+       case RCAR_IRQ_OPEN_FOR_SEND:
+               val |= MDEE; /* default + send */
+               break;
+       case RCAR_IRQ_OPEN_FOR_RECV:
+               val |= MDRE; /* default + read */
+               break;
+       case RCAR_IRQ_OPEN_FOR_STOP:
+               val = MSTE; /* stop irq only */
+               break;
+       case RCAR_IRQ_CLOSE:
+       default:
+               val = 0; /* all close */
+               break;
+       }
+       rcar_i2c_write(priv, ICMIER, val);
+}
+
+static void rcar_i2c_set_addr(struct rcar_i2c_priv *priv, u32 recv)
+{
+       rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | recv);
+}
+
+/*
+ *             bus control functions
+ */
+static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
+{
+       int i;
+
+       for (i = 0; i < LOOP_TIMEOUT; i++) {
+               /* make sure that bus is not busy */
+               if (!(rcar_i2c_read(priv, ICMCR) & FSDA))
+                       return 0;
+               udelay(1);
+       }
+
+       return -EBUSY;
+}
+
+static void rcar_i2c_bus_phase(struct rcar_i2c_priv *priv, int phase)
+{
+       switch (phase) {
+       case RCAR_BUS_PHASE_ADDR:
+               rcar_i2c_write(priv, ICMCR, MDBS | MIE | ESG);
+               break;
+       case RCAR_BUS_PHASE_DATA:
+               rcar_i2c_write(priv, ICMCR, MDBS | MIE);
+               break;
+       case RCAR_BUS_PHASE_STOP:
+               rcar_i2c_write(priv, ICMCR, MDBS | MIE | FSB);
+               break;
+       }
+}
+
+/*
+ *             clock function
+ */
+static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
+                                   u32 bus_speed,
+                                   struct device *dev)
+{
+       struct clk *clkp = clk_get(NULL, "peripheral_clk");
+       u32 scgd, cdf;
+       u32 round, ick;
+       u32 scl;
+
+       if (!clkp) {
+               dev_err(dev, "there is no peripheral_clk\n");
+               return -EIO;
+       }
+
+       /*
+        * calculate SCL clock
+        * see
+        *      ICCCR
+        *
+        * ick  = clkp / (1 + CDF)
+        * SCL  = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick])
+        *
+        * ick  : I2C internal clock < 20 MHz
+        * ticf : I2C SCL falling time  =  35 ns here
+        * tr   : I2C SCL rising  time  = 200 ns here
+        * intd : LSI internal delay    =  50 ns here
+        * clkp : peripheral_clk
+        * F[]  : integer up-valuation
+        */
+       for (cdf = 0; cdf < 4; cdf++) {
+               ick = clk_get_rate(clkp) / (1 + cdf);
+               if (ick < 20000000)
+                       goto ick_find;
+       }
+       dev_err(dev, "there is no best CDF\n");
+       return -EIO;
+
+ick_find:
+       /*
+        * it is impossible to calculate large scale
+        * number on u32. separate it
+        *
+        * F[(ticf + tr + intd) * ick]
+        *  = F[(35 + 200 + 50)ns * ick]
+        *  = F[285 * ick / 1000000000]
+        *  = F[(ick / 1000000) * 285 / 1000]
+        */
+       round = (ick + 500000) / 1000000 * 285;
+       round = (round + 500) / 1000;
+
+       /*
+        * SCL  = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick])
+        *
+        * Calculation result (= SCL) should be less than
+        * bus_speed for hardware safety
+        */
+       for (scgd = 0; scgd < 0x40; scgd++) {
+               scl = ick / (20 + (scgd * 8) + round);
+               if (scl <= bus_speed)
+                       goto scgd_find;
+       }
+       dev_err(dev, "it is impossible to calculate best SCL\n");
+       return -EIO;
+
+scgd_find:
+       dev_dbg(dev, "clk %d/%d(%lu), round %u, CDF:0x%x, SCGD: 0x%x\n",
+               scl, bus_speed, clk_get_rate(clkp), round, cdf, scgd);
+
+       /*
+        * keep icccr value
+        */
+       priv->icccr = (scgd << 2 | cdf);
+
+       return 0;
+}
+
+static void rcar_i2c_clock_start(struct rcar_i2c_priv *priv)
+{
+       rcar_i2c_write(priv, ICCCR, priv->icccr);
+}
+
+/*
+ *             status functions
+ */
+static u32 rcar_i2c_status_get(struct rcar_i2c_priv *priv)
+{
+       return rcar_i2c_read(priv, ICMSR);
+}
+
+#define rcar_i2c_status_clear(priv) rcar_i2c_status_bit_clear(priv, 0xffffffff)
+static void rcar_i2c_status_bit_clear(struct rcar_i2c_priv *priv, u32 bit)
+{
+       rcar_i2c_write(priv, ICMSR, ~bit);
+}
+
+/*
+ *             recv/send functions
+ */
+static int rcar_i2c_recv(struct rcar_i2c_priv *priv)
+{
+       rcar_i2c_set_addr(priv, 1);
+       rcar_i2c_status_clear(priv);
+       rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_ADDR);
+       rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_RECV);
+
+       return 0;
+}
+
+static int rcar_i2c_send(struct rcar_i2c_priv *priv)
+{
+       int ret;
+
+       /*
+        * It should check bus status when send case
+        */
+       ret = rcar_i2c_bus_barrier(priv);
+       if (ret < 0)
+               return ret;
+
+       rcar_i2c_set_addr(priv, 0);
+       rcar_i2c_status_clear(priv);
+       rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_ADDR);
+       rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_SEND);
+
+       return 0;
+}
+
+#define rcar_i2c_send_restart(priv) rcar_i2c_status_bit_clear(priv, (MAT | MDE))
+#define rcar_i2c_recv_restart(priv) rcar_i2c_status_bit_clear(priv, (MAT | MDR))
+
+/*
+ *             interrupt functions
+ */
+static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
+{
+       struct i2c_msg *msg = priv->msg;
+
+       /*
+        * FIXME
+        * sometimes, unknown interrupt happened.
+        * Do nothing
+        */
+       if (!(msr & MDE))
+               return 0;
+
+       /*
+        * If address transfer phase finished,
+        * goto data phase.
+        */
+       if (msr & MAT)
+               rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_DATA);
+
+       if (priv->pos < msg->len) {
+               /*
+                * Prepare next data to ICRXTX register.
+                * This data will go to _SHIFT_ register.
+                *
+                *    *
+                * [ICRXTX] -> [SHIFT] -> [I2C bus]
+                */
+               rcar_i2c_write(priv, ICRXTX, msg->buf[priv->pos]);
+               priv->pos++;
+
+       } else {
+               /*
+                * The last data was pushed to ICRXTX on _PREV_ empty irq.
+                * It is on _SHIFT_ register, and will sent to I2C bus.
+                *
+                *                *
+                * [ICRXTX] -> [SHIFT] -> [I2C bus]
+                */
+
+               if (priv->flags & ID_LAST_MSG)
+                       /*
+                        * If current msg is the _LAST_ msg,
+                        * prepare stop condition here.
+                        * ID_DONE will be set on STOP irq.
+                        */
+                       rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP);
+               else
+                       /*
+                        * If current msg is _NOT_ last msg,
+                        * it doesn't call stop phase.
+                        * thus, there is no STOP irq.
+                        * return ID_DONE here.
+                        */
+                       return ID_DONE;
+       }
+
+       rcar_i2c_send_restart(priv);
+
+       return 0;
+}
+
+static int rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
+{
+       struct i2c_msg *msg = priv->msg;
+
+       /*
+        * FIXME
+        * sometimes, unknown interrupt happened.
+        * Do nothing
+        */
+       if (!(msr & MDR))
+               return 0;
+
+       if (msr & MAT) {
+               /*
+                * Address transfer phase finished,
+                * but, there is no data at this point.
+                * Do nothing.
+                */
+       } else if (priv->pos < msg->len) {
+               /*
+                * get received data
+                */
+               msg->buf[priv->pos] = rcar_i2c_read(priv, ICRXTX);
+               priv->pos++;
+       }
+
+       /*
+        * If next received data is the _LAST_,
+        * go to STOP phase,
+        * otherwise, go to DATA phase.
+        */
+       if (priv->pos + 1 >= msg->len)
+               rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP);
+       else
+               rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_DATA);
+
+       rcar_i2c_recv_restart(priv);
+
+       return 0;
+}
+
+static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
+{
+       struct rcar_i2c_priv *priv = ptr;
+       struct device *dev = rcar_i2c_priv_to_dev(priv);
+       u32 msr;
+
+       /*-------------- spin lock -----------------*/
+       spin_lock(&priv->lock);
+
+       msr = rcar_i2c_status_get(priv);
+
+       /*
+        * Arbitration lost
+        */
+       if (msr & MAL) {
+               /*
+                * CAUTION
+                *
+                * When arbitration lost, device become _slave_ mode.
+                */
+               dev_dbg(dev, "Arbitration Lost\n");
+               rcar_i2c_flags_set(priv, (ID_DONE | ID_ARBLOST));
+               goto out;
+       }
+
+       /*
+        * Stop
+        */
+       if (msr & MST) {
+               dev_dbg(dev, "Stop\n");
+               rcar_i2c_flags_set(priv, ID_DONE);
+               goto out;
+       }
+
+       /*
+        * Nack
+        */
+       if (msr & MNR) {
+               dev_dbg(dev, "Nack\n");
+
+               /* go to stop phase */
+               rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP);
+               rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_STOP);
+               rcar_i2c_flags_set(priv, ID_NACK);
+               goto out;
+       }
+
+       /*
+        * recv/send
+        */
+       if (rcar_i2c_is_recv(priv))
+               rcar_i2c_flags_set(priv, rcar_i2c_irq_recv(priv, msr));
+       else
+               rcar_i2c_flags_set(priv, rcar_i2c_irq_send(priv, msr));
+
+out:
+       if (rcar_i2c_flags_has(priv, ID_DONE)) {
+               rcar_i2c_irq_mask(priv, RCAR_IRQ_CLOSE);
+               rcar_i2c_status_clear(priv);
+               wake_up(&priv->wait);
+       }
+
+       spin_unlock(&priv->lock);
+       /*-------------- spin unlock -----------------*/
+
+       return IRQ_HANDLED;
+}
+
+static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
+                               struct i2c_msg *msgs,
+                               int num)
+{
+       struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
+       struct device *dev = rcar_i2c_priv_to_dev(priv);
+       unsigned long flags;
+       int i, ret, timeout;
+
+       pm_runtime_get_sync(dev);
+
+       /*-------------- spin lock -----------------*/
+       spin_lock_irqsave(&priv->lock, flags);
+
+       rcar_i2c_init(priv);
+       rcar_i2c_clock_start(priv);
+
+       spin_unlock_irqrestore(&priv->lock, flags);
+       /*-------------- spin unlock -----------------*/
+
+       ret = -EINVAL;
+       for (i = 0; i < num; i++) {
+               /*-------------- spin lock -----------------*/
+               spin_lock_irqsave(&priv->lock, flags);
+
+               /* init each data */
+               priv->msg       = &msgs[i];
+               priv->pos       = 0;
+               priv->flags     = 0;
+               if (priv->msg == &msgs[num - 1])
+                       rcar_i2c_flags_set(priv, ID_LAST_MSG);
+
+               /* start send/recv */
+               if (rcar_i2c_is_recv(priv))
+                       ret = rcar_i2c_recv(priv);
+               else
+                       ret = rcar_i2c_send(priv);
+
+               spin_unlock_irqrestore(&priv->lock, flags);
+               /*-------------- spin unlock -----------------*/
+
+               if (ret < 0)
+                       break;
+
+               /*
+                * wait result
+                */
+               timeout = wait_event_timeout(priv->wait,
+                                            rcar_i2c_flags_has(priv, ID_DONE),
+                                            5 * HZ);
+               if (!timeout) {
+                       ret = -ETIMEDOUT;
+                       break;
+               }
+
+               /*
+                * error handling
+                */
+               if (rcar_i2c_flags_has(priv, ID_NACK)) {
+                       ret = -EREMOTEIO;
+                       break;
+               }
+
+               if (rcar_i2c_flags_has(priv, ID_ARBLOST)) {
+                       ret = -EAGAIN;
+                       break;
+               }
+
+               if (rcar_i2c_flags_has(priv, ID_IOERROR)) {
+                       ret = -EIO;
+                       break;
+               }
+
+               ret = i + 1; /* The number of transfer */
+       }
+
+       pm_runtime_put(dev);
+
+       if (ret < 0)
+               dev_err(dev, "error %d : %x\n", ret, priv->flags);
+
+       return ret;
+}
+
+static u32 rcar_i2c_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm rcar_i2c_algo = {
+       .master_xfer    = rcar_i2c_master_xfer,
+       .functionality  = rcar_i2c_func,
+};
+
+static int __devinit rcar_i2c_probe(struct platform_device *pdev)
+{
+       struct i2c_rcar_platform_data *pdata = pdev->dev.platform_data;
+       struct rcar_i2c_priv *priv;
+       struct i2c_adapter *adap;
+       struct resource *res;
+       struct device *dev = &pdev->dev;
+       u32 bus_speed;
+       int ret;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(dev, "no mmio resources\n");
+               return -ENODEV;
+       }
+
+       priv = devm_kzalloc(dev, sizeof(struct rcar_i2c_priv), GFP_KERNEL);
+       if (!priv) {
+               dev_err(dev, "no mem for private data\n");
+               return -ENOMEM;
+       }
+
+       bus_speed = 100000; /* default 100 kHz */
+       if (pdata && pdata->bus_speed)
+               bus_speed = pdata->bus_speed;
+       ret = rcar_i2c_clock_calculate(priv, bus_speed, dev);
+       if (ret < 0)
+               return ret;
+
+       priv->io = devm_ioremap(dev, res->start, resource_size(res));
+       if (!priv->io) {
+               dev_err(dev, "cannot ioremap\n");
+               return -ENODEV;
+       }
+
+       priv->irq = platform_get_irq(pdev, 0);
+       init_waitqueue_head(&priv->wait);
+       spin_lock_init(&priv->lock);
+
+       adap                    = &priv->adap;
+       adap->nr                = pdev->id;
+       adap->algo              = &rcar_i2c_algo;
+       adap->class             = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+       adap->retries           = 3;
+       adap->dev.parent        = dev;
+       i2c_set_adapdata(adap, priv);
+       strlcpy(adap->name, pdev->name, sizeof(adap->name));
+
+       ret = devm_request_irq(dev, priv->irq, rcar_i2c_irq, 0,
+                              dev_name(dev), priv);
+       if (ret < 0) {
+               dev_err(dev, "cannot get irq %d\n", priv->irq);
+               return ret;
+       }
+
+       ret = i2c_add_numbered_adapter(adap);
+       if (ret < 0) {
+               dev_err(dev, "reg adap failed: %d\n", ret);
+               return ret;
+       }
+
+       pm_runtime_enable(dev);
+       platform_set_drvdata(pdev, priv);
+
+       dev_info(dev, "probed\n");
+
+       return 0;
+}
+
+static int __devexit rcar_i2c_remove(struct platform_device *pdev)
+{
+       struct rcar_i2c_priv *priv = platform_get_drvdata(pdev);
+       struct device *dev = &pdev->dev;
+
+       i2c_del_adapter(&priv->adap);
+       pm_runtime_disable(dev);
+
+       return 0;
+}
+
+static struct platform_driver rcar_i2c_drv = {
+       .driver = {
+               .name   = "i2c-rcar",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = rcar_i2c_probe,
+       .remove         = __devexit_p(rcar_i2c_remove),
+};
+
+module_platform_driver(rcar_i2c_drv);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Renesas R-Car I2C bus driver");
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
index 4d07dea9bca9db1ad13305f3d7b44615b3e8ed6b..3e0335f1fc60df8b78ce50c7a4e5284e82ad432f 100644 (file)
@@ -601,14 +601,14 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
        int ret;
 
        pm_runtime_get_sync(&adap->dev);
-       clk_enable(i2c->clk);
+       clk_prepare_enable(i2c->clk);
 
        for (retry = 0; retry < adap->retries; retry++) {
 
                ret = s3c24xx_i2c_doxfer(i2c, msgs, num);
 
                if (ret != -EAGAIN) {
-                       clk_disable(i2c->clk);
+                       clk_disable_unprepare(i2c->clk);
                        pm_runtime_put(&adap->dev);
                        return ret;
                }
@@ -618,7 +618,7 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
                udelay(100);
        }
 
-       clk_disable(i2c->clk);
+       clk_disable_unprepare(i2c->clk);
        pm_runtime_put(&adap->dev);
        return -EREMOTEIO;
 }
@@ -977,7 +977,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
 
        dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
 
-       clk_enable(i2c->clk);
+       clk_prepare_enable(i2c->clk);
 
        /* map the registers */
 
@@ -1065,7 +1065,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
        pm_runtime_enable(&i2c->adap.dev);
 
        dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
-       clk_disable(i2c->clk);
+       clk_disable_unprepare(i2c->clk);
        return 0;
 
  err_cpufreq:
@@ -1082,7 +1082,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
        kfree(i2c->ioarea);
 
  err_clk:
-       clk_disable(i2c->clk);
+       clk_disable_unprepare(i2c->clk);
        clk_put(i2c->clk);
 
  err_noclk:
@@ -1106,7 +1106,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
        i2c_del_adapter(&i2c->adap);
        free_irq(i2c->irq, i2c);
 
-       clk_disable(i2c->clk);
+       clk_disable_unprepare(i2c->clk);
        clk_put(i2c->clk);
 
        iounmap(i2c->regs);
@@ -1135,9 +1135,9 @@ static int s3c24xx_i2c_resume(struct device *dev)
        struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
 
        i2c->suspended = 0;
-       clk_enable(i2c->clk);
+       clk_prepare_enable(i2c->clk);
        s3c24xx_i2c_init(i2c);
-       clk_disable(i2c->clk);
+       clk_disable_unprepare(i2c->clk);
 
        return 0;
 }
index 1983adc192432936e67b3ab128627596604b6f2d..a7568c34a1aa624c505f2a7a8d0235e9f2ccd21f 100644 (file)
@@ -3498,7 +3498,8 @@ out:
 }
 
 static const struct ibnl_client_cbs cma_cb_table[] = {
-       [RDMA_NL_RDMA_CM_ID_STATS] = { .dump = cma_get_id_stats },
+       [RDMA_NL_RDMA_CM_ID_STATS] = { .dump = cma_get_id_stats,
+                                      .module = THIS_MODULE },
 };
 
 static int __init cma_init(void)
index fe10a949aef9b6bd0533da3c4886933ee4a2091f..da06abde9e0d557ae1536f1995cd1a84af6ab219 100644 (file)
@@ -154,6 +154,7 @@ static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        {
                                struct netlink_dump_control c = {
                                        .dump = client->cb_table[op].dump,
+                                       .module = client->cb_table[op].module,
                                };
                                return netlink_dump_start(nls, skb, nlh, &c);
                        }
index 9e1449f8c6a26ea62349352de3f8178db2faa6fe..cf23c46185b25e8024c5a3e8e90d856bfc3ab1bc 100644 (file)
@@ -3564,16 +3564,6 @@ static int srpt_get_tcm_cmd_state(struct se_cmd *se_cmd)
        return srpt_get_cmd_state(ioctx);
 }
 
-static u16 srpt_set_fabric_sense_len(struct se_cmd *cmd, u32 sense_length)
-{
-       return 0;
-}
-
-static u16 srpt_get_fabric_sense_len(void)
-{
-       return 0;
-}
-
 /**
  * srpt_parse_i_port_id() - Parse an initiator port ID.
  * @name: ASCII representation of a 128-bit initiator port ID.
@@ -3953,8 +3943,6 @@ static struct target_core_fabric_ops srpt_template = {
        .queue_data_in                  = srpt_queue_response,
        .queue_status                   = srpt_queue_status,
        .queue_tm_rsp                   = srpt_queue_response,
-       .get_fabric_sense_len           = srpt_get_fabric_sense_len,
-       .set_fabric_sense_len           = srpt_set_fabric_sense_len,
        /*
         * Setup function pointers for generic logic in
         * target_core_fabric_configfs.c
index 118d0300f1fb72a1324006f544b790a6085affa2..6ae2ac47c9c806ecf5224e2eb02c49a704b40432 100644 (file)
 #include <linux/input/mt.h>
 #include <linux/major.h>
 #include <linux/device.h>
+#include <linux/cdev.h>
 #include "input-compat.h"
 
 struct evdev {
        int open;
-       int minor;
        struct input_handle handle;
        wait_queue_head_t wait;
        struct evdev_client __rcu *grab;
@@ -35,6 +35,7 @@ struct evdev {
        spinlock_t client_lock; /* protects client_list */
        struct mutex mutex;
        struct device dev;
+       struct cdev cdev;
        bool exist;
 };
 
@@ -51,9 +52,6 @@ struct evdev_client {
        struct input_event buffer[];
 };
 
-static struct evdev *evdev_table[EVDEV_MINORS];
-static DEFINE_MUTEX(evdev_table_mutex);
-
 static void __pass_event(struct evdev_client *client,
                         const struct input_event *event)
 {
@@ -310,35 +308,16 @@ static unsigned int evdev_compute_buffer_size(struct input_dev *dev)
 
 static int evdev_open(struct inode *inode, struct file *file)
 {
-       struct evdev *evdev;
+       struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev);
+       unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev);
        struct evdev_client *client;
-       int i = iminor(inode) - EVDEV_MINOR_BASE;
-       unsigned int bufsize;
        int error;
 
-       if (i >= EVDEV_MINORS)
-               return -ENODEV;
-
-       error = mutex_lock_interruptible(&evdev_table_mutex);
-       if (error)
-               return error;
-       evdev = evdev_table[i];
-       if (evdev)
-               get_device(&evdev->dev);
-       mutex_unlock(&evdev_table_mutex);
-
-       if (!evdev)
-               return -ENODEV;
-
-       bufsize = evdev_compute_buffer_size(evdev->handle.dev);
-
        client = kzalloc(sizeof(struct evdev_client) +
                                bufsize * sizeof(struct input_event),
                         GFP_KERNEL);
-       if (!client) {
-               error = -ENOMEM;
-               goto err_put_evdev;
-       }
+       if (!client)
+               return -ENOMEM;
 
        client->bufsize = bufsize;
        spin_lock_init(&client->buffer_lock);
@@ -352,13 +331,12 @@ static int evdev_open(struct inode *inode, struct file *file)
        file->private_data = client;
        nonseekable_open(inode, file);
 
+       get_device(&evdev->dev);
        return 0;
 
  err_free_client:
        evdev_detach_client(evdev, client);
        kfree(client);
- err_put_evdev:
-       put_device(&evdev->dev);
        return error;
 }
 
@@ -942,26 +920,6 @@ static const struct file_operations evdev_fops = {
        .llseek         = no_llseek,
 };
 
-static int evdev_install_chrdev(struct evdev *evdev)
-{
-       /*
-        * No need to do any locking here as calls to connect and
-        * disconnect are serialized by the input core
-        */
-       evdev_table[evdev->minor] = evdev;
-       return 0;
-}
-
-static void evdev_remove_chrdev(struct evdev *evdev)
-{
-       /*
-        * Lock evdev table to prevent race with evdev_open()
-        */
-       mutex_lock(&evdev_table_mutex);
-       evdev_table[evdev->minor] = NULL;
-       mutex_unlock(&evdev_table_mutex);
-}
-
 /*
  * Mark device non-existent. This disables writes, ioctls and
  * prevents new users from opening the device. Already posted
@@ -980,7 +938,8 @@ static void evdev_cleanup(struct evdev *evdev)
 
        evdev_mark_dead(evdev);
        evdev_hangup(evdev);
-       evdev_remove_chrdev(evdev);
+
+       cdev_del(&evdev->cdev);
 
        /* evdev is marked dead so no one else accesses evdev->open */
        if (evdev->open) {
@@ -991,43 +950,47 @@ static void evdev_cleanup(struct evdev *evdev)
 
 /*
  * Create new evdev device. Note that input core serializes calls
- * to connect and disconnect so we don't need to lock evdev_table here.
+ * to connect and disconnect.
  */
 static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
                         const struct input_device_id *id)
 {
        struct evdev *evdev;
        int minor;
+       int dev_no;
        int error;
 
-       for (minor = 0; minor < EVDEV_MINORS; minor++)
-               if (!evdev_table[minor])
-                       break;
-
-       if (minor == EVDEV_MINORS) {
-               pr_err("no more free evdev devices\n");
-               return -ENFILE;
+       minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true);
+       if (minor < 0) {
+               error = minor;
+               pr_err("failed to reserve new minor: %d\n", error);
+               return error;
        }
 
        evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
-       if (!evdev)
-               return -ENOMEM;
+       if (!evdev) {
+               error = -ENOMEM;
+               goto err_free_minor;
+       }
 
        INIT_LIST_HEAD(&evdev->client_list);
        spin_lock_init(&evdev->client_lock);
        mutex_init(&evdev->mutex);
        init_waitqueue_head(&evdev->wait);
-
-       dev_set_name(&evdev->dev, "event%d", minor);
        evdev->exist = true;
-       evdev->minor = minor;
+
+       dev_no = minor;
+       /* Normalize device number if it falls into legacy range */
+       if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS)
+               dev_no -= EVDEV_MINOR_BASE;
+       dev_set_name(&evdev->dev, "event%d", dev_no);
 
        evdev->handle.dev = input_get_device(dev);
        evdev->handle.name = dev_name(&evdev->dev);
        evdev->handle.handler = handler;
        evdev->handle.private = evdev;
 
-       evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
+       evdev->dev.devt = MKDEV(INPUT_MAJOR, minor);
        evdev->dev.class = &input_class;
        evdev->dev.parent = &dev->dev;
        evdev->dev.release = evdev_free;
@@ -1037,7 +1000,8 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
        if (error)
                goto err_free_evdev;
 
-       error = evdev_install_chrdev(evdev);
+       cdev_init(&evdev->cdev, &evdev_fops);
+       error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
 
@@ -1053,6 +1017,8 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
        input_unregister_handle(&evdev->handle);
  err_free_evdev:
        put_device(&evdev->dev);
+ err_free_minor:
+       input_free_minor(minor);
        return error;
 }
 
@@ -1062,6 +1028,7 @@ static void evdev_disconnect(struct input_handle *handle)
 
        device_del(&evdev->dev);
        evdev_cleanup(evdev);
+       input_free_minor(MINOR(evdev->dev.devt));
        input_unregister_handle(handle);
        put_device(&evdev->dev);
 }
@@ -1078,7 +1045,7 @@ static struct input_handler evdev_handler = {
        .events         = evdev_events,
        .connect        = evdev_connect,
        .disconnect     = evdev_disconnect,
-       .fops           = &evdev_fops,
+       .legacy_minors  = true,
        .minor          = EVDEV_MINOR_BASE,
        .name           = "evdev",
        .id_table       = evdev_ids,
index ace3f7c4226d60325fb11b1959fae61180cb3869..53a0ddee78724221e1134310eca5574dde3ce7ec 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <linux/init.h>
 #include <linux/types.h>
+#include <linux/idr.h>
 #include <linux/input/mt.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -32,7 +33,9 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("Input core");
 MODULE_LICENSE("GPL");
 
-#define INPUT_DEVICES  256
+#define INPUT_MAX_CHAR_DEVICES         1024
+#define INPUT_FIRST_DYNAMIC_DEV                256
+static DEFINE_IDA(input_ida);
 
 static LIST_HEAD(input_dev_list);
 static LIST_HEAD(input_handler_list);
@@ -45,8 +48,6 @@ static LIST_HEAD(input_handler_list);
  */
 static DEFINE_MUTEX(input_mutex);
 
-static struct input_handler *input_table[8];
-
 static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 };
 
 static inline int is_event_supported(unsigned int code,
@@ -1218,7 +1219,7 @@ static int input_handlers_seq_show(struct seq_file *seq, void *v)
        seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name);
        if (handler->filter)
                seq_puts(seq, " (filter)");
-       if (handler->fops)
+       if (handler->legacy_minors)
                seq_printf(seq, " Minor=%d", handler->minor);
        seq_putc(seq, '\n');
 
@@ -2016,22 +2017,14 @@ EXPORT_SYMBOL(input_unregister_device);
 int input_register_handler(struct input_handler *handler)
 {
        struct input_dev *dev;
-       int retval;
+       int error;
 
-       retval = mutex_lock_interruptible(&input_mutex);
-       if (retval)
-               return retval;
+       error = mutex_lock_interruptible(&input_mutex);
+       if (error)
+               return error;
 
        INIT_LIST_HEAD(&handler->h_list);
 
-       if (handler->fops != NULL) {
-               if (input_table[handler->minor >> 5]) {
-                       retval = -EBUSY;
-                       goto out;
-               }
-               input_table[handler->minor >> 5] = handler;
-       }
-
        list_add_tail(&handler->node, &input_handler_list);
 
        list_for_each_entry(dev, &input_dev_list, node)
@@ -2039,9 +2032,8 @@ int input_register_handler(struct input_handler *handler)
 
        input_wakeup_procfs_readers();
 
- out:
        mutex_unlock(&input_mutex);
-       return retval;
+       return 0;
 }
 EXPORT_SYMBOL(input_register_handler);
 
@@ -2064,9 +2056,6 @@ void input_unregister_handler(struct input_handler *handler)
 
        list_del_init(&handler->node);
 
-       if (handler->fops != NULL)
-               input_table[handler->minor >> 5] = NULL;
-
        input_wakeup_procfs_readers();
 
        mutex_unlock(&input_mutex);
@@ -2183,51 +2172,52 @@ void input_unregister_handle(struct input_handle *handle)
 }
 EXPORT_SYMBOL(input_unregister_handle);
 
-static int input_open_file(struct inode *inode, struct file *file)
+/**
+ * input_get_new_minor - allocates a new input minor number
+ * @legacy_base: beginning or the legacy range to be searched
+ * @legacy_num: size of legacy range
+ * @allow_dynamic: whether we can also take ID from the dynamic range
+ *
+ * This function allocates a new device minor for from input major namespace.
+ * Caller can request legacy minor by specifying @legacy_base and @legacy_num
+ * parameters and whether ID can be allocated from dynamic range if there are
+ * no free IDs in legacy range.
+ */
+int input_get_new_minor(int legacy_base, unsigned int legacy_num,
+                       bool allow_dynamic)
 {
-       struct input_handler *handler;
-       const struct file_operations *old_fops, *new_fops = NULL;
-       int err;
-
-       err = mutex_lock_interruptible(&input_mutex);
-       if (err)
-               return err;
-
-       /* No load-on-demand here? */
-       handler = input_table[iminor(inode) >> 5];
-       if (handler)
-               new_fops = fops_get(handler->fops);
-
-       mutex_unlock(&input_mutex);
-
        /*
-        * That's _really_ odd. Usually NULL ->open means "nothing special",
-        * not "no device". Oh, well...
+        * This function should be called from input handler's ->connect()
+        * methods, which are serialized with input_mutex, so no additional
+        * locking is needed here.
         */
-       if (!new_fops || !new_fops->open) {
-               fops_put(new_fops);
-               err = -ENODEV;
-               goto out;
+       if (legacy_base >= 0) {
+               int minor = ida_simple_get(&input_ida,
+                                          legacy_base,
+                                          legacy_base + legacy_num,
+                                          GFP_KERNEL);
+               if (minor >= 0 || !allow_dynamic)
+                       return minor;
        }
 
-       old_fops = file->f_op;
-       file->f_op = new_fops;
-
-       err = new_fops->open(inode, file);
-       if (err) {
-               fops_put(file->f_op);
-               file->f_op = fops_get(old_fops);
-       }
-       fops_put(old_fops);
-out:
-       return err;
+       return ida_simple_get(&input_ida,
+                             INPUT_FIRST_DYNAMIC_DEV, INPUT_MAX_CHAR_DEVICES,
+                             GFP_KERNEL);
 }
+EXPORT_SYMBOL(input_get_new_minor);
 
-static const struct file_operations input_fops = {
-       .owner = THIS_MODULE,
-       .open = input_open_file,
-       .llseek = noop_llseek,
-};
+/**
+ * input_free_minor - release previously allocated minor
+ * @minor: minor to be released
+ *
+ * This function releases previously allocated input minor so that it can be
+ * reused later.
+ */
+void input_free_minor(unsigned int minor)
+{
+       ida_simple_remove(&input_ida, minor);
+}
+EXPORT_SYMBOL(input_free_minor);
 
 static int __init input_init(void)
 {
@@ -2243,7 +2233,8 @@ static int __init input_init(void)
        if (err)
                goto fail1;
 
-       err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
+       err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0),
+                                    INPUT_MAX_CHAR_DEVICES, "input");
        if (err) {
                pr_err("unable to register char major %d", INPUT_MAJOR);
                goto fail2;
@@ -2259,7 +2250,8 @@ static int __init input_init(void)
 static void __exit input_exit(void)
 {
        input_proc_exit();
-       unregister_chrdev(INPUT_MAJOR, "input");
+       unregister_chrdev_region(MKDEV(INPUT_MAJOR, 0),
+                                INPUT_MAX_CHAR_DEVICES);
        class_unregister(&input_class);
 }
 
index 78f323ea1e4bff2821dcd8cd73bedf90ede73cbc..b62b5891f3999573893c732297ecd0467a094147 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/cdev.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Joystick device interfaces");
@@ -39,13 +40,13 @@ MODULE_LICENSE("GPL");
 
 struct joydev {
        int open;
-       int minor;
        struct input_handle handle;
        wait_queue_head_t wait;
        struct list_head client_list;
        spinlock_t client_lock; /* protects client_list */
        struct mutex mutex;
        struct device dev;
+       struct cdev cdev;
        bool exist;
 
        struct js_corr corr[ABS_CNT];
@@ -70,9 +71,6 @@ struct joydev_client {
        struct list_head node;
 };
 
-static struct joydev *joydev_table[JOYDEV_MINORS];
-static DEFINE_MUTEX(joydev_table_mutex);
-
 static int joydev_correct(int value, struct js_corr *corr)
 {
        switch (corr->type) {
@@ -252,30 +250,14 @@ static int joydev_release(struct inode *inode, struct file *file)
 
 static int joydev_open(struct inode *inode, struct file *file)
 {
+       struct joydev *joydev =
+                       container_of(inode->i_cdev, struct joydev, cdev);
        struct joydev_client *client;
-       struct joydev *joydev;
-       int i = iminor(inode) - JOYDEV_MINOR_BASE;
        int error;
 
-       if (i >= JOYDEV_MINORS)
-               return -ENODEV;
-
-       error = mutex_lock_interruptible(&joydev_table_mutex);
-       if (error)
-               return error;
-       joydev = joydev_table[i];
-       if (joydev)
-               get_device(&joydev->dev);
-       mutex_unlock(&joydev_table_mutex);
-
-       if (!joydev)
-               return -ENODEV;
-
        client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
-       if (!client) {
-               error = -ENOMEM;
-               goto err_put_joydev;
-       }
+       if (!client)
+               return -ENOMEM;
 
        spin_lock_init(&client->buffer_lock);
        client->joydev = joydev;
@@ -288,13 +270,12 @@ static int joydev_open(struct inode *inode, struct file *file)
        file->private_data = client;
        nonseekable_open(inode, file);
 
+       get_device(&joydev->dev);
        return 0;
 
  err_free_client:
        joydev_detach_client(joydev, client);
        kfree(client);
- err_put_joydev:
-       put_device(&joydev->dev);
        return error;
 }
 
@@ -742,19 +723,6 @@ static const struct file_operations joydev_fops = {
        .llseek         = no_llseek,
 };
 
-static int joydev_install_chrdev(struct joydev *joydev)
-{
-       joydev_table[joydev->minor] = joydev;
-       return 0;
-}
-
-static void joydev_remove_chrdev(struct joydev *joydev)
-{
-       mutex_lock(&joydev_table_mutex);
-       joydev_table[joydev->minor] = NULL;
-       mutex_unlock(&joydev_table_mutex);
-}
-
 /*
  * Mark device non-existent. This disables writes, ioctls and
  * prevents new users from opening the device. Already posted
@@ -773,7 +741,8 @@ static void joydev_cleanup(struct joydev *joydev)
 
        joydev_mark_dead(joydev);
        joydev_hangup(joydev);
-       joydev_remove_chrdev(joydev);
+
+       cdev_del(&joydev->cdev);
 
        /* joydev is marked dead so no one else accesses joydev->open */
        if (joydev->open)
@@ -798,30 +767,33 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
                          const struct input_device_id *id)
 {
        struct joydev *joydev;
-       int i, j, t, minor;
+       int i, j, t, minor, dev_no;
        int error;
 
-       for (minor = 0; minor < JOYDEV_MINORS; minor++)
-               if (!joydev_table[minor])
-                       break;
-
-       if (minor == JOYDEV_MINORS) {
-               pr_err("no more free joydev devices\n");
-               return -ENFILE;
+       minor = input_get_new_minor(JOYDEV_MINOR_BASE, JOYDEV_MINORS, true);
+       if (minor < 0) {
+               error = minor;
+               pr_err("failed to reserve new minor: %d\n", error);
+               return error;
        }
 
        joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL);
-       if (!joydev)
-               return -ENOMEM;
+       if (!joydev) {
+               error = -ENOMEM;
+               goto err_free_minor;
+       }
 
        INIT_LIST_HEAD(&joydev->client_list);
        spin_lock_init(&joydev->client_lock);
        mutex_init(&joydev->mutex);
        init_waitqueue_head(&joydev->wait);
-
-       dev_set_name(&joydev->dev, "js%d", minor);
        joydev->exist = true;
-       joydev->minor = minor;
+
+       dev_no = minor;
+       /* Normalize device number if it falls into legacy range */
+       if (dev_no < JOYDEV_MINOR_BASE + JOYDEV_MINORS)
+               dev_no -= JOYDEV_MINOR_BASE;
+       dev_set_name(&joydev->dev, "js%d", dev_no);
 
        joydev->handle.dev = input_get_device(dev);
        joydev->handle.name = dev_name(&joydev->dev);
@@ -875,7 +847,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
                }
        }
 
-       joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
+       joydev->dev.devt = MKDEV(INPUT_MAJOR, minor);
        joydev->dev.class = &input_class;
        joydev->dev.parent = &dev->dev;
        joydev->dev.release = joydev_free;
@@ -885,7 +857,8 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
        if (error)
                goto err_free_joydev;
 
-       error = joydev_install_chrdev(joydev);
+       cdev_init(&joydev->cdev, &joydev_fops);
+       error = cdev_add(&joydev->cdev, joydev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
 
@@ -901,6 +874,8 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
        input_unregister_handle(&joydev->handle);
  err_free_joydev:
        put_device(&joydev->dev);
+ err_free_minor:
+       input_free_minor(minor);
        return error;
 }
 
@@ -910,6 +885,7 @@ static void joydev_disconnect(struct input_handle *handle)
 
        device_del(&joydev->dev);
        joydev_cleanup(joydev);
+       input_free_minor(MINOR(joydev->dev.devt));
        input_unregister_handle(handle);
        put_device(&joydev->dev);
 }
@@ -961,7 +937,7 @@ static struct input_handler joydev_handler = {
        .match          = joydev_match,
        .connect        = joydev_connect,
        .disconnect     = joydev_disconnect,
-       .fops           = &joydev_fops,
+       .legacy_minors  = true,
        .minor          = JOYDEV_MINOR_BASE,
        .name           = "joydev",
        .id_table       = joydev_ids,
index 277e26dc910e40c8522722a5895b240d51a6b6d8..9d7a111486f76eadf3417f4f066375aaaf971895 100644 (file)
@@ -431,6 +431,12 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev)
                goto err_unmap_base;
        }
 
+       error = clk_prepare(keypad->clk);
+       if (error) {
+               dev_err(&pdev->dev, "keypad clock prepare failed\n");
+               goto err_put_clk;
+       }
+
        keypad->input_dev = input_dev;
        keypad->pdev = pdev;
        keypad->row_shift = row_shift;
@@ -461,7 +467,7 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev)
                                           keypad->keycodes, input_dev);
        if (error) {
                dev_err(&pdev->dev, "failed to build keymap\n");
-               goto err_put_clk;
+               goto err_unprepare_clk;
        }
 
        input_set_capability(input_dev, EV_MSC, MSC_SCAN);
@@ -503,6 +509,8 @@ err_free_irq:
        pm_runtime_disable(&pdev->dev);
        device_init_wakeup(&pdev->dev, 0);
        platform_set_drvdata(pdev, NULL);
+err_unprepare_clk:
+       clk_unprepare(keypad->clk);
 err_put_clk:
        clk_put(keypad->clk);
        samsung_keypad_dt_gpio_free(keypad);
@@ -531,6 +539,7 @@ static int __devexit samsung_keypad_remove(struct platform_device *pdev)
         */
        free_irq(keypad->irq, keypad);
 
+       clk_unprepare(keypad->clk);
        clk_put(keypad->clk);
        samsung_keypad_dt_gpio_free(keypad);
 
index 964e43d81e29d9224a3261a0666f84dd500100c6..a1b4c37956b2ef3af055e5c66ccd7753225cabeb 100644 (file)
 #include <linux/random.h>
 #include <linux/major.h>
 #include <linux/device.h>
+#include <linux/cdev.h>
 #include <linux/kernel.h>
-#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
-#include <linux/miscdevice.h>
-#endif
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Mouse (ExplorerPS/2) device interfaces");
@@ -61,17 +59,18 @@ struct mousedev_hw_data {
 
 struct mousedev {
        int open;
-       int minor;
        struct input_handle handle;
        wait_queue_head_t wait;
        struct list_head client_list;
        spinlock_t client_lock; /* protects client_list */
        struct mutex mutex;
        struct device dev;
+       struct cdev cdev;
        bool exist;
+       bool is_mixdev;
 
        struct list_head mixdev_node;
-       int mixdev_open;
+       bool opened_by_mixdev;
 
        struct mousedev_hw_data packet;
        unsigned int pkt_count;
@@ -114,10 +113,6 @@ struct mousedev_client {
 static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 };
 static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
 
-static struct input_handler mousedev_handler;
-
-static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
-static DEFINE_MUTEX(mousedev_table_mutex);
 static struct mousedev *mousedev_mix;
 static LIST_HEAD(mousedev_mix_list);
 
@@ -433,7 +428,7 @@ static int mousedev_open_device(struct mousedev *mousedev)
        if (retval)
                return retval;
 
-       if (mousedev->minor == MOUSEDEV_MIX)
+       if (mousedev->is_mixdev)
                mixdev_open_devices();
        else if (!mousedev->exist)
                retval = -ENODEV;
@@ -451,7 +446,7 @@ static void mousedev_close_device(struct mousedev *mousedev)
 {
        mutex_lock(&mousedev->mutex);
 
-       if (mousedev->minor == MOUSEDEV_MIX)
+       if (mousedev->is_mixdev)
                mixdev_close_devices();
        else if (mousedev->exist && !--mousedev->open)
                input_close_device(&mousedev->handle);
@@ -472,11 +467,11 @@ static void mixdev_open_devices(void)
                return;
 
        list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
-               if (!mousedev->mixdev_open) {
+               if (!mousedev->opened_by_mixdev) {
                        if (mousedev_open_device(mousedev))
                                continue;
 
-                       mousedev->mixdev_open = 1;
+                       mousedev->opened_by_mixdev = true;
                }
        }
 }
@@ -494,8 +489,8 @@ static void mixdev_close_devices(void)
                return;
 
        list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
-               if (mousedev->mixdev_open) {
-                       mousedev->mixdev_open = 0;
+               if (mousedev->opened_by_mixdev) {
+                       mousedev->opened_by_mixdev = false;
                        mousedev_close_device(mousedev);
                }
        }
@@ -538,35 +533,17 @@ static int mousedev_open(struct inode *inode, struct file *file)
        struct mousedev_client *client;
        struct mousedev *mousedev;
        int error;
-       int i;
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
        if (imajor(inode) == MISC_MAJOR)
-               i = MOUSEDEV_MIX;
+               mousedev = mousedev_mix;
        else
 #endif
-               i = iminor(inode) - MOUSEDEV_MINOR_BASE;
-
-       if (i >= MOUSEDEV_MINORS)
-               return -ENODEV;
-
-       error = mutex_lock_interruptible(&mousedev_table_mutex);
-       if (error)
-               return error;
-
-       mousedev = mousedev_table[i];
-       if (mousedev)
-               get_device(&mousedev->dev);
-       mutex_unlock(&mousedev_table_mutex);
-
-       if (!mousedev)
-               return -ENODEV;
+               mousedev = container_of(inode->i_cdev, struct mousedev, cdev);
 
        client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
-       if (!client) {
-               error = -ENOMEM;
-               goto err_put_mousedev;
-       }
+       if (!client)
+               return -ENOMEM;
 
        spin_lock_init(&client->packet_lock);
        client->pos_x = xres / 2;
@@ -579,13 +556,14 @@ static int mousedev_open(struct inode *inode, struct file *file)
                goto err_free_client;
 
        file->private_data = client;
+       nonseekable_open(inode, file);
+
+       get_device(&mousedev->dev);
        return 0;
 
  err_free_client:
        mousedev_detach_client(mousedev, client);
        kfree(client);
- err_put_mousedev:
-       put_device(&mousedev->dev);
        return error;
 }
 
@@ -785,29 +763,16 @@ static unsigned int mousedev_poll(struct file *file, poll_table *wait)
 }
 
 static const struct file_operations mousedev_fops = {
-       .owner =        THIS_MODULE,
-       .read =         mousedev_read,
-       .write =        mousedev_write,
-       .poll =         mousedev_poll,
-       .open =         mousedev_open,
-       .release =      mousedev_release,
-       .fasync =       mousedev_fasync,
-       .llseek = noop_llseek,
+       .owner          = THIS_MODULE,
+       .read           = mousedev_read,
+       .write          = mousedev_write,
+       .poll           = mousedev_poll,
+       .open           = mousedev_open,
+       .release        = mousedev_release,
+       .fasync         = mousedev_fasync,
+       .llseek         = noop_llseek,
 };
 
-static int mousedev_install_chrdev(struct mousedev *mousedev)
-{
-       mousedev_table[mousedev->minor] = mousedev;
-       return 0;
-}
-
-static void mousedev_remove_chrdev(struct mousedev *mousedev)
-{
-       mutex_lock(&mousedev_table_mutex);
-       mousedev_table[mousedev->minor] = NULL;
-       mutex_unlock(&mousedev_table_mutex);
-}
-
 /*
  * Mark device non-existent. This disables writes, ioctls and
  * prevents new users from opening the device. Already posted
@@ -842,24 +807,50 @@ static void mousedev_cleanup(struct mousedev *mousedev)
 
        mousedev_mark_dead(mousedev);
        mousedev_hangup(mousedev);
-       mousedev_remove_chrdev(mousedev);
+
+       cdev_del(&mousedev->cdev);
 
        /* mousedev is marked dead so no one else accesses mousedev->open */
        if (mousedev->open)
                input_close_device(handle);
 }
 
+static int mousedev_reserve_minor(bool mixdev)
+{
+       int minor;
+
+       if (mixdev) {
+               minor = input_get_new_minor(MOUSEDEV_MIX, 1, false);
+               if (minor < 0)
+                       pr_err("failed to reserve mixdev minor: %d\n", minor);
+       } else {
+               minor = input_get_new_minor(MOUSEDEV_MINOR_BASE,
+                                           MOUSEDEV_MINORS, true);
+               if (minor < 0)
+                       pr_err("failed to reserve new minor: %d\n", minor);
+       }
+
+       return minor;
+}
+
 static struct mousedev *mousedev_create(struct input_dev *dev,
                                        struct input_handler *handler,
-                                       int minor)
+                                       bool mixdev)
 {
        struct mousedev *mousedev;
+       int minor;
        int error;
 
+       minor = mousedev_reserve_minor(mixdev);
+       if (minor < 0) {
+               error = minor;
+               goto err_out;
+       }
+
        mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
        if (!mousedev) {
                error = -ENOMEM;
-               goto err_out;
+               goto err_free_minor;
        }
 
        INIT_LIST_HEAD(&mousedev->client_list);
@@ -867,16 +858,21 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
        spin_lock_init(&mousedev->client_lock);
        mutex_init(&mousedev->mutex);
        lockdep_set_subclass(&mousedev->mutex,
-                            minor == MOUSEDEV_MIX ? SINGLE_DEPTH_NESTING : 0);
+                            mixdev ? SINGLE_DEPTH_NESTING : 0);
        init_waitqueue_head(&mousedev->wait);
 
-       if (minor == MOUSEDEV_MIX)
+       if (mixdev) {
                dev_set_name(&mousedev->dev, "mice");
-       else
-               dev_set_name(&mousedev->dev, "mouse%d", minor);
+       } else {
+               int dev_no = minor;
+               /* Normalize device number if it falls into legacy range */
+               if (dev_no < MOUSEDEV_MINOR_BASE + MOUSEDEV_MINORS)
+                       dev_no -= MOUSEDEV_MINOR_BASE;
+               dev_set_name(&mousedev->dev, "mouse%d", dev_no);
+       }
 
-       mousedev->minor = minor;
        mousedev->exist = true;
+       mousedev->is_mixdev = mixdev;
        mousedev->handle.dev = input_get_device(dev);
        mousedev->handle.name = dev_name(&mousedev->dev);
        mousedev->handle.handler = handler;
@@ -885,17 +881,18 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
        mousedev->dev.class = &input_class;
        if (dev)
                mousedev->dev.parent = &dev->dev;
-       mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor);
+       mousedev->dev.devt = MKDEV(INPUT_MAJOR, minor);
        mousedev->dev.release = mousedev_free;
        device_initialize(&mousedev->dev);
 
-       if (minor != MOUSEDEV_MIX) {
+       if (!mixdev) {
                error = input_register_handle(&mousedev->handle);
                if (error)
                        goto err_free_mousedev;
        }
 
-       error = mousedev_install_chrdev(mousedev);
+       cdev_init(&mousedev->cdev, &mousedev_fops);
+       error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
 
@@ -908,10 +905,12 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
  err_cleanup_mousedev:
        mousedev_cleanup(mousedev);
  err_unregister_handle:
-       if (minor != MOUSEDEV_MIX)
+       if (!mixdev)
                input_unregister_handle(&mousedev->handle);
  err_free_mousedev:
        put_device(&mousedev->dev);
+ err_free_minor:
+       input_free_minor(minor);
  err_out:
        return ERR_PTR(error);
 }
@@ -920,7 +919,8 @@ static void mousedev_destroy(struct mousedev *mousedev)
 {
        device_del(&mousedev->dev);
        mousedev_cleanup(mousedev);
-       if (mousedev->minor != MOUSEDEV_MIX)
+       input_free_minor(MINOR(mousedev->dev.devt));
+       if (!mousedev->is_mixdev)
                input_unregister_handle(&mousedev->handle);
        put_device(&mousedev->dev);
 }
@@ -938,7 +938,7 @@ static int mixdev_add_device(struct mousedev *mousedev)
                if (retval)
                        goto out;
 
-               mousedev->mixdev_open = 1;
+               mousedev->opened_by_mixdev = true;
        }
 
        get_device(&mousedev->dev);
@@ -953,8 +953,8 @@ static void mixdev_remove_device(struct mousedev *mousedev)
 {
        mutex_lock(&mousedev_mix->mutex);
 
-       if (mousedev->mixdev_open) {
-               mousedev->mixdev_open = 0;
+       if (mousedev->opened_by_mixdev) {
+               mousedev->opened_by_mixdev = false;
                mousedev_close_device(mousedev);
        }
 
@@ -969,19 +969,9 @@ static int mousedev_connect(struct input_handler *handler,
                            const struct input_device_id *id)
 {
        struct mousedev *mousedev;
-       int minor;
        int error;
 
-       for (minor = 0; minor < MOUSEDEV_MINORS; minor++)
-               if (!mousedev_table[minor])
-                       break;
-
-       if (minor == MOUSEDEV_MINORS) {
-               pr_err("no more free mousedev devices\n");
-               return -ENFILE;
-       }
-
-       mousedev = mousedev_create(dev, handler, minor);
+       mousedev = mousedev_create(dev, handler, false);
        if (IS_ERR(mousedev))
                return PTR_ERR(mousedev);
 
@@ -1054,27 +1044,53 @@ static const struct input_device_id mousedev_ids[] = {
 MODULE_DEVICE_TABLE(input, mousedev_ids);
 
 static struct input_handler mousedev_handler = {
-       .event =        mousedev_event,
-       .connect =      mousedev_connect,
-       .disconnect =   mousedev_disconnect,
-       .fops =         &mousedev_fops,
-       .minor =        MOUSEDEV_MINOR_BASE,
-       .name =         "mousedev",
-       .id_table =     mousedev_ids,
+       .event          = mousedev_event,
+       .connect        = mousedev_connect,
+       .disconnect     = mousedev_disconnect,
+       .legacy_minors  = true,
+       .minor          = MOUSEDEV_MINOR_BASE,
+       .name           = "mousedev",
+       .id_table       = mousedev_ids,
 };
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
+#include <linux/miscdevice.h>
+
 static struct miscdevice psaux_mouse = {
-       PSMOUSE_MINOR, "psaux", &mousedev_fops
+       .minor  = PSMOUSE_MINOR,
+       .name   = "psaux",
+       .fops   = &mousedev_fops,
 };
-static int psaux_registered;
+
+static bool psaux_registered;
+
+static void __init mousedev_psaux_register(void)
+{
+       int error;
+
+       error = misc_register(&psaux_mouse);
+       if (error)
+               pr_warn("could not register psaux device, error: %d\n",
+                          error);
+       else
+               psaux_registered = true;
+}
+
+static void __exit mousedev_psaux_unregister(void)
+{
+       if (psaux_registered)
+               misc_deregister(&psaux_mouse);
+}
+#else
+static inline void mousedev_psaux_register(void) { }
+static inline void mousedev_psaux_unregister(void) { }
 #endif
 
 static int __init mousedev_init(void)
 {
        int error;
 
-       mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX);
+       mousedev_mix = mousedev_create(NULL, &mousedev_handler, true);
        if (IS_ERR(mousedev_mix))
                return PTR_ERR(mousedev_mix);
 
@@ -1084,14 +1100,7 @@ static int __init mousedev_init(void)
                return error;
        }
 
-#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
-       error = misc_register(&psaux_mouse);
-       if (error)
-               pr_warn("could not register psaux device, error: %d\n",
-                          error);
-       else
-               psaux_registered = 1;
-#endif
+       mousedev_psaux_register();
 
        pr_info("PS/2 mouse device common for all mice\n");
 
@@ -1100,10 +1109,7 @@ static int __init mousedev_init(void)
 
 static void __exit mousedev_exit(void)
 {
-#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
-       if (psaux_registered)
-               misc_deregister(&psaux_mouse);
-#endif
+       mousedev_psaux_unregister();
        input_unregister_handler(&mousedev_handler);
        mousedev_destroy(mousedev_mix);
 }
index 0d3219f297448cbbc10d3a20319ed0ea287ddcb5..9edf9806cff9db6350e4e25677fb74177364251a 100644 (file)
@@ -171,6 +171,76 @@ static void wacom_close(struct input_dev *dev)
                usb_autopm_put_interface(wacom->intf);
 }
 
+/*
+ * Calculate the resolution of the X or Y axis, given appropriate HID data.
+ * This function is little more than hidinput_calc_abs_res stripped down.
+ */
+static int wacom_calc_hid_res(int logical_extents, int physical_extents,
+                              unsigned char unit, unsigned char exponent)
+{
+       int prev, unit_exponent;
+
+       /* Check if the extents are sane */
+       if (logical_extents <= 0 || physical_extents <= 0)
+               return 0;
+
+       /* Get signed value of nybble-sized twos-compliment exponent */
+       unit_exponent = exponent;
+       if (unit_exponent > 7)
+               unit_exponent -= 16;
+
+       /* Convert physical_extents to millimeters */
+       if (unit == 0x11) {             /* If centimeters */
+               unit_exponent += 1;
+       } else if (unit == 0x13) {      /* If inches */
+               prev = physical_extents;
+               physical_extents *= 254;
+               if (physical_extents < prev)
+                       return 0;
+               unit_exponent -= 1;
+       } else {
+               return 0;
+       }
+
+       /* Apply negative unit exponent */
+       for (; unit_exponent < 0; unit_exponent++) {
+               prev = logical_extents;
+               logical_extents *= 10;
+               if (logical_extents < prev)
+                       return 0;
+       }
+       /* Apply positive unit exponent */
+       for (; unit_exponent > 0; unit_exponent--) {
+               prev = physical_extents;
+               physical_extents *= 10;
+               if (physical_extents < prev)
+                       return 0;
+       }
+
+       /* Calculate resolution */
+       return logical_extents / physical_extents;
+}
+
+/*
+ * The physical dimension specified by the HID descriptor is likely not in
+ * the "100th of a mm" units expected by wacom_calculate_touch_res. This
+ * function adjusts the value of [xy]_phy based on the unit and exponent
+ * provided by the HID descriptor. If an error occurs durring conversion
+ * (e.g. from the unit being left unspecified) [xy]_phy is not modified.
+ */
+static void wacom_fix_phy_from_hid(struct wacom_features *features)
+{
+       int xres = wacom_calc_hid_res(features->x_max, features->x_phy,
+                                       features->unit, features->unitExpo);
+       int yres = wacom_calc_hid_res(features->y_max, features->y_phy,
+                                       features->unit, features->unitExpo);
+
+       if (xres > 0 && yres > 0) {
+               features->x_phy = (100 * features->x_max) / xres;
+               features->y_phy = (100 * features->y_max) / yres;
+       }
+}
+
 /*
  * Static values for max X/Y and resolution of Pen interface is stored in
  * features. This mean physical size of active area can be computed.
@@ -432,56 +502,52 @@ static int wacom_parse_hid(struct usb_interface *intf,
        return result;
 }
 
-static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features)
+static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int length, int mode)
 {
        unsigned char *rep_data;
-       int limit = 0, report_id = 2;
-       int error = -ENOMEM;
+       int error = -ENOMEM, limit = 0;
 
-       rep_data = kmalloc(4, GFP_KERNEL);
+       rep_data = kzalloc(length, GFP_KERNEL);
        if (!rep_data)
                return error;
 
-       /* ask to report Wacom data */
+       rep_data[0] = report_id;
+       rep_data[1] = mode;
+
+       do {
+               error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
+                                        report_id, rep_data, length, 1);
+               if (error >= 0)
+                       error = wacom_get_report(intf, WAC_HID_FEATURE_REPORT,
+                                                report_id, rep_data, length, 1);
+       } while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES);
+
+       kfree(rep_data);
+
+       return error < 0 ? error : 0;
+}
+
+/*
+ * Switch the tablet into its most-capable mode. Wacom tablets are
+ * typically configured to power-up in a mode which sends mouse-like
+ * reports to the OS. To get absolute position, pressure data, etc.
+ * from the tablet, it is necessary to switch the tablet out of this
+ * mode and into one which sends the full range of tablet data.
+ */
+static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features)
+{
        if (features->device_type == BTN_TOOL_FINGER) {
-               /* if it is an MT Tablet PC touch */
                if (features->type > TABLETPC) {
-                       do {
-                               rep_data[0] = 3;
-                               rep_data[1] = 4;
-                               rep_data[2] = 0;
-                               rep_data[3] = 0;
-                               report_id = 3;
-                               error = wacom_set_report(intf,
-                                                        WAC_HID_FEATURE_REPORT,
-                                                        report_id,
-                                                        rep_data, 4, 1);
-                               if (error >= 0)
-                                       error = wacom_get_report(intf,
-                                                       WAC_HID_FEATURE_REPORT,
-                                                       report_id,
-                                                       rep_data, 4, 1);
-                       } while ((error < 0 || rep_data[1] != 4) &&
-                                limit++ < WAC_MSG_RETRIES);
+                       /* MT Tablet PC touch */
+                       return wacom_set_device_mode(intf, 3, 4, 4);
+               }
+       } else if (features->device_type == BTN_TOOL_PEN) {
+               if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
+                       return wacom_set_device_mode(intf, 2, 2, 2);
                }
-       } else if (features->type <= BAMBOO_PT &&
-                  features->type != WIRELESS &&
-                  features->device_type == BTN_TOOL_PEN) {
-               do {
-                       rep_data[0] = 2;
-                       rep_data[1] = 2;
-                       error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
-                                                report_id, rep_data, 2, 1);
-                       if (error >= 0)
-                               error = wacom_get_report(intf,
-                                               WAC_HID_FEATURE_REPORT,
-                                               report_id, rep_data, 2, 1);
-               } while ((error < 0 || rep_data[1] != 2) && limit++ < WAC_MSG_RETRIES);
        }
 
-       kfree(rep_data);
-
-       return error < 0 ? error : 0;
+       return 0;
 }
 
 static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
@@ -531,6 +597,7 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
        error = wacom_parse_hid(intf, hid_desc, features);
        if (error)
                goto out;
+       wacom_fix_phy_from_hid(features);
 
  out:
        return error;
index 08b462b6c0d8c9f9e8e8ee1c0dbc70127c434583..c3468c8dbd891865b0fd2b4a8159f499ea8df1f1 100644 (file)
 #define WACOM_INTUOS_RES       100
 #define WACOM_INTUOS3_RES      200
 
+/* Scale factor relating reported contact size to logical contact area.
+ * 2^14/pi is a good approximation on Intuos5 and 3rd-gen Bamboo
+ */
+#define WACOM_CONTACT_AREA_SCALE 2607
+
 static int wacom_penpartner_irq(struct wacom_wac *wacom)
 {
        unsigned char *data = wacom->data;
@@ -326,7 +331,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
 
        /* Enter report */
        if ((data[1] & 0xfc) == 0xc0) {
-               if (features->type >= INTUOS5S && features->type <= INTUOS5L)
+               if (features->quirks == WACOM_QUIRK_MULTI_INPUT)
                        wacom->shared->stylus_in_proximity = true;
 
                /* serial number of the tool */
@@ -414,7 +419,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
 
        /* Exit report */
        if ((data[1] & 0xfe) == 0x80) {
-               if (features->type >= INTUOS5S && features->type <= INTUOS5L)
+               if (features->quirks == WACOM_QUIRK_MULTI_INPUT)
                        wacom->shared->stylus_in_proximity = false;
 
                /*
@@ -1043,11 +1048,19 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
        if (touch) {
                int x = (data[2] << 4) | (data[4] >> 4);
                int y = (data[3] << 4) | (data[4] & 0x0f);
-               int w = data[6];
+               int a = data[5];
+
+               // "a" is a scaled-down area which we assume is roughly
+               // circular and which can be described as: a=(pi*r^2)/C.
+               int x_res  = input_abs_get_res(input, ABS_X);
+               int y_res  = input_abs_get_res(input, ABS_Y);
+               int width  = 2 * int_sqrt(a * WACOM_CONTACT_AREA_SCALE);
+               int height = width * y_res / x_res;
 
                input_report_abs(input, ABS_MT_POSITION_X, x);
                input_report_abs(input, ABS_MT_POSITION_Y, y);
-               input_report_abs(input, ABS_MT_TOUCH_MAJOR, w);
+               input_report_abs(input, ABS_MT_TOUCH_MAJOR, width);
+               input_report_abs(input, ABS_MT_TOUCH_MINOR, height);
        }
 }
 
@@ -1533,7 +1546,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
                        input_mt_init_slots(input_dev, features->touch_max, 0);
 
                        input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
-                                            0, 255, 0, 0);
+                                            0, features->x_max, 0, 0);
+                       input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR,
+                                            0, features->y_max, 0, 0);
 
                        input_set_abs_params(input_dev, ABS_MT_POSITION_X,
                                             0, features->x_max,
@@ -1641,7 +1656,10 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 
                                input_set_abs_params(input_dev,
                                                     ABS_MT_TOUCH_MAJOR,
-                                                    0, 255, 0, 0);
+                                                    0, features->x_max, 0, 0);
+                               input_set_abs_params(input_dev,
+                                                    ABS_MT_TOUCH_MINOR,
+                                                    0, features->y_max, 0, 0);
                        }
 
                        input_set_abs_params(input_dev, ABS_MT_POSITION_X,
index e92615d0b1b0330b334b1a54a603354fdc3a8960..1df2396af0085b4e719e7d25ec5ea58d9cc2034a 100644 (file)
@@ -320,10 +320,8 @@ static bool mxt_object_writable(unsigned int type)
 static void mxt_dump_message(struct device *dev,
                             struct mxt_message *message)
 {
-       dev_dbg(dev, "reportid: %u\tmessage: %02x %02x %02x %02x %02x %02x %02x\n",
-               message->reportid, message->message[0], message->message[1],
-               message->message[2], message->message[3], message->message[4],
-               message->message[5], message->message[6]);
+       dev_dbg(dev, "reportid: %u\tmessage: %*ph\n",
+               message->reportid, 7, message->message);
 }
 
 static int mxt_check_bootloader(struct i2c_client *client,
index a1e76015082177c25a7befa7c401d8ea1713446e..61d78fa03b1aa0438553f57f4b4c01686b141609 100644 (file)
@@ -595,7 +595,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
                        j = ipc->num / (sizeof(long) * 8);
                        i = ipc->num % (sizeof(long) * 8);
                        if (j < 8)
-                               protos[j] |= (0x1 << i);
+                               protos[j] |= (1UL << i);
                        ipc = ipc->next;
                }
                if ((r = set_arg(argp, protos, 8 * sizeof(long))))
index 16578d3b52bb8ba6e43f8437c7141a0b6fd0ab87..f508defc0d961f8390f6e008f54a64ebc0f3acc0 100644 (file)
@@ -63,6 +63,17 @@ config LEDS_LM3533
          hardware-accelerated blinking with maximum on and off periods of 9.8
          and 77 seconds respectively.
 
+config LEDS_LM3642
+       tristate "LED support for LM3642 Chip"
+       depends on LEDS_CLASS && I2C
+       select REGMAP_I2C
+       help
+         This option enables support for LEDs connected to LM3642.
+         The LM3642 is a 4MHz fixed-frequency synchronous boost
+         converter plus 1.5A constant current driver for a high-current
+         white LED.
+
+
 config LEDS_LOCOMO
        tristate "LED Support for Locomo device"
        depends on LEDS_CLASS
@@ -192,11 +203,12 @@ config LEDS_LP5521
          programming the engines.
 
 config LEDS_LP5523
-       tristate "LED Support for N.S. LP5523 LED driver chip"
+       tristate "LED Support for TI/National LP5523/55231 LED driver chip"
        depends on LEDS_CLASS && I2C
        help
-         If you say yes here you get support for the National Semiconductor
-         LP5523 LED driver. It is 9 channel chip with programmable engines.
+         If you say yes here you get support for TI/National Semiconductor
+         LP5523/55231 LED driver.
+         It is 9 channel chip with programmable engines.
          Driver provides direct control via LED class and interface for
          programming the engines.
 
@@ -422,13 +434,13 @@ config LEDS_MAX8997
          This option enables support for on-chip LED drivers on
          MAXIM MAX8997 PMIC.
 
-config LEDS_LM3556
-       tristate "LED support for LM3556 Chip"
+config LEDS_LM355x
+       tristate "LED support for LM355x Chips, LM3554 and LM3556"
        depends on LEDS_CLASS && I2C
        select REGMAP_I2C
        help
-         This option enables support for LEDs connected to LM3556.
-         LM3556 includes Torch, Flash and Indicator functions.
+         This option enables support for LEDs connected to LM355x.
+         LM355x includes Torch, Flash and Indicator functions.
 
 config LEDS_OT200
        tristate "LED support for the Bachmann OT200"
index a9b627c4f8ba94c5b1574a7f81800bc20d80c368..3fb9641b619411ba058ca3cbd6c584deeeb20a19 100644 (file)
@@ -11,6 +11,7 @@ obj-$(CONFIG_LEDS_BD2802)             += leds-bd2802.o
 obj-$(CONFIG_LEDS_LOCOMO)              += leds-locomo.o
 obj-$(CONFIG_LEDS_LM3530)              += leds-lm3530.o
 obj-$(CONFIG_LEDS_LM3533)              += leds-lm3533.o
+obj-$(CONFIG_LEDS_LM3642)              += leds-lm3642.o
 obj-$(CONFIG_LEDS_MIKROTIK_RB532)      += leds-rb532.o
 obj-$(CONFIG_LEDS_S3C24XX)             += leds-s3c24xx.o
 obj-$(CONFIG_LEDS_NET48XX)             += leds-net48xx.o
@@ -48,7 +49,7 @@ obj-$(CONFIG_LEDS_NETXBIG)            += leds-netxbig.o
 obj-$(CONFIG_LEDS_ASIC3)               += leds-asic3.o
 obj-$(CONFIG_LEDS_RENESAS_TPU)         += leds-renesas-tpu.o
 obj-$(CONFIG_LEDS_MAX8997)             += leds-max8997.o
-obj-$(CONFIG_LEDS_LM3556)              += leds-lm3556.o
+obj-$(CONFIG_LEDS_LM355x)              += leds-lm355x.o
 obj-$(CONFIG_LEDS_BLINKM)              += leds-blinkm.o
 
 # LED SPI Drivers
index c599095bc00556f9c79b3444dd2933f89ca0496a..48cce18e9d6d5d8c97e89ab953b586e5107a75e0 100644 (file)
@@ -124,6 +124,16 @@ static void led_timer_function(unsigned long data)
        mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
 }
 
+static void set_brightness_delayed(struct work_struct *ws)
+{
+       struct led_classdev *led_cdev =
+               container_of(ws, struct led_classdev, set_brightness_work);
+
+       led_stop_software_blink(led_cdev);
+
+       __led_set_brightness(led_cdev, led_cdev->delayed_set_value);
+}
+
 /**
  * led_classdev_suspend - suspend an led_classdev.
  * @led_cdev: the led_classdev to suspend.
@@ -191,6 +201,8 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
 
        led_update_brightness(led_cdev);
 
+       INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed);
+
        init_timer(&led_cdev->blink_timer);
        led_cdev->blink_timer.function = led_timer_function;
        led_cdev->blink_timer.data = (unsigned long)led_cdev;
@@ -221,7 +233,10 @@ void led_classdev_unregister(struct led_classdev *led_cdev)
        up_write(&led_cdev->trigger_lock);
 #endif
 
+       cancel_work_sync(&led_cdev->set_brightness_work);
+
        /* Stop blinking */
+       led_stop_software_blink(led_cdev);
        led_set_brightness(led_cdev, LED_OFF);
 
        device_unregister(led_cdev->dev);
index 2ab05af3de31ab188fb0300befb04a708702637f..ce8921a753a32107b30915f8c2ae2b837310d33d 100644 (file)
@@ -103,13 +103,23 @@ void led_blink_set_oneshot(struct led_classdev *led_cdev,
 }
 EXPORT_SYMBOL(led_blink_set_oneshot);
 
-void led_set_brightness(struct led_classdev *led_cdev,
-                       enum led_brightness brightness)
+void led_stop_software_blink(struct led_classdev *led_cdev)
 {
-       /* stop and clear soft-blink timer */
        del_timer_sync(&led_cdev->blink_timer);
        led_cdev->blink_delay_on = 0;
        led_cdev->blink_delay_off = 0;
+}
+EXPORT_SYMBOL_GPL(led_stop_software_blink);
+
+void led_set_brightness(struct led_classdev *led_cdev,
+                       enum led_brightness brightness)
+{
+       /* delay brightness setting if need to stop soft-blink timer */
+       if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) {
+               led_cdev->delayed_set_value = brightness;
+               schedule_work(&led_cdev->set_brightness_work);
+               return;
+       }
 
        __led_set_brightness(led_cdev, brightness);
 }
index 363975b3c925989badc13117d7a5309a5860a1b8..262eb41937102c7814ad95c685393981057d6453 100644 (file)
@@ -102,6 +102,12 @@ EXPORT_SYMBOL_GPL(led_trigger_show);
 void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
 {
        unsigned long flags;
+       char *event = NULL;
+       char *envp[2];
+       const char *name;
+
+       name = trig ? trig->name : "none";
+       event = kasprintf(GFP_KERNEL, "TRIGGER=%s", name);
 
        /* Remove any existing trigger */
        if (led_cdev->trigger) {
@@ -109,6 +115,8 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
                list_del(&led_cdev->trig_list);
                write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock,
                        flags);
+               cancel_work_sync(&led_cdev->set_brightness_work);
+               led_stop_software_blink(led_cdev);
                if (led_cdev->trigger->deactivate)
                        led_cdev->trigger->deactivate(led_cdev);
                led_cdev->trigger = NULL;
@@ -122,6 +130,13 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
                if (trig->activate)
                        trig->activate(led_cdev);
        }
+
+       if (event) {
+               envp[0] = event;
+               envp[1] = NULL;
+               kobject_uevent_env(&led_cdev->dev->kobj, KOBJ_CHANGE, envp);
+               kfree(event);
+       }
 }
 EXPORT_SYMBOL_GPL(led_trigger_set);
 
@@ -224,7 +239,7 @@ void led_trigger_event(struct led_trigger *trig,
                struct led_classdev *led_cdev;
 
                led_cdev = list_entry(entry, struct led_classdev, trig_list);
-               __led_set_brightness(led_cdev, brightness);
+               led_set_brightness(led_cdev, brightness);
        }
        read_unlock(&trig->leddev_list_lock);
 }
index 1ed1677c916f260285d0acefa255ef7adf337802..e024b0b1c3b1e11fbae8dc6de27006d1cb1bc0b6 100644 (file)
@@ -31,7 +31,7 @@ static int __init clevo_mail_led_dmi_callback(const struct dmi_system_id *id)
 }
 
 /*
- * struct mail_led_whitelist - List of known good models
+ * struct clevo_mail_led_dmi_table - List of known good models
  *
  * Contains the known good models this driver is compatible with.
  * When adding a new model try to be as strict as possible. This
@@ -39,7 +39,7 @@ static int __init clevo_mail_led_dmi_callback(const struct dmi_system_id *id)
  * detected as working, but in reality it is not) as low as
  * possible.
  */
-static struct dmi_system_id __initdata mail_led_whitelist[] = {
+static struct dmi_system_id __initdata clevo_mail_led_dmi_table[] = {
        {
                .callback = clevo_mail_led_dmi_callback,
                .ident = "Clevo D410J",
@@ -59,11 +59,10 @@ static struct dmi_system_id __initdata mail_led_whitelist[] = {
        },
        {
                .callback = clevo_mail_led_dmi_callback,
-               .ident = "Positivo Mobile",
+               .ident = "Clevo M5x0V",
                .matches = {
                        DMI_MATCH(DMI_BOARD_VENDOR, "CLEVO Co. "),
                        DMI_MATCH(DMI_BOARD_NAME, "M5X0V "),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Positivo Mobile"),
                        DMI_MATCH(DMI_PRODUCT_VERSION, "VT6198")
                }
        },
@@ -89,6 +88,7 @@ static struct dmi_system_id __initdata mail_led_whitelist[] = {
        },
        { }
 };
+MODULE_DEVICE_TABLE(dmi, clevo_mail_led_dmi_table);
 
 static void clevo_mail_led_set(struct led_classdev *led_cdev,
                                enum led_brightness value)
@@ -180,7 +180,7 @@ static int __init clevo_mail_led_init(void)
 
        /* Check with the help of DMI if we are running on supported hardware */
        if (!nodetect) {
-               count = dmi_check_system(mail_led_whitelist);
+               count = dmi_check_system(clevo_mail_led_dmi_table);
        } else {
                count = 1;
                printk(KERN_ERR KBUILD_MODNAME ": Skipping DMI detection. "
index c032b2180340e123c3017e893185c34087fcdbde..087d1e66f4f76e754aea4d21a149e7eb8633a060 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
 
 struct gpio_led_data {
        struct led_classdev cdev;
@@ -170,11 +171,10 @@ static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_dev
 {
        struct device_node *np = pdev->dev.of_node, *child;
        struct gpio_leds_priv *priv;
-       int count = 0, ret;
+       int count, ret;
 
        /* count LEDs in this device, so we know how much to allocate */
-       for_each_child_of_node(np, child)
-               count++;
+       count = of_get_child_count(np);
        if (!count)
                return NULL;
 
@@ -228,7 +228,6 @@ static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_dev
 {
        return NULL;
 }
-#define of_gpio_leds_match NULL
 #endif /* CONFIG_OF_GPIO */
 
 
@@ -236,8 +235,14 @@ static int __devinit gpio_led_probe(struct platform_device *pdev)
 {
        struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
        struct gpio_leds_priv *priv;
+       struct pinctrl *pinctrl;
        int i, ret = 0;
 
+       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+       if (IS_ERR(pinctrl))
+               dev_warn(&pdev->dev,
+                       "pins are not configured from the driver\n");
+
        if (pdata && pdata->num_leds) {
                priv = devm_kzalloc(&pdev->dev,
                                sizeof_gpio_leds_priv(pdata->num_leds),
@@ -270,13 +275,13 @@ static int __devinit gpio_led_probe(struct platform_device *pdev)
 
 static int __devexit gpio_led_remove(struct platform_device *pdev)
 {
-       struct gpio_leds_priv *priv = dev_get_drvdata(&pdev->dev);
+       struct gpio_leds_priv *priv = platform_get_drvdata(pdev);
        int i;
 
        for (i = 0; i < priv->num_leds; i++)
                delete_gpio_led(&priv->leds[i]);
 
-       dev_set_drvdata(&pdev->dev, NULL);
+       platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
@@ -287,7 +292,7 @@ static struct platform_driver gpio_led_driver = {
        .driver         = {
                .name   = "leds-gpio",
                .owner  = THIS_MODULE,
-               .of_match_table = of_gpio_leds_match,
+               .of_match_table = of_match_ptr(of_gpio_leds_match),
        },
 };
 
index 23637bdb275d0b93d0e5db08f75145295b38af91..b26306f6724dcebc1605625405625aeebe022298 100644 (file)
@@ -150,7 +150,7 @@ static int lm3530_get_mode_from_str(const char *str)
                if (sysfs_streq(str, mode_map[i].mode))
                        return mode_map[i].mode_val;
 
-       return -1;
+       return -EINVAL;
 }
 
 static void lm3530_als_configure(struct lm3530_platform_data *pdata,
@@ -358,7 +358,7 @@ static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
        mode = lm3530_get_mode_from_str(buf);
        if (mode < 0) {
                dev_err(dev, "Invalid mode\n");
-               return -EINVAL;
+               return mode;
        }
 
        drvdata->mode = mode;
@@ -416,7 +416,7 @@ static int __devinit lm3530_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, drvdata);
 
-       drvdata->regulator = regulator_get(&client->dev, "vin");
+       drvdata->regulator = devm_regulator_get(&client->dev, "vin");
        if (IS_ERR(drvdata->regulator)) {
                dev_err(&client->dev, "regulator get failed\n");
                err = PTR_ERR(drvdata->regulator);
@@ -429,15 +429,13 @@ static int __devinit lm3530_probe(struct i2c_client *client,
                if (err < 0) {
                        dev_err(&client->dev,
                                "Register Init failed: %d\n", err);
-                       err = -ENODEV;
-                       goto err_reg_init;
+                       return err;
                }
        }
        err = led_classdev_register(&client->dev, &drvdata->led_dev);
        if (err < 0) {
                dev_err(&client->dev, "Register led class failed: %d\n", err);
-               err = -ENODEV;
-               goto err_class_register;
+               return err;
        }
 
        err = device_create_file(drvdata->led_dev.dev, &dev_attr_mode);
@@ -451,9 +449,6 @@ static int __devinit lm3530_probe(struct i2c_client *client,
 
 err_create_file:
        led_classdev_unregister(&drvdata->led_dev);
-err_class_register:
-err_reg_init:
-       regulator_put(drvdata->regulator);
        return err;
 }
 
@@ -465,7 +460,6 @@ static int __devexit lm3530_remove(struct i2c_client *client)
 
        if (drvdata->enable)
                regulator_disable(drvdata->regulator);
-       regulator_put(drvdata->regulator);
        led_classdev_unregister(&drvdata->led_dev);
        return 0;
 }
diff --git a/drivers/leds/leds-lm3556.c b/drivers/leds/leds-lm3556.c
deleted file mode 100644 (file)
index 3062abd..0000000
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * Simple driver for Texas Instruments LM3556 LED Flash driver chip (Rev0x03)
- * Copyright (C) 2012 Texas Instruments
- *
- * 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.
- *
- * Please refer Documentation/leds/leds-lm3556.txt file.
- */
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/leds.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/fs.h>
-#include <linux/regmap.h>
-#include <linux/platform_data/leds-lm3556.h>
-
-#define REG_FILT_TIME                  (0x0)
-#define REG_IVFM_MODE                  (0x1)
-#define REG_NTC                                (0x2)
-#define REG_INDIC_TIME                 (0x3)
-#define REG_INDIC_BLINK                        (0x4)
-#define REG_INDIC_PERIOD               (0x5)
-#define REG_TORCH_TIME                 (0x6)
-#define REG_CONF                       (0x7)
-#define REG_FLASH                      (0x8)
-#define REG_I_CTRL                     (0x9)
-#define REG_ENABLE                     (0xA)
-#define REG_FLAG                       (0xB)
-#define REG_MAX                                (0xB)
-
-#define IVFM_FILTER_TIME_SHIFT         (3)
-#define UVLO_EN_SHIFT                  (7)
-#define HYSTERSIS_SHIFT                        (5)
-#define IVM_D_TH_SHIFT                 (2)
-#define IVFM_ADJ_MODE_SHIFT            (0)
-#define NTC_EVENT_LVL_SHIFT            (5)
-#define NTC_TRIP_TH_SHIFT              (2)
-#define NTC_BIAS_I_LVL_SHIFT           (0)
-#define INDIC_RAMP_UP_TIME_SHIFT       (3)
-#define INDIC_RAMP_DN_TIME_SHIFT       (0)
-#define INDIC_N_BLANK_SHIFT            (4)
-#define INDIC_PULSE_TIME_SHIFT         (0)
-#define INDIC_N_PERIOD_SHIFT           (0)
-#define TORCH_RAMP_UP_TIME_SHIFT       (3)
-#define TORCH_RAMP_DN_TIME_SHIFT       (0)
-#define STROBE_USUAGE_SHIFT            (7)
-#define STROBE_PIN_POLARITY_SHIFT      (6)
-#define TORCH_PIN_POLARITY_SHIFT       (5)
-#define TX_PIN_POLARITY_SHIFT          (4)
-#define TX_EVENT_LVL_SHIFT             (3)
-#define IVFM_EN_SHIFT                  (2)
-#define NTC_MODE_SHIFT                 (1)
-#define INDIC_MODE_SHIFT               (0)
-#define INDUCTOR_I_LIMIT_SHIFT         (6)
-#define FLASH_RAMP_TIME_SHIFT          (3)
-#define FLASH_TOUT_TIME_SHIFT          (0)
-#define TORCH_I_SHIFT                  (4)
-#define FLASH_I_SHIFT                  (0)
-#define NTC_EN_SHIFT                   (7)
-#define TX_PIN_EN_SHIFT                        (6)
-#define STROBE_PIN_EN_SHIFT            (5)
-#define TORCH_PIN_EN_SHIFT             (4)
-#define PRECHG_MODE_EN_SHIFT           (3)
-#define PASS_MODE_ONLY_EN_SHIFT                (2)
-#define MODE_BITS_SHIFT                        (0)
-
-#define IVFM_FILTER_TIME_MASK          (0x3)
-#define UVLO_EN_MASK                   (0x1)
-#define HYSTERSIS_MASK                 (0x3)
-#define IVM_D_TH_MASK                  (0x7)
-#define IVFM_ADJ_MODE_MASK             (0x3)
-#define NTC_EVENT_LVL_MASK             (0x1)
-#define NTC_TRIP_TH_MASK               (0x7)
-#define NTC_BIAS_I_LVL_MASK            (0x3)
-#define INDIC_RAMP_UP_TIME_MASK                (0x7)
-#define INDIC_RAMP_DN_TIME_MASK                (0x7)
-#define INDIC_N_BLANK_MASK             (0x7)
-#define INDIC_PULSE_TIME_MASK          (0x7)
-#define INDIC_N_PERIOD_MASK            (0x7)
-#define TORCH_RAMP_UP_TIME_MASK                (0x7)
-#define TORCH_RAMP_DN_TIME_MASK                (0x7)
-#define STROBE_USUAGE_MASK             (0x1)
-#define STROBE_PIN_POLARITY_MASK       (0x1)
-#define TORCH_PIN_POLARITY_MASK                (0x1)
-#define TX_PIN_POLARITY_MASK           (0x1)
-#define TX_EVENT_LVL_MASK              (0x1)
-#define IVFM_EN_MASK                   (0x1)
-#define NTC_MODE_MASK                  (0x1)
-#define INDIC_MODE_MASK                        (0x1)
-#define INDUCTOR_I_LIMIT_MASK          (0x3)
-#define FLASH_RAMP_TIME_MASK           (0x7)
-#define FLASH_TOUT_TIME_MASK           (0x7)
-#define TORCH_I_MASK                   (0x7)
-#define FLASH_I_MASK                   (0xF)
-#define NTC_EN_MASK                    (0x1)
-#define TX_PIN_EN_MASK                 (0x1)
-#define STROBE_PIN_EN_MASK             (0x1)
-#define TORCH_PIN_EN_MASK              (0x1)
-#define PRECHG_MODE_EN_MASK            (0x1)
-#define PASS_MODE_ONLY_EN_MASK         (0x1)
-#define MODE_BITS_MASK                 (0x13)
-#define EX_PIN_CONTROL_MASK            (0xF1)
-#define EX_PIN_ENABLE_MASK             (0x70)
-
-enum lm3556_indic_pulse_time {
-       PULSE_TIME_0_MS = 0,
-       PULSE_TIME_32_MS,
-       PULSE_TIME_64_MS,
-       PULSE_TIME_92_MS,
-       PULSE_TIME_128_MS,
-       PULSE_TIME_160_MS,
-       PULSE_TIME_196_MS,
-       PULSE_TIME_224_MS,
-       PULSE_TIME_256_MS,
-       PULSE_TIME_288_MS,
-       PULSE_TIME_320_MS,
-       PULSE_TIME_352_MS,
-       PULSE_TIME_384_MS,
-       PULSE_TIME_416_MS,
-       PULSE_TIME_448_MS,
-       PULSE_TIME_480_MS,
-};
-
-enum lm3556_indic_n_blank {
-       INDIC_N_BLANK_0 = 0,
-       INDIC_N_BLANK_1,
-       INDIC_N_BLANK_2,
-       INDIC_N_BLANK_3,
-       INDIC_N_BLANK_4,
-       INDIC_N_BLANK_5,
-       INDIC_N_BLANK_6,
-       INDIC_N_BLANK_7,
-       INDIC_N_BLANK_8,
-       INDIC_N_BLANK_9,
-       INDIC_N_BLANK_10,
-       INDIC_N_BLANK_11,
-       INDIC_N_BLANK_12,
-       INDIC_N_BLANK_13,
-       INDIC_N_BLANK_14,
-       INDIC_N_BLANK_15,
-};
-
-enum lm3556_indic_period {
-       INDIC_PERIOD_0 = 0,
-       INDIC_PERIOD_1,
-       INDIC_PERIOD_2,
-       INDIC_PERIOD_3,
-       INDIC_PERIOD_4,
-       INDIC_PERIOD_5,
-       INDIC_PERIOD_6,
-       INDIC_PERIOD_7,
-};
-
-enum lm3556_mode {
-       MODES_STASNDBY = 0,
-       MODES_INDIC,
-       MODES_TORCH,
-       MODES_FLASH
-};
-
-#define INDIC_PATTERN_SIZE 4
-
-struct indicator {
-       u8 blinking;
-       u8 period_cnt;
-};
-
-struct lm3556_chip_data {
-       struct device *dev;
-
-       struct led_classdev cdev_flash;
-       struct led_classdev cdev_torch;
-       struct led_classdev cdev_indicator;
-
-       struct lm3556_platform_data *pdata;
-       struct regmap *regmap;
-       struct mutex lock;
-
-       unsigned int last_flag;
-};
-
-/* indicator pattern */
-static struct indicator indicator_pattern[INDIC_PATTERN_SIZE] = {
-       [0] = {(INDIC_N_BLANK_1 << INDIC_N_BLANK_SHIFT)
-              | PULSE_TIME_32_MS, INDIC_PERIOD_1},
-       [1] = {(INDIC_N_BLANK_15 << INDIC_N_BLANK_SHIFT)
-              | PULSE_TIME_32_MS, INDIC_PERIOD_2},
-       [2] = {(INDIC_N_BLANK_10 << INDIC_N_BLANK_SHIFT)
-              | PULSE_TIME_32_MS, INDIC_PERIOD_4},
-       [3] = {(INDIC_N_BLANK_5 << INDIC_N_BLANK_SHIFT)
-              | PULSE_TIME_32_MS, INDIC_PERIOD_7},
-};
-
-/* chip initialize */
-static int __devinit lm3556_chip_init(struct lm3556_chip_data *chip)
-{
-       unsigned int reg_val;
-       int ret;
-       struct lm3556_platform_data *pdata = chip->pdata;
-
-       /* set config register */
-       ret = regmap_read(chip->regmap, REG_CONF, &reg_val);
-       if (ret < 0) {
-               dev_err(chip->dev, "Failed to read REG_CONF Register\n");
-               goto out;
-       }
-
-       reg_val &= (~EX_PIN_CONTROL_MASK);
-       reg_val |= ((pdata->torch_pin_polarity & 0x01)
-                   << TORCH_PIN_POLARITY_SHIFT);
-       reg_val |= ((pdata->strobe_usuage & 0x01) << STROBE_USUAGE_SHIFT);
-       reg_val |= ((pdata->strobe_pin_polarity & 0x01)
-                   << STROBE_PIN_POLARITY_SHIFT);
-       reg_val |= ((pdata->tx_pin_polarity & 0x01) << TX_PIN_POLARITY_SHIFT);
-       reg_val |= ((pdata->indicator_mode & 0x01) << INDIC_MODE_SHIFT);
-
-       ret = regmap_write(chip->regmap, REG_CONF, reg_val);
-       if (ret < 0) {
-               dev_err(chip->dev, "Failed to write REG_CONF Regisgter\n");
-               goto out;
-       }
-
-       /* set enable register */
-       ret = regmap_read(chip->regmap, REG_ENABLE, &reg_val);
-       if (ret < 0) {
-               dev_err(chip->dev, "Failed to read REG_ENABLE Register\n");
-               goto out;
-       }
-
-       reg_val &= (~EX_PIN_ENABLE_MASK);
-       reg_val |= ((pdata->torch_pin_en & 0x01) << TORCH_PIN_EN_SHIFT);
-       reg_val |= ((pdata->strobe_pin_en & 0x01) << STROBE_PIN_EN_SHIFT);
-       reg_val |= ((pdata->tx_pin_en & 0x01) << TX_PIN_EN_SHIFT);
-
-       ret = regmap_write(chip->regmap, REG_ENABLE, reg_val);
-       if (ret < 0) {
-               dev_err(chip->dev, "Failed to write REG_ENABLE Regisgter\n");
-               goto out;
-       }
-
-out:
-       return ret;
-}
-
-/* chip control */
-static int lm3556_control(struct lm3556_chip_data *chip,
-                         u8 brightness, enum lm3556_mode opmode)
-{
-       int ret;
-       struct lm3556_platform_data *pdata = chip->pdata;
-
-       ret = regmap_read(chip->regmap, REG_FLAG, &chip->last_flag);
-       if (ret < 0) {
-               dev_err(chip->dev, "Failed to read REG_FLAG Register\n");
-               goto out;
-       }
-
-       if (chip->last_flag)
-               dev_info(chip->dev, "Last FLAG is 0x%x\n", chip->last_flag);
-
-       /* brightness 0 means off-state */
-       if (!brightness)
-               opmode = MODES_STASNDBY;
-
-       switch (opmode) {
-       case MODES_TORCH:
-               ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
-                                        TORCH_I_MASK << TORCH_I_SHIFT,
-                                        (brightness - 1) << TORCH_I_SHIFT);
-
-               if (pdata->torch_pin_en)
-                       opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
-               break;
-
-       case MODES_FLASH:
-               ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
-                                        FLASH_I_MASK << FLASH_I_SHIFT,
-                                        (brightness - 1) << FLASH_I_SHIFT);
-               break;
-
-       case MODES_INDIC:
-               ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
-                                        TORCH_I_MASK << TORCH_I_SHIFT,
-                                        (brightness - 1) << TORCH_I_SHIFT);
-               break;
-
-       case MODES_STASNDBY:
-               if (pdata->torch_pin_en)
-                       opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
-               break;
-
-       default:
-               return ret;
-       }
-       if (ret < 0) {
-               dev_err(chip->dev, "Failed to write REG_I_CTRL Register\n");
-               goto out;
-       }
-       ret = regmap_update_bits(chip->regmap, REG_ENABLE,
-                                MODE_BITS_MASK << MODE_BITS_SHIFT,
-                                opmode << MODE_BITS_SHIFT);
-
-out:
-       return ret;
-}
-
-/* torch */
-static void lm3556_torch_brightness_set(struct led_classdev *cdev,
-                                       enum led_brightness brightness)
-{
-       struct lm3556_chip_data *chip =
-           container_of(cdev, struct lm3556_chip_data, cdev_torch);
-
-       mutex_lock(&chip->lock);
-       lm3556_control(chip, brightness, MODES_TORCH);
-       mutex_unlock(&chip->lock);
-}
-
-/* flash */
-static void lm3556_strobe_brightness_set(struct led_classdev *cdev,
-                                        enum led_brightness brightness)
-{
-       struct lm3556_chip_data *chip =
-           container_of(cdev, struct lm3556_chip_data, cdev_flash);
-
-       mutex_lock(&chip->lock);
-       lm3556_control(chip, brightness, MODES_FLASH);
-       mutex_unlock(&chip->lock);
-}
-
-/* indicator */
-static void lm3556_indicator_brightness_set(struct led_classdev *cdev,
-                                           enum led_brightness brightness)
-{
-       struct lm3556_chip_data *chip =
-           container_of(cdev, struct lm3556_chip_data, cdev_indicator);
-
-       mutex_lock(&chip->lock);
-       lm3556_control(chip, brightness, MODES_INDIC);
-       mutex_unlock(&chip->lock);
-}
-
-/* indicator pattern */
-static ssize_t lm3556_indicator_pattern_store(struct device *dev,
-                                             struct device_attribute *devAttr,
-                                             const char *buf, size_t size)
-{
-       ssize_t ret;
-       struct led_classdev *led_cdev = dev_get_drvdata(dev);
-       struct lm3556_chip_data *chip =
-           container_of(led_cdev, struct lm3556_chip_data, cdev_indicator);
-       unsigned int state;
-
-       ret = kstrtouint(buf, 10, &state);
-       if (ret)
-               goto out;
-       if (state > INDIC_PATTERN_SIZE - 1)
-               state = INDIC_PATTERN_SIZE - 1;
-
-       ret = regmap_write(chip->regmap, REG_INDIC_BLINK,
-                          indicator_pattern[state].blinking);
-       if (ret < 0) {
-               dev_err(chip->dev, "Failed to write REG_ENABLE Regisgter\n");
-               goto out;
-       }
-
-       ret = regmap_write(chip->regmap, REG_INDIC_PERIOD,
-                          indicator_pattern[state].period_cnt);
-       if (ret < 0) {
-               dev_err(chip->dev, "Failed to write REG_ENABLE Regisgter\n");
-               goto out;
-       }
-
-       return size;
-out:
-       dev_err(chip->dev, "Indicator pattern doesn't saved\n");
-       return size;
-}
-
-static DEVICE_ATTR(pattern, 0666, NULL, lm3556_indicator_pattern_store);
-
-static const struct regmap_config lm3556_regmap = {
-       .reg_bits = 8,
-       .val_bits = 8,
-       .max_register = REG_MAX,
-};
-
-/* module initialize */
-static int __devinit lm3556_probe(struct i2c_client *client,
-                                 const struct i2c_device_id *id)
-{
-       struct lm3556_platform_data *pdata = client->dev.platform_data;
-       struct lm3556_chip_data *chip;
-
-       int err;
-
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-               dev_err(&client->dev, "i2c functionality check fail.\n");
-               return -EOPNOTSUPP;
-       }
-
-       if (pdata == NULL) {
-               dev_err(&client->dev, "Needs Platform Data.\n");
-               return -ENODATA;
-       }
-
-       chip =
-           devm_kzalloc(&client->dev, sizeof(struct lm3556_chip_data),
-                        GFP_KERNEL);
-       if (!chip)
-               return -ENOMEM;
-
-       chip->dev = &client->dev;
-       chip->pdata = pdata;
-
-       chip->regmap = devm_regmap_init_i2c(client, &lm3556_regmap);
-       if (IS_ERR(chip->regmap)) {
-               err = PTR_ERR(chip->regmap);
-               dev_err(&client->dev, "Failed to allocate register map: %d\n",
-                       err);
-               return err;
-       }
-
-       mutex_init(&chip->lock);
-       i2c_set_clientdata(client, chip);
-
-       err = lm3556_chip_init(chip);
-       if (err < 0)
-               goto err_out;
-
-       /* flash */
-       chip->cdev_flash.name = "flash";
-       chip->cdev_flash.max_brightness = 16;
-       chip->cdev_flash.brightness_set = lm3556_strobe_brightness_set;
-       err = led_classdev_register((struct device *)
-                                   &client->dev, &chip->cdev_flash);
-       if (err < 0)
-               goto err_out;
-       /* torch */
-       chip->cdev_torch.name = "torch";
-       chip->cdev_torch.max_brightness = 8;
-       chip->cdev_torch.brightness_set = lm3556_torch_brightness_set;
-       err = led_classdev_register((struct device *)
-                                   &client->dev, &chip->cdev_torch);
-       if (err < 0)
-               goto err_create_torch_file;
-       /* indicator */
-       chip->cdev_indicator.name = "indicator";
-       chip->cdev_indicator.max_brightness = 8;
-       chip->cdev_indicator.brightness_set = lm3556_indicator_brightness_set;
-       err = led_classdev_register((struct device *)
-                                   &client->dev, &chip->cdev_indicator);
-       if (err < 0)
-               goto err_create_indicator_file;
-
-       err = device_create_file(chip->cdev_indicator.dev, &dev_attr_pattern);
-       if (err < 0)
-               goto err_create_pattern_file;
-
-       dev_info(&client->dev, "LM3556 is initialized\n");
-       return 0;
-
-err_create_pattern_file:
-       led_classdev_unregister(&chip->cdev_indicator);
-err_create_indicator_file:
-       led_classdev_unregister(&chip->cdev_torch);
-err_create_torch_file:
-       led_classdev_unregister(&chip->cdev_flash);
-err_out:
-       return err;
-}
-
-static int __devexit lm3556_remove(struct i2c_client *client)
-{
-       struct lm3556_chip_data *chip = i2c_get_clientdata(client);
-
-       device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern);
-       led_classdev_unregister(&chip->cdev_indicator);
-       led_classdev_unregister(&chip->cdev_torch);
-       led_classdev_unregister(&chip->cdev_flash);
-       regmap_write(chip->regmap, REG_ENABLE, 0);
-       return 0;
-}
-
-static const struct i2c_device_id lm3556_id[] = {
-       {LM3556_NAME, 0},
-       {}
-};
-
-MODULE_DEVICE_TABLE(i2c, lm3556_id);
-
-static struct i2c_driver lm3556_i2c_driver = {
-       .driver = {
-                  .name = LM3556_NAME,
-                  .owner = THIS_MODULE,
-                  .pm = NULL,
-                  },
-       .probe = lm3556_probe,
-       .remove = __devexit_p(lm3556_remove),
-       .id_table = lm3556_id,
-};
-
-module_i2c_driver(lm3556_i2c_driver);
-
-MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3556");
-MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
-MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
new file mode 100644 (file)
index 0000000..065ec01
--- /dev/null
@@ -0,0 +1,572 @@
+/*
+* Simple driver for Texas Instruments LM355x LED Flash driver chip
+* Copyright (C) 2012 Texas Instruments
+*
+* 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/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/regmap.h>
+#include <linux/workqueue.h>
+#include <linux/platform_data/leds-lm355x.h>
+
+enum lm355x_type {
+       CHIP_LM3554 = 0,
+       CHIP_LM3556,
+};
+
+enum lm355x_regs {
+       REG_FLAG = 0,
+       REG_TORCH_CFG,
+       REG_TORCH_CTRL,
+       REG_STROBE_CFG,
+       REG_FLASH_CTRL,
+       REG_INDI_CFG,
+       REG_INDI_CTRL,
+       REG_OPMODE,
+       REG_MAX,
+};
+
+/* operation mode */
+enum lm355x_mode {
+       MODE_SHDN = 0,
+       MODE_INDIC,
+       MODE_TORCH,
+       MODE_FLASH
+};
+
+/* register map info. */
+struct lm355x_reg_data {
+       u8 regno;
+       u8 mask;
+       u8 shift;
+};
+
+struct lm355x_chip_data {
+       struct device *dev;
+       enum lm355x_type type;
+
+       struct led_classdev cdev_flash;
+       struct led_classdev cdev_torch;
+       struct led_classdev cdev_indicator;
+
+       struct work_struct work_flash;
+       struct work_struct work_torch;
+       struct work_struct work_indicator;
+
+       u8 br_flash;
+       u8 br_torch;
+       u8 br_indicator;
+
+       struct lm355x_platform_data *pdata;
+       struct regmap *regmap;
+       struct mutex lock;
+
+       unsigned int last_flag;
+       struct lm355x_reg_data *regs;
+};
+
+/* specific indicator function for lm3556 */
+enum lm3556_indic_pulse_time {
+       PULSE_TIME_0_MS = 0,
+       PULSE_TIME_32_MS,
+       PULSE_TIME_64_MS,
+       PULSE_TIME_92_MS,
+       PULSE_TIME_128_MS,
+       PULSE_TIME_160_MS,
+       PULSE_TIME_196_MS,
+       PULSE_TIME_224_MS,
+       PULSE_TIME_256_MS,
+       PULSE_TIME_288_MS,
+       PULSE_TIME_320_MS,
+       PULSE_TIME_352_MS,
+       PULSE_TIME_384_MS,
+       PULSE_TIME_416_MS,
+       PULSE_TIME_448_MS,
+       PULSE_TIME_480_MS,
+};
+
+enum lm3556_indic_n_blank {
+       INDIC_N_BLANK_0 = 0,
+       INDIC_N_BLANK_1,
+       INDIC_N_BLANK_2,
+       INDIC_N_BLANK_3,
+       INDIC_N_BLANK_4,
+       INDIC_N_BLANK_5,
+       INDIC_N_BLANK_6,
+       INDIC_N_BLANK_7,
+       INDIC_N_BLANK_8,
+       INDIC_N_BLANK_9,
+       INDIC_N_BLANK_10,
+       INDIC_N_BLANK_11,
+       INDIC_N_BLANK_12,
+       INDIC_N_BLANK_13,
+       INDIC_N_BLANK_14,
+       INDIC_N_BLANK_15,
+};
+
+enum lm3556_indic_period {
+       INDIC_PERIOD_0 = 0,
+       INDIC_PERIOD_1,
+       INDIC_PERIOD_2,
+       INDIC_PERIOD_3,
+       INDIC_PERIOD_4,
+       INDIC_PERIOD_5,
+       INDIC_PERIOD_6,
+       INDIC_PERIOD_7,
+};
+
+#define INDIC_PATTERN_SIZE 4
+
+struct indicator {
+       u8 blinking;
+       u8 period_cnt;
+};
+
+/* indicator pattern data only for lm3556 */
+static struct indicator indicator_pattern[INDIC_PATTERN_SIZE] = {
+       [0] = {(INDIC_N_BLANK_1 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_1},
+       [1] = {(INDIC_N_BLANK_15 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_2},
+       [2] = {(INDIC_N_BLANK_10 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_4},
+       [3] = {(INDIC_N_BLANK_5 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_7},
+};
+
+static struct lm355x_reg_data lm3554_regs[REG_MAX] = {
+       [REG_FLAG] = {0xD0, 0xBF, 0},
+       [REG_TORCH_CFG] = {0xE0, 0x80, 7},
+       [REG_TORCH_CTRL] = {0xA0, 0x38, 3},
+       [REG_STROBE_CFG] = {0xE0, 0x04, 2},
+       [REG_FLASH_CTRL] = {0xB0, 0x78, 3},
+       [REG_INDI_CFG] = {0xE0, 0x08, 3},
+       [REG_INDI_CTRL] = {0xA0, 0xC0, 6},
+       [REG_OPMODE] = {0xA0, 0x03, 0},
+};
+
+static struct lm355x_reg_data lm3556_regs[REG_MAX] = {
+       [REG_FLAG] = {0x0B, 0xFF, 0},
+       [REG_TORCH_CFG] = {0x0A, 0x10, 4},
+       [REG_TORCH_CTRL] = {0x09, 0x70, 4},
+       [REG_STROBE_CFG] = {0x0A, 0x20, 5},
+       [REG_FLASH_CTRL] = {0x09, 0x0F, 0},
+       [REG_INDI_CFG] = {0xFF, 0xFF, 0},
+       [REG_INDI_CTRL] = {0x09, 0x70, 4},
+       [REG_OPMODE] = {0x0A, 0x03, 0},
+};
+
+static char lm355x_name[][I2C_NAME_SIZE] = {
+       [CHIP_LM3554] = LM3554_NAME,
+       [CHIP_LM3556] = LM3556_NAME,
+};
+
+/* chip initialize */
+static int __devinit lm355x_chip_init(struct lm355x_chip_data *chip)
+{
+       int ret;
+       unsigned int reg_val;
+       struct lm355x_platform_data *pdata = chip->pdata;
+
+       /* input and output pins configuration */
+       switch (chip->type) {
+       case CHIP_LM3554:
+               reg_val = pdata->pin_tx2 | pdata->ntc_pin;
+               ret = regmap_update_bits(chip->regmap, 0xE0, 0x28, reg_val);
+               if (ret < 0)
+                       goto out;
+               reg_val = pdata->pass_mode;
+               ret = regmap_update_bits(chip->regmap, 0xA0, 0x04, reg_val);
+               if (ret < 0)
+                       goto out;
+               break;
+
+       case CHIP_LM3556:
+               reg_val = pdata->pin_tx2 | pdata->ntc_pin | pdata->pass_mode;
+               ret = regmap_update_bits(chip->regmap, 0x0A, 0xC4, reg_val);
+               if (ret < 0)
+                       goto out;
+               break;
+       default:
+               return -ENODATA;
+       }
+
+       return ret;
+out:
+       dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
+       return ret;
+}
+
+/* chip control */
+static void lm355x_control(struct lm355x_chip_data *chip,
+                          u8 brightness, enum lm355x_mode opmode)
+{
+       int ret;
+       unsigned int reg_val;
+       struct lm355x_platform_data *pdata = chip->pdata;
+       struct lm355x_reg_data *preg = chip->regs;
+
+       ret = regmap_read(chip->regmap, preg[REG_FLAG].regno, &chip->last_flag);
+       if (ret < 0)
+               goto out;
+       if (chip->last_flag & preg[REG_FLAG].mask)
+               dev_info(chip->dev, "%s Last FLAG is 0x%x\n",
+                        lm355x_name[chip->type],
+                        chip->last_flag & preg[REG_FLAG].mask);
+       /* brightness 0 means shutdown */
+       if (!brightness)
+               opmode = MODE_SHDN;
+
+       switch (opmode) {
+       case MODE_TORCH:
+               ret =
+                   regmap_update_bits(chip->regmap, preg[REG_TORCH_CTRL].regno,
+                                      preg[REG_TORCH_CTRL].mask,
+                                      (brightness - 1)
+                                      << preg[REG_TORCH_CTRL].shift);
+               if (ret < 0)
+                       goto out;
+
+               if (pdata->pin_tx1 != LM355x_PIN_TORCH_DISABLE) {
+                       ret =
+                           regmap_update_bits(chip->regmap,
+                                              preg[REG_TORCH_CFG].regno,
+                                              preg[REG_TORCH_CFG].mask,
+                                              0x01 <<
+                                              preg[REG_TORCH_CFG].shift);
+                       if (ret < 0)
+                               goto out;
+                       opmode = MODE_SHDN;
+                       dev_info(chip->dev,
+                                "torch brt is set - ext. torch pin mode\n");
+               }
+               break;
+
+       case MODE_FLASH:
+
+               ret =
+                   regmap_update_bits(chip->regmap, preg[REG_FLASH_CTRL].regno,
+                                      preg[REG_FLASH_CTRL].mask,
+                                      (brightness - 1)
+                                      << preg[REG_FLASH_CTRL].shift);
+               if (ret < 0)
+                       goto out;
+
+               if (pdata->pin_strobe != LM355x_PIN_STROBE_DISABLE) {
+                       if (chip->type == CHIP_LM3554)
+                               reg_val = 0x00;
+                       else
+                               reg_val = 0x01;
+                       ret =
+                           regmap_update_bits(chip->regmap,
+                                              preg[REG_STROBE_CFG].regno,
+                                              preg[REG_STROBE_CFG].mask,
+                                              reg_val <<
+                                              preg[REG_STROBE_CFG].shift);
+                       if (ret < 0)
+                               goto out;
+                       opmode = MODE_SHDN;
+                       dev_info(chip->dev,
+                                "flash brt is set - ext. strobe pin mode\n");
+               }
+               break;
+
+       case MODE_INDIC:
+               ret =
+                   regmap_update_bits(chip->regmap, preg[REG_INDI_CTRL].regno,
+                                      preg[REG_INDI_CTRL].mask,
+                                      (brightness - 1)
+                                      << preg[REG_INDI_CTRL].shift);
+               if (ret < 0)
+                       goto out;
+
+               if (pdata->pin_tx2 != LM355x_PIN_TX_DISABLE) {
+                       ret =
+                           regmap_update_bits(chip->regmap,
+                                              preg[REG_INDI_CFG].regno,
+                                              preg[REG_INDI_CFG].mask,
+                                              0x01 <<
+                                              preg[REG_INDI_CFG].shift);
+                       if (ret < 0)
+                               goto out;
+                       opmode = MODE_SHDN;
+               }
+               break;
+       case MODE_SHDN:
+               break;
+       default:
+               return;
+       }
+       /* operation mode control */
+       ret = regmap_update_bits(chip->regmap, preg[REG_OPMODE].regno,
+                                preg[REG_OPMODE].mask,
+                                opmode << preg[REG_OPMODE].shift);
+       if (ret < 0)
+               goto out;
+       return;
+out:
+       dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
+       return;
+}
+
+/* torch */
+static void lm355x_deferred_torch_brightness_set(struct work_struct *work)
+{
+       struct lm355x_chip_data *chip =
+           container_of(work, struct lm355x_chip_data, work_torch);
+
+       mutex_lock(&chip->lock);
+       lm355x_control(chip, chip->br_torch, MODE_TORCH);
+       mutex_unlock(&chip->lock);
+}
+
+static void lm355x_torch_brightness_set(struct led_classdev *cdev,
+                                       enum led_brightness brightness)
+{
+       struct lm355x_chip_data *chip =
+           container_of(cdev, struct lm355x_chip_data, cdev_torch);
+
+       chip->br_torch = brightness;
+       schedule_work(&chip->work_torch);
+}
+
+/* flash */
+static void lm355x_deferred_strobe_brightness_set(struct work_struct *work)
+{
+       struct lm355x_chip_data *chip =
+           container_of(work, struct lm355x_chip_data, work_flash);
+
+       mutex_lock(&chip->lock);
+       lm355x_control(chip, chip->br_flash, MODE_FLASH);
+       mutex_unlock(&chip->lock);
+}
+
+static void lm355x_strobe_brightness_set(struct led_classdev *cdev,
+                                        enum led_brightness brightness)
+{
+       struct lm355x_chip_data *chip =
+           container_of(cdev, struct lm355x_chip_data, cdev_flash);
+
+       chip->br_flash = brightness;
+       schedule_work(&chip->work_flash);
+}
+
+/* indicator */
+static void lm355x_deferred_indicator_brightness_set(struct work_struct *work)
+{
+       struct lm355x_chip_data *chip =
+           container_of(work, struct lm355x_chip_data, work_indicator);
+
+       mutex_lock(&chip->lock);
+       lm355x_control(chip, chip->br_indicator, MODE_INDIC);
+       mutex_unlock(&chip->lock);
+}
+
+static void lm355x_indicator_brightness_set(struct led_classdev *cdev,
+                                           enum led_brightness brightness)
+{
+       struct lm355x_chip_data *chip =
+           container_of(cdev, struct lm355x_chip_data, cdev_indicator);
+
+       chip->br_indicator = brightness;
+       schedule_work(&chip->work_indicator);
+}
+
+/* indicator pattern only for lm3556*/
+static ssize_t lm3556_indicator_pattern_store(struct device *dev,
+                                             struct device_attribute *devAttr,
+                                             const char *buf, size_t size)
+{
+       ssize_t ret;
+       struct led_classdev *led_cdev = dev_get_drvdata(dev);
+       struct lm355x_chip_data *chip =
+           container_of(led_cdev, struct lm355x_chip_data, cdev_indicator);
+       unsigned int state;
+
+       ret = kstrtouint(buf, 10, &state);
+       if (ret)
+               goto out;
+       if (state > INDIC_PATTERN_SIZE - 1)
+               state = INDIC_PATTERN_SIZE - 1;
+
+       ret = regmap_write(chip->regmap, 0x04,
+                          indicator_pattern[state].blinking);
+       if (ret < 0)
+               goto out;
+
+       ret = regmap_write(chip->regmap, 0x05,
+                          indicator_pattern[state].period_cnt);
+       if (ret < 0)
+               goto out;
+
+       return size;
+out:
+       dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
+       return size;
+}
+
+static DEVICE_ATTR(pattern, 0666, NULL, lm3556_indicator_pattern_store);
+
+static const struct regmap_config lm355x_regmap = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = 0xFF,
+};
+
+/* module initialize */
+static int __devinit lm355x_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
+{
+       struct lm355x_platform_data *pdata = client->dev.platform_data;
+       struct lm355x_chip_data *chip;
+
+       int err;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               dev_err(&client->dev, "i2c functionality check fail.\n");
+               return -EOPNOTSUPP;
+       }
+
+       if (pdata == NULL) {
+               dev_err(&client->dev, "needs Platform Data.\n");
+               return -ENODATA;
+       }
+
+       chip = devm_kzalloc(&client->dev,
+                           sizeof(struct lm355x_chip_data), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       chip->dev = &client->dev;
+       chip->type = id->driver_data;
+       switch (id->driver_data) {
+       case CHIP_LM3554:
+               chip->regs = lm3554_regs;
+               break;
+       case CHIP_LM3556:
+               chip->regs = lm3556_regs;
+               break;
+       default:
+               return -ENOSYS;
+       }
+       chip->pdata = pdata;
+
+       chip->regmap = devm_regmap_init_i2c(client, &lm355x_regmap);
+       if (IS_ERR(chip->regmap)) {
+               err = PTR_ERR(chip->regmap);
+               dev_err(&client->dev,
+                       "Failed to allocate register map: %d\n", err);
+               return err;
+       }
+
+       mutex_init(&chip->lock);
+       i2c_set_clientdata(client, chip);
+
+       err = lm355x_chip_init(chip);
+       if (err < 0)
+               goto err_out;
+
+       /* flash */
+       INIT_WORK(&chip->work_flash, lm355x_deferred_strobe_brightness_set);
+       chip->cdev_flash.name = "flash";
+       chip->cdev_flash.max_brightness = 16;
+       chip->cdev_flash.brightness_set = lm355x_strobe_brightness_set;
+       err = led_classdev_register((struct device *)
+                                   &client->dev, &chip->cdev_flash);
+       if (err < 0)
+               goto err_out;
+       /* torch */
+       INIT_WORK(&chip->work_torch, lm355x_deferred_torch_brightness_set);
+       chip->cdev_torch.name = "torch";
+       chip->cdev_torch.max_brightness = 8;
+       chip->cdev_torch.brightness_set = lm355x_torch_brightness_set;
+       err = led_classdev_register((struct device *)
+                                   &client->dev, &chip->cdev_torch);
+       if (err < 0)
+               goto err_create_torch_file;
+       /* indicator */
+       INIT_WORK(&chip->work_indicator,
+                 lm355x_deferred_indicator_brightness_set);
+       chip->cdev_indicator.name = "indicator";
+       if (id->driver_data == CHIP_LM3554)
+               chip->cdev_indicator.max_brightness = 4;
+       else
+               chip->cdev_indicator.max_brightness = 8;
+       chip->cdev_indicator.brightness_set = lm355x_indicator_brightness_set;
+       err = led_classdev_register((struct device *)
+                                   &client->dev, &chip->cdev_indicator);
+       if (err < 0)
+               goto err_create_indicator_file;
+       /* indicator pattern control only for LM3554 */
+       if (id->driver_data == CHIP_LM3556) {
+               err =
+                   device_create_file(chip->cdev_indicator.dev,
+                                      &dev_attr_pattern);
+               if (err < 0)
+                       goto err_create_pattern_file;
+       }
+
+       dev_info(&client->dev, "%s is initialized\n",
+                lm355x_name[id->driver_data]);
+       return 0;
+
+err_create_pattern_file:
+       led_classdev_unregister(&chip->cdev_indicator);
+err_create_indicator_file:
+       led_classdev_unregister(&chip->cdev_torch);
+err_create_torch_file:
+       led_classdev_unregister(&chip->cdev_flash);
+err_out:
+       return err;
+}
+
+static int __devexit lm355x_remove(struct i2c_client *client)
+{
+       struct lm355x_chip_data *chip = i2c_get_clientdata(client);
+       struct lm355x_reg_data *preg = chip->regs;
+
+       regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0);
+       if (chip->type == CHIP_LM3556)
+               device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern);
+       led_classdev_unregister(&chip->cdev_indicator);
+       flush_work(&chip->work_indicator);
+       led_classdev_unregister(&chip->cdev_torch);
+       flush_work(&chip->work_torch);
+       led_classdev_unregister(&chip->cdev_flash);
+       flush_work(&chip->work_flash);
+       dev_info(&client->dev, "%s is removed\n", lm355x_name[chip->type]);
+
+       return 0;
+}
+
+static const struct i2c_device_id lm355x_id[] = {
+       {LM3554_NAME, CHIP_LM3554},
+       {LM3556_NAME, CHIP_LM3556},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, lm355x_id);
+
+static struct i2c_driver lm355x_i2c_driver = {
+       .driver = {
+                  .name = LM355x_NAME,
+                  .owner = THIS_MODULE,
+                  .pm = NULL,
+                  },
+       .probe = lm355x_probe,
+       .remove = __devexit_p(lm355x_remove),
+       .id_table = lm355x_id,
+};
+
+module_i2c_driver(lm355x_i2c_driver);
+
+MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM355x");
+MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
+MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c
new file mode 100644 (file)
index 0000000..3285006
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+* Simple driver for Texas Instruments LM3642 LED Flash driver chip
+* Copyright (C) 2012 Texas Instruments
+*
+* 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/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/regmap.h>
+#include <linux/workqueue.h>
+#include <linux/platform_data/leds-lm3642.h>
+
+#define        REG_FILT_TIME                   (0x0)
+#define        REG_IVFM_MODE                   (0x1)
+#define        REG_TORCH_TIME                  (0x6)
+#define        REG_FLASH                       (0x8)
+#define        REG_I_CTRL                      (0x9)
+#define        REG_ENABLE                      (0xA)
+#define        REG_FLAG                        (0xB)
+#define        REG_MAX                         (0xB)
+
+#define        UVLO_EN_SHIFT                   (7)
+#define        IVM_D_TH_SHIFT                  (2)
+#define        TORCH_RAMP_UP_TIME_SHIFT        (3)
+#define        TORCH_RAMP_DN_TIME_SHIFT        (0)
+#define        INDUCTOR_I_LIMIT_SHIFT          (6)
+#define        FLASH_RAMP_TIME_SHIFT           (3)
+#define        FLASH_TOUT_TIME_SHIFT           (0)
+#define        TORCH_I_SHIFT                   (4)
+#define        FLASH_I_SHIFT                   (0)
+#define        IVFM_SHIFT                      (7)
+#define        TX_PIN_EN_SHIFT                 (6)
+#define        STROBE_PIN_EN_SHIFT             (5)
+#define        TORCH_PIN_EN_SHIFT              (4)
+#define        MODE_BITS_SHIFT                 (0)
+
+#define        UVLO_EN_MASK                    (0x1)
+#define        IVM_D_TH_MASK                   (0x7)
+#define        TORCH_RAMP_UP_TIME_MASK         (0x7)
+#define        TORCH_RAMP_DN_TIME_MASK         (0x7)
+#define        INDUCTOR_I_LIMIT_MASK           (0x1)
+#define        FLASH_RAMP_TIME_MASK            (0x7)
+#define        FLASH_TOUT_TIME_MASK            (0x7)
+#define        TORCH_I_MASK                    (0x7)
+#define        FLASH_I_MASK                    (0xF)
+#define        IVFM_MASK                       (0x1)
+#define        TX_PIN_EN_MASK                  (0x1)
+#define        STROBE_PIN_EN_MASK              (0x1)
+#define        TORCH_PIN_EN_MASK               (0x1)
+#define        MODE_BITS_MASK                  (0x73)
+#define EX_PIN_CONTROL_MASK            (0x71)
+#define EX_PIN_ENABLE_MASK             (0x70)
+
+enum lm3642_mode {
+       MODES_STASNDBY = 0,
+       MODES_INDIC,
+       MODES_TORCH,
+       MODES_FLASH
+};
+
+struct lm3642_chip_data {
+       struct device *dev;
+
+       struct led_classdev cdev_flash;
+       struct led_classdev cdev_torch;
+       struct led_classdev cdev_indicator;
+
+       struct work_struct work_flash;
+       struct work_struct work_torch;
+       struct work_struct work_indicator;
+
+       u8 br_flash;
+       u8 br_torch;
+       u8 br_indicator;
+
+       enum lm3642_torch_pin_enable torch_pin;
+       enum lm3642_strobe_pin_enable strobe_pin;
+       enum lm3642_tx_pin_enable tx_pin;
+
+       struct lm3642_platform_data *pdata;
+       struct regmap *regmap;
+       struct mutex lock;
+
+       unsigned int last_flag;
+};
+
+/* chip initialize */
+static int __devinit lm3642_chip_init(struct lm3642_chip_data *chip)
+{
+       int ret;
+       struct lm3642_platform_data *pdata = chip->pdata;
+
+       /* set enable register */
+       ret = regmap_update_bits(chip->regmap, REG_ENABLE, EX_PIN_ENABLE_MASK,
+                                pdata->tx_pin);
+       if (ret < 0)
+               dev_err(chip->dev, "Failed to update REG_ENABLE Register\n");
+       return ret;
+}
+
+/* chip control */
+static int lm3642_control(struct lm3642_chip_data *chip,
+                         u8 brightness, enum lm3642_mode opmode)
+{
+       int ret;
+
+       ret = regmap_read(chip->regmap, REG_FLAG, &chip->last_flag);
+       if (ret < 0) {
+               dev_err(chip->dev, "Failed to read REG_FLAG Register\n");
+               goto out;
+       }
+
+       if (chip->last_flag)
+               dev_info(chip->dev, "Last FLAG is 0x%x\n", chip->last_flag);
+
+       /* brightness 0 means off-state */
+       if (!brightness)
+               opmode = MODES_STASNDBY;
+
+       switch (opmode) {
+       case MODES_TORCH:
+               ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
+                                        TORCH_I_MASK << TORCH_I_SHIFT,
+                                        (brightness - 1) << TORCH_I_SHIFT);
+
+               if (chip->torch_pin)
+                       opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
+               break;
+
+       case MODES_FLASH:
+               ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
+                                        FLASH_I_MASK << FLASH_I_SHIFT,
+                                        (brightness - 1) << FLASH_I_SHIFT);
+
+               if (chip->strobe_pin)
+                       opmode |= (STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT);
+               break;
+
+       case MODES_INDIC:
+               ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
+                                        TORCH_I_MASK << TORCH_I_SHIFT,
+                                        (brightness - 1) << TORCH_I_SHIFT);
+               break;
+
+       case MODES_STASNDBY:
+
+               break;
+
+       default:
+               return ret;
+       }
+       if (ret < 0) {
+               dev_err(chip->dev, "Failed to write REG_I_CTRL Register\n");
+               goto out;
+       }
+
+       if (chip->tx_pin)
+               opmode |= (TX_PIN_EN_MASK << TX_PIN_EN_SHIFT);
+
+       ret = regmap_update_bits(chip->regmap, REG_ENABLE,
+                                MODE_BITS_MASK << MODE_BITS_SHIFT,
+                                opmode << MODE_BITS_SHIFT);
+out:
+       return ret;
+}
+
+/* torch */
+
+/* torch pin config for lm3642*/
+static ssize_t lm3642_torch_pin_store(struct device *dev,
+                                     struct device_attribute *devAttr,
+                                     const char *buf, size_t size)
+{
+       ssize_t ret;
+       struct led_classdev *led_cdev = dev_get_drvdata(dev);
+       struct lm3642_chip_data *chip =
+           container_of(led_cdev, struct lm3642_chip_data, cdev_indicator);
+       unsigned int state;
+
+       ret = kstrtouint(buf, 10, &state);
+       if (ret)
+               goto out_strtoint;
+       if (state != 0)
+               state = 0x01 << TORCH_PIN_EN_SHIFT;
+
+       chip->torch_pin = state;
+       ret = regmap_update_bits(chip->regmap, REG_ENABLE,
+                                TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT,
+                                state);
+       if (ret < 0)
+               goto out;
+
+       return size;
+out:
+       dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
+       return size;
+out_strtoint:
+       dev_err(chip->dev, "%s: fail to change str to int\n", __func__);
+       return size;
+}
+
+static DEVICE_ATTR(torch_pin, 0666, NULL, lm3642_torch_pin_store);
+
+static void lm3642_deferred_torch_brightness_set(struct work_struct *work)
+{
+       struct lm3642_chip_data *chip =
+           container_of(work, struct lm3642_chip_data, work_torch);
+
+       mutex_lock(&chip->lock);
+       lm3642_control(chip, chip->br_torch, MODES_TORCH);
+       mutex_unlock(&chip->lock);
+}
+
+static void lm3642_torch_brightness_set(struct led_classdev *cdev,
+                                       enum led_brightness brightness)
+{
+       struct lm3642_chip_data *chip =
+           container_of(cdev, struct lm3642_chip_data, cdev_torch);
+
+       chip->br_torch = brightness;
+       schedule_work(&chip->work_torch);
+}
+
+/* flash */
+
+/* strobe pin config for lm3642*/
+static ssize_t lm3642_strobe_pin_store(struct device *dev,
+                                      struct device_attribute *devAttr,
+                                      const char *buf, size_t size)
+{
+       ssize_t ret;
+       struct led_classdev *led_cdev = dev_get_drvdata(dev);
+       struct lm3642_chip_data *chip =
+           container_of(led_cdev, struct lm3642_chip_data, cdev_indicator);
+       unsigned int state;
+
+       ret = kstrtouint(buf, 10, &state);
+       if (ret)
+               goto out_strtoint;
+       if (state != 0)
+               state = 0x01 << STROBE_PIN_EN_SHIFT;
+
+       chip->strobe_pin = state;
+       ret = regmap_update_bits(chip->regmap, REG_ENABLE,
+                                STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT,
+                                state);
+       if (ret < 0)
+               goto out;
+
+       return size;
+out:
+       dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
+       return size;
+out_strtoint:
+       dev_err(chip->dev, "%s: fail to change str to int\n", __func__);
+       return size;
+}
+
+static DEVICE_ATTR(strobe_pin, 0666, NULL, lm3642_strobe_pin_store);
+
+static void lm3642_deferred_strobe_brightness_set(struct work_struct *work)
+{
+       struct lm3642_chip_data *chip =
+           container_of(work, struct lm3642_chip_data, work_flash);
+
+       mutex_lock(&chip->lock);
+       lm3642_control(chip, chip->br_flash, MODES_FLASH);
+       mutex_unlock(&chip->lock);
+}
+
+static void lm3642_strobe_brightness_set(struct led_classdev *cdev,
+                                        enum led_brightness brightness)
+{
+       struct lm3642_chip_data *chip =
+           container_of(cdev, struct lm3642_chip_data, cdev_flash);
+
+       chip->br_flash = brightness;
+       schedule_work(&chip->work_flash);
+}
+
+/* indicator */
+static void lm3642_deferred_indicator_brightness_set(struct work_struct *work)
+{
+       struct lm3642_chip_data *chip =
+           container_of(work, struct lm3642_chip_data, work_indicator);
+
+       mutex_lock(&chip->lock);
+       lm3642_control(chip, chip->br_indicator, MODES_INDIC);
+       mutex_unlock(&chip->lock);
+}
+
+static void lm3642_indicator_brightness_set(struct led_classdev *cdev,
+                                           enum led_brightness brightness)
+{
+       struct lm3642_chip_data *chip =
+           container_of(cdev, struct lm3642_chip_data, cdev_indicator);
+
+       chip->br_indicator = brightness;
+       schedule_work(&chip->work_indicator);
+}
+
+static const struct regmap_config lm3642_regmap = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = REG_MAX,
+};
+
+static int __devinit lm3642_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
+{
+       struct lm3642_platform_data *pdata = client->dev.platform_data;
+       struct lm3642_chip_data *chip;
+
+       int err;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               dev_err(&client->dev, "i2c functionality check fail.\n");
+               return -EOPNOTSUPP;
+       }
+
+       if (pdata == NULL) {
+               dev_err(&client->dev, "needs Platform Data.\n");
+               return -ENODATA;
+       }
+
+       chip = devm_kzalloc(&client->dev,
+                           sizeof(struct lm3642_chip_data), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       chip->dev = &client->dev;
+       chip->pdata = pdata;
+
+       chip->tx_pin = pdata->tx_pin;
+       chip->torch_pin = pdata->torch_pin;
+       chip->strobe_pin = pdata->strobe_pin;
+
+       chip->regmap = devm_regmap_init_i2c(client, &lm3642_regmap);
+       if (IS_ERR(chip->regmap)) {
+               err = PTR_ERR(chip->regmap);
+               dev_err(&client->dev, "Failed to allocate register map: %d\n",
+                       err);
+               return err;
+       }
+
+       mutex_init(&chip->lock);
+       i2c_set_clientdata(client, chip);
+
+       err = lm3642_chip_init(chip);
+       if (err < 0)
+               goto err_out;
+
+       /* flash */
+       INIT_WORK(&chip->work_flash, lm3642_deferred_strobe_brightness_set);
+       chip->cdev_flash.name = "flash";
+       chip->cdev_flash.max_brightness = 16;
+       chip->cdev_flash.brightness_set = lm3642_strobe_brightness_set;
+       err = led_classdev_register((struct device *)
+                                   &client->dev, &chip->cdev_flash);
+       if (err < 0) {
+               dev_err(chip->dev, "failed to register flash\n");
+               goto err_out;
+       }
+       err = device_create_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
+       if (err < 0) {
+               dev_err(chip->dev, "failed to create strobe-pin file\n");
+               goto err_create_flash_pin_file;
+       }
+
+       /* torch */
+       INIT_WORK(&chip->work_torch, lm3642_deferred_torch_brightness_set);
+       chip->cdev_torch.name = "torch";
+       chip->cdev_torch.max_brightness = 8;
+       chip->cdev_torch.brightness_set = lm3642_torch_brightness_set;
+       err = led_classdev_register((struct device *)
+                                   &client->dev, &chip->cdev_torch);
+       if (err < 0) {
+               dev_err(chip->dev, "failed to register torch\n");
+               goto err_create_torch_file;
+       }
+       err = device_create_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
+       if (err < 0) {
+               dev_err(chip->dev, "failed to create torch-pin file\n");
+               goto err_create_torch_pin_file;
+       }
+
+       /* indicator */
+       INIT_WORK(&chip->work_indicator,
+                 lm3642_deferred_indicator_brightness_set);
+       chip->cdev_indicator.name = "indicator";
+       chip->cdev_indicator.max_brightness = 8;
+       chip->cdev_indicator.brightness_set = lm3642_indicator_brightness_set;
+       err = led_classdev_register((struct device *)
+                                   &client->dev, &chip->cdev_indicator);
+       if (err < 0) {
+               dev_err(chip->dev, "failed to register indicator\n");
+               goto err_create_indicator_file;
+       }
+
+       dev_info(&client->dev, "LM3642 is initialized\n");
+       return 0;
+
+err_create_indicator_file:
+       device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
+err_create_torch_pin_file:
+       led_classdev_unregister(&chip->cdev_torch);
+err_create_torch_file:
+       device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
+err_create_flash_pin_file:
+       led_classdev_unregister(&chip->cdev_flash);
+err_out:
+       return err;
+}
+
+static int __devexit lm3642_remove(struct i2c_client *client)
+{
+       struct lm3642_chip_data *chip = i2c_get_clientdata(client);
+
+       led_classdev_unregister(&chip->cdev_indicator);
+       flush_work(&chip->work_indicator);
+       device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
+       led_classdev_unregister(&chip->cdev_torch);
+       flush_work(&chip->work_torch);
+       device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
+       led_classdev_unregister(&chip->cdev_flash);
+       flush_work(&chip->work_flash);
+       regmap_write(chip->regmap, REG_ENABLE, 0);
+       return 0;
+}
+
+static const struct i2c_device_id lm3642_id[] = {
+       {LM3642_NAME, 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, lm3642_id);
+
+static struct i2c_driver lm3642_i2c_driver = {
+       .driver = {
+                  .name = LM3642_NAME,
+                  .owner = THIS_MODULE,
+                  .pm = NULL,
+                  },
+       .probe = lm3642_probe,
+       .remove = __devexit_p(lm3642_remove),
+       .id_table = lm3642_id,
+};
+
+module_i2c_driver(lm3642_i2c_driver);
+
+MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3642");
+MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
+MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
+MODULE_LICENSE("GPL v2");
index fbc12acada95a6e5507bcfada4b5bb483b67251a..97994ffdc0146fd7b95cb4a0ee05282e71c7cb39 100644 (file)
 #define LED_ACTIVE(mux, led)           (!!(mux & (0x0001 << led)))
 #define SHIFT_MASK(id)                 (((id) - 1) * 2)
 
+enum lp5523_chip_id {
+       LP5523,
+       LP55231,
+};
+
 struct lp5523_engine {
        int             id;
        u8              mode;
@@ -150,7 +155,7 @@ static inline struct lp5523_chip *led_to_lp5523(struct lp5523_led *led)
                            leds[led->id]);
 }
 
-static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode);
+static void lp5523_set_mode(struct lp5523_engine *engine, u8 mode);
 static int lp5523_set_engine_mode(struct lp5523_engine *engine, u8 mode);
 static int lp5523_load_program(struct lp5523_engine *engine, const u8 *pattern);
 
@@ -177,7 +182,7 @@ static int lp5523_detect(struct i2c_client *client)
        int ret;
        u8 buf;
 
-       ret = lp5523_write(client, LP5523_REG_ENABLE, 0x40);
+       ret = lp5523_write(client, LP5523_REG_ENABLE, LP5523_ENABLE);
        if (ret)
                return ret;
        ret = lp5523_read(client, LP5523_REG_ENABLE, &buf);
@@ -338,7 +343,8 @@ static int lp5523_mux_parse(const char *buf, u16 *mux, size_t len)
 {
        int i;
        u16 tmp_mux = 0;
-       len = len < LP5523_LEDS ? len : LP5523_LEDS;
+
+       len = min_t(int, len, LP5523_LEDS);
        for (i = 0; i < len; i++) {
                switch (buf[i]) {
                case '1':
@@ -546,6 +552,9 @@ static int lp5523_do_store_load(struct lp5523_engine *engine,
        unsigned cmd;
        u8 pattern[LP5523_PROGRAM_LENGTH] = {0};
 
+       if (engine->mode != LP5523_CMD_LOAD)
+               return -EINVAL;
+
        while ((offset < len - 1) && (i < LP5523_PROGRAM_LENGTH)) {
                /* separate sscanfs because length is working only for %s */
                ret = sscanf(buf + offset, "%2s%n ", c, &nrchars);
@@ -563,12 +572,7 @@ static int lp5523_do_store_load(struct lp5523_engine *engine,
                goto fail;
 
        mutex_lock(&chip->lock);
-
-       if (engine->mode == LP5523_CMD_LOAD)
-               ret = lp5523_load_program(engine, pattern);
-       else
-               ret = -EINVAL;
-
+       ret = lp5523_load_program(engine, pattern);
        mutex_unlock(&chip->lock);
 
        if (ret) {
@@ -755,6 +759,7 @@ static struct attribute *lp5523_attributes[] = {
        &dev_attr_engine2_leds.attr,
        &dev_attr_engine3_load.attr,
        &dev_attr_engine3_leds.attr,
+       NULL,
 };
 
 static const struct attribute_group lp5523_group = {
@@ -789,26 +794,28 @@ static void lp5523_unregister_sysfs(struct i2c_client *client)
 /*--------------------------------------------------------------*/
 /*                     Set chip operating mode                 */
 /*--------------------------------------------------------------*/
-static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode)
+static void lp5523_set_mode(struct lp5523_engine *engine, u8 mode)
 {
-       int ret = 0;
-
        /* if in that mode already do nothing, except for run */
        if (mode == engine->mode && mode != LP5523_CMD_RUN)
-               return 0;
+               return;
 
-       if (mode == LP5523_CMD_RUN) {
-               ret = lp5523_run_program(engine);
-       } else if (mode == LP5523_CMD_LOAD) {
+       switch (mode) {
+       case LP5523_CMD_RUN:
+               lp5523_run_program(engine);
+               break;
+       case LP5523_CMD_LOAD:
                lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED);
                lp5523_set_engine_mode(engine, LP5523_CMD_LOAD);
-       } else if (mode == LP5523_CMD_DISABLED) {
+               break;
+       case LP5523_CMD_DISABLED:
                lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED);
+               break;
+       default:
+               return;
        }
 
        engine->mode = mode;
-
-       return ret;
 }
 
 /*--------------------------------------------------------------*/
@@ -827,7 +834,8 @@ static int __init lp5523_init_engine(struct lp5523_engine *engine, int id)
 }
 
 static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
-                          int chan, struct lp5523_platform_data *pdata)
+                          int chan, struct lp5523_platform_data *pdata,
+                          const char *chip_name)
 {
        char name[32];
        int res;
@@ -846,10 +854,14 @@ static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
                        return -EINVAL;
                }
 
-               snprintf(name, sizeof(name), "%s:channel%d",
-                       pdata->label ?: "lp5523", chan);
+               if (pdata->led_config[chan].name) {
+                       led->cdev.name = pdata->led_config[chan].name;
+               } else {
+                       snprintf(name, sizeof(name), "%s:channel%d",
+                               pdata->label ? : chip_name, chan);
+                       led->cdev.name = name;
+               }
 
-               led->cdev.name = name;
                led->cdev.brightness_set = lp5523_set_brightness;
                res = led_classdev_register(dev, &led->cdev);
                if (res < 0) {
@@ -917,7 +929,7 @@ static int __devinit lp5523_probe(struct i2c_client *client,
        if (ret)
                goto fail1;
 
-       dev_info(&client->dev, "LP5523 Programmable led chip found\n");
+       dev_info(&client->dev, "%s Programmable led chip found\n", id->name);
 
        /* Initialize engines */
        for (i = 0; i < ARRAY_SIZE(chip->engines); i++) {
@@ -945,7 +957,8 @@ static int __devinit lp5523_probe(struct i2c_client *client,
                INIT_WORK(&chip->leds[led].brightness_work,
                        lp5523_led_brightness_work);
 
-               ret = lp5523_init_led(&chip->leds[led], &client->dev, i, pdata);
+               ret = lp5523_init_led(&chip->leds[led], &client->dev, i, pdata,
+                               id->name);
                if (ret) {
                        dev_err(&client->dev, "error initializing leds\n");
                        goto fail2;
@@ -970,7 +983,7 @@ static int __devinit lp5523_probe(struct i2c_client *client,
 fail2:
        for (i = 0; i < chip->num_leds; i++) {
                led_classdev_unregister(&chip->leds[i].cdev);
-               cancel_work_sync(&chip->leds[i].brightness_work);
+               flush_work(&chip->leds[i].brightness_work);
        }
 fail1:
        if (pdata->enable)
@@ -985,11 +998,14 @@ static int lp5523_remove(struct i2c_client *client)
        struct lp5523_chip *chip = i2c_get_clientdata(client);
        int i;
 
+       /* Disable engine mode */
+       lp5523_write(client, LP5523_REG_OP_MODE, LP5523_CMD_DISABLED);
+
        lp5523_unregister_sysfs(client);
 
        for (i = 0; i < chip->num_leds; i++) {
                led_classdev_unregister(&chip->leds[i].cdev);
-               cancel_work_sync(&chip->leds[i].brightness_work);
+               flush_work(&chip->leds[i].brightness_work);
        }
 
        if (chip->pdata->enable)
@@ -1000,7 +1016,8 @@ static int lp5523_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id lp5523_id[] = {
-       { "lp5523", 0 },
+       { "lp5523",  LP5523 },
+       { "lp55231", LP55231 },
        { }
 };
 
@@ -1008,7 +1025,7 @@ MODULE_DEVICE_TABLE(i2c, lp5523_id);
 
 static struct i2c_driver lp5523_driver = {
        .driver = {
-               .name   = "lp5523",
+               .name   = "lp5523x",
        },
        .probe          = lp5523_probe,
        .remove         = lp5523_remove,
index edcd706c5631f1024b305821a95857996260f593..2f2f9c43535dcb1c3940178c6b56e4f6280ba831 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/i2c.h>
 #include <linux/workqueue.h>
 #include <linux/slab.h>
+#include <linux/platform_data/leds-pca9633.h>
 
 /* LED select registers determine the source that drives LED outputs */
 #define PCA9633_LED_OFF                0x0     /* LED driver off */
@@ -96,13 +97,13 @@ static int __devinit pca9633_probe(struct i2c_client *client,
                                        const struct i2c_device_id *id)
 {
        struct pca9633_led *pca9633;
-       struct led_platform_data *pdata;
+       struct pca9633_platform_data *pdata;
        int i, err;
 
        pdata = client->dev.platform_data;
 
        if (pdata) {
-               if (pdata->num_leds <= 0 || pdata->num_leds > 4) {
+               if (pdata->leds.num_leds <= 0 || pdata->leds.num_leds > 4) {
                        dev_err(&client->dev, "board info must claim at most 4 LEDs");
                        return -EINVAL;
                }
@@ -119,14 +120,14 @@ static int __devinit pca9633_probe(struct i2c_client *client,
                pca9633[i].led_num = i;
 
                /* Platform data can specify LED names and default triggers */
-               if (pdata && i < pdata->num_leds) {
-                       if (pdata->leds[i].name)
+               if (pdata && i < pdata->leds.num_leds) {
+                       if (pdata->leds.leds[i].name)
                                snprintf(pca9633[i].name,
                                         sizeof(pca9633[i].name), "pca9633:%s",
-                                        pdata->leds[i].name);
-                       if (pdata->leds[i].default_trigger)
+                                        pdata->leds.leds[i].name);
+                       if (pdata->leds.leds[i].default_trigger)
                                pca9633[i].led_cdev.default_trigger =
-                                       pdata->leds[i].default_trigger;
+                                       pdata->leds.leds[i].default_trigger;
                } else {
                        snprintf(pca9633[i].name, sizeof(pca9633[i].name),
                                 "pca9633:%d", i);
@@ -145,6 +146,10 @@ static int __devinit pca9633_probe(struct i2c_client *client,
        /* Disable LED all-call address and set normal mode */
        i2c_smbus_write_byte_data(client, PCA9633_MODE1, 0x00);
 
+       /* Configure output: open-drain or totem pole (push-pull) */
+       if (pdata && pdata->outdrv == PCA9633_OPEN_DRAIN)
+               i2c_smbus_write_byte_data(client, PCA9633_MODE2, 0x01);
+
        /* Turn off LEDs */
        i2c_smbus_write_byte_data(client, PCA9633_LEDOUT, 0x00);
 
index 4c62113f7a77d04a0eb7fb50de7fb84e089514bf..88f23f845595e614c9164b3c1520375d77314521 100644 (file)
@@ -201,7 +201,7 @@ static int wm8350_led_probe(struct platform_device *pdev)
        struct regulator *isink, *dcdc;
        struct wm8350_led *led;
        struct wm8350_led_platform_data *pdata = pdev->dev.platform_data;
-       int ret, i;
+       int i;
 
        if (pdata == NULL) {
                dev_err(&pdev->dev, "no platform data\n");
@@ -214,24 +214,21 @@ static int wm8350_led_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       isink = regulator_get(&pdev->dev, "led_isink");
+       isink = devm_regulator_get(&pdev->dev, "led_isink");
        if (IS_ERR(isink)) {
                printk(KERN_ERR "%s: can't get ISINK\n", __func__);
                return PTR_ERR(isink);
        }
 
-       dcdc = regulator_get(&pdev->dev, "led_vcc");
+       dcdc = devm_regulator_get(&pdev->dev, "led_vcc");
        if (IS_ERR(dcdc)) {
                printk(KERN_ERR "%s: can't get DCDC\n", __func__);
-               ret = PTR_ERR(dcdc);
-               goto err_isink;
+               return PTR_ERR(dcdc);
        }
 
        led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
-       if (led == NULL) {
-               ret = -ENOMEM;
-               goto err_dcdc;
-       }
+       if (led == NULL)
+               return -ENOMEM;
 
        led->cdev.brightness_set = wm8350_led_set;
        led->cdev.default_trigger = pdata->default_trigger;
@@ -257,17 +254,7 @@ static int wm8350_led_probe(struct platform_device *pdev)
        led->value = LED_OFF;
        platform_set_drvdata(pdev, led);
 
-       ret = led_classdev_register(&pdev->dev, &led->cdev);
-       if (ret < 0)
-               goto err_dcdc;
-
-       return 0;
-
- err_dcdc:
-       regulator_put(dcdc);
- err_isink:
-       regulator_put(isink);
-       return ret;
+       return led_classdev_register(&pdev->dev, &led->cdev);
 }
 
 static int wm8350_led_remove(struct platform_device *pdev)
@@ -277,8 +264,6 @@ static int wm8350_led_remove(struct platform_device *pdev)
        led_classdev_unregister(&led->cdev);
        flush_work(&led->work);
        wm8350_led_disable(led);
-       regulator_put(led->dcdc);
-       regulator_put(led->isink);
        return 0;
 }
 
index d02acd4961269ab672ab11f1bc17960691496b05..4c50365344a9a01cca4a7e22d8adeae10dc46711 100644 (file)
@@ -32,6 +32,8 @@ static inline int led_get_brightness(struct led_classdev *led_cdev)
        return led_cdev->brightness;
 }
 
+void led_stop_software_blink(struct led_classdev *led_cdev);
+
 extern struct rw_semaphore leds_list_lock;
 extern struct list_head leds_list;
 
index d949b781f6f8b3df59e3952936e3cec7c5d769da..91a02eeeb319aa72283af7358c5cfee0c022ce12 100644 (file)
@@ -216,6 +216,13 @@ config DM_BUFIO
         as a cache, holding recently-read blocks in memory and performing
         delayed writes.
 
+config DM_BIO_PRISON
+       tristate
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       ---help---
+        Some bio locking schemes used by other device-mapper targets
+        including thin provisioning.
+
 source "drivers/md/persistent-data/Kconfig"
 
 config DM_CRYPT
@@ -247,6 +254,7 @@ config DM_THIN_PROVISIONING
        tristate "Thin provisioning target (EXPERIMENTAL)"
        depends on BLK_DEV_DM && EXPERIMENTAL
        select DM_PERSISTENT_DATA
+       select DM_BIO_PRISON
        ---help---
          Provides thin provisioning and snapshots that share a data store.
 
index 8b2e0dffe82e9c7fd4ca571381ea2fdfb0d77986..94dce8b493241b342a23815f9b4bba76e0901597 100644 (file)
@@ -29,6 +29,7 @@ obj-$(CONFIG_MD_FAULTY)               += faulty.o
 obj-$(CONFIG_BLK_DEV_MD)       += md-mod.o
 obj-$(CONFIG_BLK_DEV_DM)       += dm-mod.o
 obj-$(CONFIG_DM_BUFIO)         += dm-bufio.o
+obj-$(CONFIG_DM_BIO_PRISON)    += dm-bio-prison.o
 obj-$(CONFIG_DM_CRYPT)         += dm-crypt.o
 obj-$(CONFIG_DM_DELAY)         += dm-delay.o
 obj-$(CONFIG_DM_FLAKEY)                += dm-flakey.o
diff --git a/drivers/md/dm-bio-prison.c b/drivers/md/dm-bio-prison.c
new file mode 100644 (file)
index 0000000..e4e8415
--- /dev/null
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm.h"
+#include "dm-bio-prison.h"
+
+#include <linux/spinlock.h>
+#include <linux/mempool.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+/*----------------------------------------------------------------*/
+
+struct dm_bio_prison_cell {
+       struct hlist_node list;
+       struct dm_bio_prison *prison;
+       struct dm_cell_key key;
+       struct bio *holder;
+       struct bio_list bios;
+};
+
+struct dm_bio_prison {
+       spinlock_t lock;
+       mempool_t *cell_pool;
+
+       unsigned nr_buckets;
+       unsigned hash_mask;
+       struct hlist_head *cells;
+};
+
+/*----------------------------------------------------------------*/
+
+static uint32_t calc_nr_buckets(unsigned nr_cells)
+{
+       uint32_t n = 128;
+
+       nr_cells /= 4;
+       nr_cells = min(nr_cells, 8192u);
+
+       while (n < nr_cells)
+               n <<= 1;
+
+       return n;
+}
+
+static struct kmem_cache *_cell_cache;
+
+/*
+ * @nr_cells should be the number of cells you want in use _concurrently_.
+ * Don't confuse it with the number of distinct keys.
+ */
+struct dm_bio_prison *dm_bio_prison_create(unsigned nr_cells)
+{
+       unsigned i;
+       uint32_t nr_buckets = calc_nr_buckets(nr_cells);
+       size_t len = sizeof(struct dm_bio_prison) +
+               (sizeof(struct hlist_head) * nr_buckets);
+       struct dm_bio_prison *prison = kmalloc(len, GFP_KERNEL);
+
+       if (!prison)
+               return NULL;
+
+       spin_lock_init(&prison->lock);
+       prison->cell_pool = mempool_create_slab_pool(nr_cells, _cell_cache);
+       if (!prison->cell_pool) {
+               kfree(prison);
+               return NULL;
+       }
+
+       prison->nr_buckets = nr_buckets;
+       prison->hash_mask = nr_buckets - 1;
+       prison->cells = (struct hlist_head *) (prison + 1);
+       for (i = 0; i < nr_buckets; i++)
+               INIT_HLIST_HEAD(prison->cells + i);
+
+       return prison;
+}
+EXPORT_SYMBOL_GPL(dm_bio_prison_create);
+
+void dm_bio_prison_destroy(struct dm_bio_prison *prison)
+{
+       mempool_destroy(prison->cell_pool);
+       kfree(prison);
+}
+EXPORT_SYMBOL_GPL(dm_bio_prison_destroy);
+
+static uint32_t hash_key(struct dm_bio_prison *prison, struct dm_cell_key *key)
+{
+       const unsigned long BIG_PRIME = 4294967291UL;
+       uint64_t hash = key->block * BIG_PRIME;
+
+       return (uint32_t) (hash & prison->hash_mask);
+}
+
+static int keys_equal(struct dm_cell_key *lhs, struct dm_cell_key *rhs)
+{
+              return (lhs->virtual == rhs->virtual) &&
+                      (lhs->dev == rhs->dev) &&
+                      (lhs->block == rhs->block);
+}
+
+static struct dm_bio_prison_cell *__search_bucket(struct hlist_head *bucket,
+                                                 struct dm_cell_key *key)
+{
+       struct dm_bio_prison_cell *cell;
+       struct hlist_node *tmp;
+
+       hlist_for_each_entry(cell, tmp, bucket, list)
+               if (keys_equal(&cell->key, key))
+                       return cell;
+
+       return NULL;
+}
+
+/*
+ * 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 1 if the cell was already held, 0 if @inmate is the new holder.
+ */
+int dm_bio_detain(struct dm_bio_prison *prison, struct dm_cell_key *key,
+                 struct bio *inmate, struct dm_bio_prison_cell **ref)
+{
+       int r = 1;
+       unsigned long flags;
+       uint32_t hash = hash_key(prison, key);
+       struct dm_bio_prison_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;
+       }
+
+       /*
+        * 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);
+       if (cell) {
+               mempool_free(cell2, prison->cell_pool);
+               bio_list_add(&cell->bios, inmate);
+               goto out;
+       }
+
+       /*
+        * Use new cell.
+        */
+       cell = cell2;
+
+       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 = 0;
+
+out:
+       spin_unlock_irqrestore(&prison->lock, flags);
+
+       *ref = cell;
+
+       return r;
+}
+EXPORT_SYMBOL_GPL(dm_bio_detain);
+
+/*
+ * @inmates must have been initialised prior to this call
+ */
+static void __cell_release(struct dm_bio_prison_cell *cell, struct bio_list *inmates)
+{
+       struct dm_bio_prison *prison = cell->prison;
+
+       hlist_del(&cell->list);
+
+       if (inmates) {
+               bio_list_add(inmates, cell->holder);
+               bio_list_merge(inmates, &cell->bios);
+       }
+
+       mempool_free(cell, prison->cell_pool);
+}
+
+void dm_cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios)
+{
+       unsigned long flags;
+       struct dm_bio_prison *prison = cell->prison;
+
+       spin_lock_irqsave(&prison->lock, flags);
+       __cell_release(cell, bios);
+       spin_unlock_irqrestore(&prison->lock, flags);
+}
+EXPORT_SYMBOL_GPL(dm_cell_release);
+
+/*
+ * There are a couple of places where we put a bio into a cell briefly
+ * before taking it out again.  In these situations we know that no other
+ * bio may be in the cell.  This function releases the cell, and also does
+ * a sanity check.
+ */
+static void __cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio)
+{
+       BUG_ON(cell->holder != bio);
+       BUG_ON(!bio_list_empty(&cell->bios));
+
+       __cell_release(cell, NULL);
+}
+
+void dm_cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio)
+{
+       unsigned long flags;
+       struct dm_bio_prison *prison = cell->prison;
+
+       spin_lock_irqsave(&prison->lock, flags);
+       __cell_release_singleton(cell, bio);
+       spin_unlock_irqrestore(&prison->lock, flags);
+}
+EXPORT_SYMBOL_GPL(dm_cell_release_singleton);
+
+/*
+ * Sometimes we don't want the holder, just the additional bios.
+ */
+static void __cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates)
+{
+       struct dm_bio_prison *prison = cell->prison;
+
+       hlist_del(&cell->list);
+       bio_list_merge(inmates, &cell->bios);
+
+       mempool_free(cell, prison->cell_pool);
+}
+
+void dm_cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates)
+{
+       unsigned long flags;
+       struct dm_bio_prison *prison = cell->prison;
+
+       spin_lock_irqsave(&prison->lock, flags);
+       __cell_release_no_holder(cell, inmates);
+       spin_unlock_irqrestore(&prison->lock, flags);
+}
+EXPORT_SYMBOL_GPL(dm_cell_release_no_holder);
+
+void dm_cell_error(struct dm_bio_prison_cell *cell)
+{
+       struct dm_bio_prison *prison = cell->prison;
+       struct bio_list bios;
+       struct bio *bio;
+       unsigned long flags;
+
+       bio_list_init(&bios);
+
+       spin_lock_irqsave(&prison->lock, flags);
+       __cell_release(cell, &bios);
+       spin_unlock_irqrestore(&prison->lock, flags);
+
+       while ((bio = bio_list_pop(&bios)))
+               bio_io_error(bio);
+}
+EXPORT_SYMBOL_GPL(dm_cell_error);
+
+/*----------------------------------------------------------------*/
+
+#define DEFERRED_SET_SIZE 64
+
+struct dm_deferred_entry {
+       struct dm_deferred_set *ds;
+       unsigned count;
+       struct list_head work_items;
+};
+
+struct dm_deferred_set {
+       spinlock_t lock;
+       unsigned current_entry;
+       unsigned sweeper;
+       struct dm_deferred_entry entries[DEFERRED_SET_SIZE];
+};
+
+struct dm_deferred_set *dm_deferred_set_create(void)
+{
+       int i;
+       struct dm_deferred_set *ds;
+
+       ds = kmalloc(sizeof(*ds), GFP_KERNEL);
+       if (!ds)
+               return NULL;
+
+       spin_lock_init(&ds->lock);
+       ds->current_entry = 0;
+       ds->sweeper = 0;
+       for (i = 0; i < DEFERRED_SET_SIZE; i++) {
+               ds->entries[i].ds = ds;
+               ds->entries[i].count = 0;
+               INIT_LIST_HEAD(&ds->entries[i].work_items);
+       }
+
+       return ds;
+}
+EXPORT_SYMBOL_GPL(dm_deferred_set_create);
+
+void dm_deferred_set_destroy(struct dm_deferred_set *ds)
+{
+       kfree(ds);
+}
+EXPORT_SYMBOL_GPL(dm_deferred_set_destroy);
+
+struct dm_deferred_entry *dm_deferred_entry_inc(struct dm_deferred_set *ds)
+{
+       unsigned long flags;
+       struct dm_deferred_entry *entry;
+
+       spin_lock_irqsave(&ds->lock, flags);
+       entry = ds->entries + ds->current_entry;
+       entry->count++;
+       spin_unlock_irqrestore(&ds->lock, flags);
+
+       return entry;
+}
+EXPORT_SYMBOL_GPL(dm_deferred_entry_inc);
+
+static unsigned ds_next(unsigned index)
+{
+       return (index + 1) % DEFERRED_SET_SIZE;
+}
+
+static void __sweep(struct dm_deferred_set *ds, struct list_head *head)
+{
+       while ((ds->sweeper != ds->current_entry) &&
+              !ds->entries[ds->sweeper].count) {
+               list_splice_init(&ds->entries[ds->sweeper].work_items, head);
+               ds->sweeper = ds_next(ds->sweeper);
+       }
+
+       if ((ds->sweeper == ds->current_entry) && !ds->entries[ds->sweeper].count)
+               list_splice_init(&ds->entries[ds->sweeper].work_items, head);
+}
+
+void dm_deferred_entry_dec(struct dm_deferred_entry *entry, struct list_head *head)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&entry->ds->lock, flags);
+       BUG_ON(!entry->count);
+       --entry->count;
+       __sweep(entry->ds, head);
+       spin_unlock_irqrestore(&entry->ds->lock, flags);
+}
+EXPORT_SYMBOL_GPL(dm_deferred_entry_dec);
+
+/*
+ * Returns 1 if deferred or 0 if no pending items to delay job.
+ */
+int dm_deferred_set_add_work(struct dm_deferred_set *ds, struct list_head *work)
+{
+       int r = 1;
+       unsigned long flags;
+       unsigned next_entry;
+
+       spin_lock_irqsave(&ds->lock, flags);
+       if ((ds->sweeper == ds->current_entry) &&
+           !ds->entries[ds->current_entry].count)
+               r = 0;
+       else {
+               list_add(work, &ds->entries[ds->current_entry].work_items);
+               next_entry = ds_next(ds->current_entry);
+               if (!ds->entries[next_entry].count)
+                       ds->current_entry = next_entry;
+       }
+       spin_unlock_irqrestore(&ds->lock, flags);
+
+       return r;
+}
+EXPORT_SYMBOL_GPL(dm_deferred_set_add_work);
+
+/*----------------------------------------------------------------*/
+
+static int __init dm_bio_prison_init(void)
+{
+       _cell_cache = KMEM_CACHE(dm_bio_prison_cell, 0);
+       if (!_cell_cache)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void __exit dm_bio_prison_exit(void)
+{
+       kmem_cache_destroy(_cell_cache);
+       _cell_cache = NULL;
+}
+
+/*
+ * module hooks
+ */
+module_init(dm_bio_prison_init);
+module_exit(dm_bio_prison_exit);
+
+MODULE_DESCRIPTION(DM_NAME " bio prison");
+MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/md/dm-bio-prison.h b/drivers/md/dm-bio-prison.h
new file mode 100644 (file)
index 0000000..4e0ac37
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2011-2012 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_BIO_PRISON_H
+#define DM_BIO_PRISON_H
+
+#include "persistent-data/dm-block-manager.h" /* FIXME: for dm_block_t */
+#include "dm-thin-metadata.h" /* FIXME: for dm_thin_id */
+
+#include <linux/list.h>
+#include <linux/bio.h>
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Sometimes we can't deal with a bio straight away.  We put them in prison
+ * where they can't cause any mischief.  Bios are put in a cell identified
+ * by a key, multiple bios can be in the same cell.  When the cell is
+ * subsequently unlocked the bios become available.
+ */
+struct dm_bio_prison;
+struct dm_bio_prison_cell;
+
+/* FIXME: this needs to be more abstract */
+struct dm_cell_key {
+       int virtual;
+       dm_thin_id dev;
+       dm_block_t block;
+};
+
+struct dm_bio_prison *dm_bio_prison_create(unsigned nr_cells);
+void dm_bio_prison_destroy(struct dm_bio_prison *prison);
+
+/*
+ * 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 1 if the cell was already held, 0 if @inmate is the new holder.
+ */
+int dm_bio_detain(struct dm_bio_prison *prison, struct dm_cell_key *key,
+                 struct bio *inmate, struct dm_bio_prison_cell **ref);
+
+void dm_cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios);
+void dm_cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio); // FIXME: bio arg not needed
+void dm_cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates);
+void dm_cell_error(struct dm_bio_prison_cell *cell);
+
+/*----------------------------------------------------------------*/
+
+/*
+ * We use the deferred set to keep track of pending reads to shared blocks.
+ * We do this to ensure the new mapping caused by a write isn't performed
+ * until these prior reads have completed.  Otherwise the insertion of the
+ * new mapping could free the old block that the read bios are mapped to.
+ */
+
+struct dm_deferred_set;
+struct dm_deferred_entry;
+
+struct dm_deferred_set *dm_deferred_set_create(void);
+void dm_deferred_set_destroy(struct dm_deferred_set *ds);
+
+struct dm_deferred_entry *dm_deferred_entry_inc(struct dm_deferred_set *ds);
+void dm_deferred_entry_dec(struct dm_deferred_entry *entry, struct list_head *head);
+int dm_deferred_set_add_work(struct dm_deferred_set *ds, struct list_head *work);
+
+/*----------------------------------------------------------------*/
+
+#endif
index cc06a1e5242395c9d05e26b76c71849490f348af..651ca79881dd5ce8bddaac4498d0134317e6c05c 100644 (file)
@@ -280,9 +280,7 @@ static void __cache_size_refresh(void)
        BUG_ON(!mutex_is_locked(&dm_bufio_clients_lock));
        BUG_ON(dm_bufio_client_count < 0);
 
-       dm_bufio_cache_size_latch = dm_bufio_cache_size;
-
-       barrier();
+       dm_bufio_cache_size_latch = ACCESS_ONCE(dm_bufio_cache_size);
 
        /*
         * Use default if set to 0 and report the actual cache size used.
@@ -441,8 +439,7 @@ static void __relink_lru(struct dm_buffer *b, int dirty)
        c->n_buffers[b->list_mode]--;
        c->n_buffers[dirty]++;
        b->list_mode = dirty;
-       list_del(&b->lru_list);
-       list_add(&b->lru_list, &c->lru[dirty]);
+       list_move(&b->lru_list, &c->lru[dirty]);
 }
 
 /*----------------------------------------------------------------
@@ -813,7 +810,7 @@ static void __get_memory_limit(struct dm_bufio_client *c,
 {
        unsigned long buffers;
 
-       if (dm_bufio_cache_size != dm_bufio_cache_size_latch) {
+       if (ACCESS_ONCE(dm_bufio_cache_size) != dm_bufio_cache_size_latch) {
                mutex_lock(&dm_bufio_clients_lock);
                __cache_size_refresh();
                mutex_unlock(&dm_bufio_clients_lock);
@@ -1591,11 +1588,9 @@ EXPORT_SYMBOL_GPL(dm_bufio_client_destroy);
 
 static void cleanup_old_buffers(void)
 {
-       unsigned long max_age = dm_bufio_max_age;
+       unsigned long max_age = ACCESS_ONCE(dm_bufio_max_age);
        struct dm_bufio_client *c;
 
-       barrier();
-
        if (max_age > ULONG_MAX / HZ)
                max_age = ULONG_MAX / HZ;
 
index 664743d6a6cdb7961ea7555544185ea4cff06357..bbf459bca61d9442e11b9ca544084877b2155268 100644 (file)
@@ -798,14 +798,6 @@ static int crypt_convert(struct crypt_config *cc,
        return 0;
 }
 
-static void dm_crypt_bio_destructor(struct bio *bio)
-{
-       struct dm_crypt_io *io = bio->bi_private;
-       struct crypt_config *cc = io->cc;
-
-       bio_free(bio, cc->bs);
-}
-
 /*
  * Generate a new unfragmented bio with the given size
  * This should never violate the device limitations
@@ -974,7 +966,6 @@ static void clone_init(struct dm_crypt_io *io, struct bio *clone)
        clone->bi_end_io  = crypt_endio;
        clone->bi_bdev    = cc->dev->bdev;
        clone->bi_rw      = io->base_bio->bi_rw;
-       clone->bi_destructor = dm_crypt_bio_destructor;
 }
 
 static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp)
@@ -988,19 +979,14 @@ static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp)
         * copy the required bvecs because we need the original
         * one in order to decrypt the whole bio data *afterwards*.
         */
-       clone = bio_alloc_bioset(gfp, bio_segments(base_bio), cc->bs);
+       clone = bio_clone_bioset(base_bio, gfp, cc->bs);
        if (!clone)
                return 1;
 
        crypt_inc_pending(io);
 
        clone_init(io, clone);
-       clone->bi_idx = 0;
-       clone->bi_vcnt = bio_segments(base_bio);
-       clone->bi_size = base_bio->bi_size;
        clone->bi_sector = cc->start + io->sector;
-       memcpy(clone->bi_io_vec, bio_iovec(base_bio),
-              sizeof(struct bio_vec) * clone->bi_vcnt);
 
        generic_make_request(clone);
        return 0;
index ea5dd289fe2a591cf62246eb10b36ab445de201f..1c46f97d6664a850ea286f90b6a36e82d6b73074 100644 (file)
@@ -249,16 +249,6 @@ static void vm_dp_init(struct dpages *dp, void *data)
        dp->context_ptr = data;
 }
 
-static void dm_bio_destructor(struct bio *bio)
-{
-       unsigned region;
-       struct io *io;
-
-       retrieve_io_and_region_from_bio(bio, &io, &region);
-
-       bio_free(bio, io->client->bios);
-}
-
 /*
  * Functions for getting the pages from kernel memory.
  */
@@ -317,7 +307,6 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
                bio->bi_sector = where->sector + (where->count - remaining);
                bio->bi_bdev = where->bdev;
                bio->bi_end_io = endio;
-               bio->bi_destructor = dm_bio_destructor;
                store_io_and_region_in_bio(bio, io, region);
 
                if (rw & REQ_DISCARD) {
index d778563a4ffd2ca829c42e3e480ed89cb908541e..573bd04591bfb0acb1eb2cb3a51f90f1e88da601 100644 (file)
@@ -1309,13 +1309,14 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone,
 {
        struct multipath *m = ti->private;
        struct dm_mpath_io *mpio = map_context->ptr;
-       struct pgpath *pgpath = mpio->pgpath;
+       struct pgpath *pgpath;
        struct path_selector *ps;
        int r;
 
        BUG_ON(!mpio);
 
        r  = do_end_io(m, clone, error, mpio);
+       pgpath = mpio->pgpath;
        if (pgpath) {
                ps = &pgpath->pg->ps;
                if (ps->type->end_io)
index c29410af1e2211cbba6029a16128e2fabbf97976..058acf3a5ba7aaa43ba58e0eb7dd1acfd1f6399b 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include "dm-thin-metadata.h"
+#include "dm-bio-prison.h"
 #include "dm.h"
 
 #include <linux/device-mapper.h>
@@ -21,7 +22,6 @@
  * Tunable constants
  */
 #define ENDIO_HOOK_POOL_SIZE 1024
-#define DEFERRED_SET_SIZE 64
 #define MAPPING_POOL_SIZE 1024
 #define PRISON_CELLS 1024
 #define COMMIT_PERIOD HZ
@@ -58,7 +58,7 @@
  * i) plug io further to this physical block. (see bio_prison code).
  *
  * ii) quiesce any read io to that shared data block.  Obviously
- * including all devices that share this block.  (see deferred_set code)
+ * including all devices that share this block.  (see dm_deferred_set code)
  *
  * iii) copy the data block to a newly allocate block.  This step can be
  * missed out if the io covers the block. (schedule_copy).
 
 /*----------------------------------------------------------------*/
 
-/*
- * Sometimes we can't deal with a bio straight away.  We put them in prison
- * where they can't cause any mischief.  Bios are put in a cell identified
- * by a key, multiple bios can be in the same cell.  When the cell is
- * subsequently unlocked the bios become available.
- */
-struct bio_prison;
-
-struct cell_key {
-       int virtual;
-       dm_thin_id dev;
-       dm_block_t block;
-};
-
-struct dm_bio_prison_cell {
-       struct hlist_node list;
-       struct bio_prison *prison;
-       struct cell_key key;
-       struct bio *holder;
-       struct bio_list bios;
-};
-
-struct bio_prison {
-       spinlock_t lock;
-       mempool_t *cell_pool;
-
-       unsigned nr_buckets;
-       unsigned hash_mask;
-       struct hlist_head *cells;
-};
-
-static uint32_t calc_nr_buckets(unsigned nr_cells)
-{
-       uint32_t n = 128;
-
-       nr_cells /= 4;
-       nr_cells = min(nr_cells, 8192u);
-
-       while (n < nr_cells)
-               n <<= 1;
-
-       return n;
-}
-
-static struct kmem_cache *_cell_cache;
-
-/*
- * @nr_cells should be the number of cells you want in use _concurrently_.
- * Don't confuse it with the number of distinct keys.
- */
-static struct bio_prison *prison_create(unsigned nr_cells)
-{
-       unsigned i;
-       uint32_t nr_buckets = calc_nr_buckets(nr_cells);
-       size_t len = sizeof(struct bio_prison) +
-               (sizeof(struct hlist_head) * nr_buckets);
-       struct bio_prison *prison = kmalloc(len, GFP_KERNEL);
-
-       if (!prison)
-               return NULL;
-
-       spin_lock_init(&prison->lock);
-       prison->cell_pool = mempool_create_slab_pool(nr_cells, _cell_cache);
-       if (!prison->cell_pool) {
-               kfree(prison);
-               return NULL;
-       }
-
-       prison->nr_buckets = nr_buckets;
-       prison->hash_mask = nr_buckets - 1;
-       prison->cells = (struct hlist_head *) (prison + 1);
-       for (i = 0; i < nr_buckets; i++)
-               INIT_HLIST_HEAD(prison->cells + i);
-
-       return prison;
-}
-
-static void prison_destroy(struct bio_prison *prison)
-{
-       mempool_destroy(prison->cell_pool);
-       kfree(prison);
-}
-
-static uint32_t hash_key(struct bio_prison *prison, struct cell_key *key)
-{
-       const unsigned long BIG_PRIME = 4294967291UL;
-       uint64_t hash = key->block * BIG_PRIME;
-
-       return (uint32_t) (hash & prison->hash_mask);
-}
-
-static int keys_equal(struct cell_key *lhs, struct cell_key *rhs)
-{
-              return (lhs->virtual == rhs->virtual) &&
-                      (lhs->dev == rhs->dev) &&
-                      (lhs->block == rhs->block);
-}
-
-static struct dm_bio_prison_cell *__search_bucket(struct hlist_head *bucket,
-                                                 struct cell_key *key)
-{
-       struct dm_bio_prison_cell *cell;
-       struct hlist_node *tmp;
-
-       hlist_for_each_entry(cell, tmp, bucket, list)
-               if (keys_equal(&cell->key, key))
-                       return cell;
-
-       return NULL;
-}
-
-/*
- * 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 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 dm_bio_prison_cell **ref)
-{
-       int r = 1;
-       unsigned long flags;
-       uint32_t hash = hash_key(prison, key);
-       struct dm_bio_prison_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;
-       }
-
-       /*
-        * 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);
-       if (cell) {
-               mempool_free(cell2, prison->cell_pool);
-               bio_list_add(&cell->bios, inmate);
-               goto out;
-       }
-
-       /*
-        * Use new cell.
-        */
-       cell = cell2;
-
-       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 = 0;
-
-out:
-       spin_unlock_irqrestore(&prison->lock, flags);
-
-       *ref = cell;
-
-       return r;
-}
-
-/*
- * @inmates must have been initialised prior to this call
- */
-static void __cell_release(struct dm_bio_prison_cell *cell, struct bio_list *inmates)
-{
-       struct bio_prison *prison = cell->prison;
-
-       hlist_del(&cell->list);
-
-       if (inmates) {
-               bio_list_add(inmates, cell->holder);
-               bio_list_merge(inmates, &cell->bios);
-       }
-
-       mempool_free(cell, prison->cell_pool);
-}
-
-static void cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios)
-{
-       unsigned long flags;
-       struct bio_prison *prison = cell->prison;
-
-       spin_lock_irqsave(&prison->lock, flags);
-       __cell_release(cell, bios);
-       spin_unlock_irqrestore(&prison->lock, flags);
-}
-
-/*
- * There are a couple of places where we put a bio into a cell briefly
- * before taking it out again.  In these situations we know that no other
- * bio may be in the cell.  This function releases the cell, and also does
- * a sanity check.
- */
-static void __cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio)
-{
-       BUG_ON(cell->holder != bio);
-       BUG_ON(!bio_list_empty(&cell->bios));
-
-       __cell_release(cell, NULL);
-}
-
-static void cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio)
-{
-       unsigned long flags;
-       struct bio_prison *prison = cell->prison;
-
-       spin_lock_irqsave(&prison->lock, flags);
-       __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 dm_bio_prison_cell *cell,
-                                    struct bio_list *inmates)
-{
-       struct bio_prison *prison = cell->prison;
-
-       hlist_del(&cell->list);
-       bio_list_merge(inmates, &cell->bios);
-
-       mempool_free(cell, prison->cell_pool);
-}
-
-static void cell_release_no_holder(struct dm_bio_prison_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 dm_bio_prison_cell *cell)
-{
-       struct bio_prison *prison = cell->prison;
-       struct bio_list bios;
-       struct bio *bio;
-       unsigned long flags;
-
-       bio_list_init(&bios);
-
-       spin_lock_irqsave(&prison->lock, flags);
-       __cell_release(cell, &bios);
-       spin_unlock_irqrestore(&prison->lock, flags);
-
-       while ((bio = bio_list_pop(&bios)))
-               bio_io_error(bio);
-}
-
-/*----------------------------------------------------------------*/
-
-/*
- * We use the deferred set to keep track of pending reads to shared blocks.
- * We do this to ensure the new mapping caused by a write isn't performed
- * until these prior reads have completed.  Otherwise the insertion of the
- * new mapping could free the old block that the read bios are mapped to.
- */
-
-struct deferred_set;
-struct deferred_entry {
-       struct deferred_set *ds;
-       unsigned count;
-       struct list_head work_items;
-};
-
-struct deferred_set {
-       spinlock_t lock;
-       unsigned current_entry;
-       unsigned sweeper;
-       struct deferred_entry entries[DEFERRED_SET_SIZE];
-};
-
-static void ds_init(struct deferred_set *ds)
-{
-       int i;
-
-       spin_lock_init(&ds->lock);
-       ds->current_entry = 0;
-       ds->sweeper = 0;
-       for (i = 0; i < DEFERRED_SET_SIZE; i++) {
-               ds->entries[i].ds = ds;
-               ds->entries[i].count = 0;
-               INIT_LIST_HEAD(&ds->entries[i].work_items);
-       }
-}
-
-static struct deferred_entry *ds_inc(struct deferred_set *ds)
-{
-       unsigned long flags;
-       struct deferred_entry *entry;
-
-       spin_lock_irqsave(&ds->lock, flags);
-       entry = ds->entries + ds->current_entry;
-       entry->count++;
-       spin_unlock_irqrestore(&ds->lock, flags);
-
-       return entry;
-}
-
-static unsigned ds_next(unsigned index)
-{
-       return (index + 1) % DEFERRED_SET_SIZE;
-}
-
-static void __sweep(struct deferred_set *ds, struct list_head *head)
-{
-       while ((ds->sweeper != ds->current_entry) &&
-              !ds->entries[ds->sweeper].count) {
-               list_splice_init(&ds->entries[ds->sweeper].work_items, head);
-               ds->sweeper = ds_next(ds->sweeper);
-       }
-
-       if ((ds->sweeper == ds->current_entry) && !ds->entries[ds->sweeper].count)
-               list_splice_init(&ds->entries[ds->sweeper].work_items, head);
-}
-
-static void ds_dec(struct deferred_entry *entry, struct list_head *head)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&entry->ds->lock, flags);
-       BUG_ON(!entry->count);
-       --entry->count;
-       __sweep(entry->ds, head);
-       spin_unlock_irqrestore(&entry->ds->lock, flags);
-}
-
-/*
- * Returns 1 if deferred or 0 if no pending items to delay job.
- */
-static int ds_add_work(struct deferred_set *ds, struct list_head *work)
-{
-       int r = 1;
-       unsigned long flags;
-       unsigned next_entry;
-
-       spin_lock_irqsave(&ds->lock, flags);
-       if ((ds->sweeper == ds->current_entry) &&
-           !ds->entries[ds->current_entry].count)
-               r = 0;
-       else {
-               list_add(work, &ds->entries[ds->current_entry].work_items);
-               next_entry = ds_next(ds->current_entry);
-               if (!ds->entries[next_entry].count)
-                       ds->current_entry = next_entry;
-       }
-       spin_unlock_irqrestore(&ds->lock, flags);
-
-       return r;
-}
-
-/*----------------------------------------------------------------*/
-
 /*
  * Key building.
  */
 static void build_data_key(struct dm_thin_device *td,
-                          dm_block_t b, struct cell_key *key)
+                          dm_block_t b, struct dm_cell_key *key)
 {
        key->virtual = 0;
        key->dev = dm_thin_dev_id(td);
@@ -481,7 +110,7 @@ static void build_data_key(struct dm_thin_device *td,
 }
 
 static void build_virtual_key(struct dm_thin_device *td, dm_block_t b,
-                             struct cell_key *key)
+                             struct dm_cell_key *key)
 {
        key->virtual = 1;
        key->dev = dm_thin_dev_id(td);
@@ -534,7 +163,7 @@ struct pool {
        unsigned low_water_triggered:1; /* A dm event has been sent */
        unsigned no_free_space:1;       /* A -ENOSPC warning has been issued */
 
-       struct bio_prison *prison;
+       struct dm_bio_prison *prison;
        struct dm_kcopyd_client *copier;
 
        struct workqueue_struct *wq;
@@ -552,8 +181,8 @@ struct pool {
 
        struct bio_list retry_on_resume_list;
 
-       struct deferred_set shared_read_ds;
-       struct deferred_set all_io_ds;
+       struct dm_deferred_set *shared_read_ds;
+       struct dm_deferred_set *all_io_ds;
 
        struct dm_thin_new_mapping *next_mapping;
        mempool_t *mapping_pool;
@@ -660,8 +289,8 @@ static struct pool *__pool_table_lookup_metadata_dev(struct block_device *md_dev
 
 struct dm_thin_endio_hook {
        struct thin_c *tc;
-       struct deferred_entry *shared_read_entry;
-       struct deferred_entry *all_io_entry;
+       struct dm_deferred_entry *shared_read_entry;
+       struct dm_deferred_entry *all_io_entry;
        struct dm_thin_new_mapping *overwrite_mapping;
 };
 
@@ -877,7 +506,7 @@ static void cell_defer(struct thin_c *tc, struct dm_bio_prison_cell *cell,
        unsigned long flags;
 
        spin_lock_irqsave(&pool->lock, flags);
-       cell_release(cell, &pool->deferred_bios);
+       dm_cell_release(cell, &pool->deferred_bios);
        spin_unlock_irqrestore(&tc->pool->lock, flags);
 
        wake_worker(pool);
@@ -896,7 +525,7 @@ static void cell_defer_except(struct thin_c *tc, struct dm_bio_prison_cell *cell
        bio_list_init(&bios);
 
        spin_lock_irqsave(&pool->lock, flags);
-       cell_release_no_holder(cell, &pool->deferred_bios);
+       dm_cell_release_no_holder(cell, &pool->deferred_bios);
        spin_unlock_irqrestore(&pool->lock, flags);
 
        wake_worker(pool);
@@ -906,7 +535,7 @@ static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m)
 {
        if (m->bio)
                m->bio->bi_end_io = m->saved_bi_end_io;
-       cell_error(m->cell);
+       dm_cell_error(m->cell);
        list_del(&m->list);
        mempool_free(m, m->tc->pool->mapping_pool);
 }
@@ -921,7 +550,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
                bio->bi_end_io = m->saved_bi_end_io;
 
        if (m->err) {
-               cell_error(m->cell);
+               dm_cell_error(m->cell);
                goto out;
        }
 
@@ -933,7 +562,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
        r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block);
        if (r) {
                DMERR("dm_thin_insert_block() failed");
-               cell_error(m->cell);
+               dm_cell_error(m->cell);
                goto out;
        }
 
@@ -1067,7 +696,7 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
        m->err = 0;
        m->bio = NULL;
 
-       if (!ds_add_work(&pool->shared_read_ds, &m->list))
+       if (!dm_deferred_set_add_work(pool->shared_read_ds, &m->list))
                m->quiesced = 1;
 
        /*
@@ -1099,7 +728,7 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
                if (r < 0) {
                        mempool_free(m, pool->mapping_pool);
                        DMERR("dm_kcopyd_copy() failed");
-                       cell_error(cell);
+                       dm_cell_error(cell);
                }
        }
 }
@@ -1164,7 +793,7 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
                if (r < 0) {
                        mempool_free(m, pool->mapping_pool);
                        DMERR("dm_kcopyd_zero() failed");
-                       cell_error(cell);
+                       dm_cell_error(cell);
                }
        }
 }
@@ -1276,7 +905,7 @@ static void no_space(struct dm_bio_prison_cell *cell)
        struct bio_list bios;
 
        bio_list_init(&bios);
-       cell_release(cell, &bios);
+       dm_cell_release(cell, &bios);
 
        while ((bio = bio_list_pop(&bios)))
                retry_on_resume(bio);
@@ -1288,13 +917,13 @@ static void process_discard(struct thin_c *tc, struct bio *bio)
        unsigned long flags;
        struct pool *pool = tc->pool;
        struct dm_bio_prison_cell *cell, *cell2;
-       struct cell_key key, key2;
+       struct dm_cell_key key, key2;
        dm_block_t block = get_bio_block(tc, bio);
        struct dm_thin_lookup_result lookup_result;
        struct dm_thin_new_mapping *m;
 
        build_virtual_key(tc->td, block, &key);
-       if (bio_detain(tc->pool->prison, &key, bio, &cell))
+       if (dm_bio_detain(tc->pool->prison, &key, bio, &cell))
                return;
 
        r = dm_thin_find_block(tc->td, block, 1, &lookup_result);
@@ -1306,8 +935,8 @@ static void process_discard(struct thin_c *tc, struct bio *bio)
                 * 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);
+               if (dm_bio_detain(tc->pool->prison, &key2, bio, &cell2)) {
+                       dm_cell_release_singleton(cell, bio);
                        break;
                }
 
@@ -1326,7 +955,7 @@ static void process_discard(struct thin_c *tc, struct bio *bio)
                        m->err = 0;
                        m->bio = bio;
 
-                       if (!ds_add_work(&pool->all_io_ds, &m->list)) {
+                       if (!dm_deferred_set_add_work(pool->all_io_ds, &m->list)) {
                                spin_lock_irqsave(&pool->lock, flags);
                                list_add(&m->list, &pool->prepared_discards);
                                spin_unlock_irqrestore(&pool->lock, flags);
@@ -1338,8 +967,8 @@ static void process_discard(struct thin_c *tc, struct bio *bio)
                         * a block boundary.  So we submit the discard of a
                         * partial block appropriately.
                         */
-                       cell_release_singleton(cell, bio);
-                       cell_release_singleton(cell2, bio);
+                       dm_cell_release_singleton(cell, bio);
+                       dm_cell_release_singleton(cell2, bio);
                        if ((!lookup_result.shared) && pool->pf.discard_passdown)
                                remap_and_issue(tc, bio, lookup_result.block);
                        else
@@ -1351,20 +980,20 @@ static void process_discard(struct thin_c *tc, struct bio *bio)
                /*
                 * It isn't provisioned, just forget it.
                 */
-               cell_release_singleton(cell, bio);
+               dm_cell_release_singleton(cell, bio);
                bio_endio(bio, 0);
                break;
 
        default:
                DMERR("discard: find block unexpectedly returned %d", r);
-               cell_release_singleton(cell, bio);
+               dm_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_cell_key *key,
                          struct dm_thin_lookup_result *lookup_result,
                          struct dm_bio_prison_cell *cell)
 {
@@ -1384,7 +1013,7 @@ static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
 
        default:
                DMERR("%s: alloc_data_block() failed, error = %d", __func__, r);
-               cell_error(cell);
+               dm_cell_error(cell);
                break;
        }
 }
@@ -1395,14 +1024,14 @@ static void process_shared_bio(struct thin_c *tc, struct bio *bio,
 {
        struct dm_bio_prison_cell *cell;
        struct pool *pool = tc->pool;
-       struct cell_key key;
+       struct dm_cell_key key;
 
        /*
         * If cell is already occupied, then sharing is already in the process
         * of being broken so we have nothing further to do here.
         */
        build_data_key(tc->td, lookup_result->block, &key);
-       if (bio_detain(pool->prison, &key, bio, &cell))
+       if (dm_bio_detain(pool->prison, &key, bio, &cell))
                return;
 
        if (bio_data_dir(bio) == WRITE && bio->bi_size)
@@ -1410,9 +1039,9 @@ static void process_shared_bio(struct thin_c *tc, struct bio *bio,
        else {
                struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr;
 
-               h->shared_read_entry = ds_inc(&pool->shared_read_ds);
+               h->shared_read_entry = dm_deferred_entry_inc(pool->shared_read_ds);
 
-               cell_release_singleton(cell, bio);
+               dm_cell_release_singleton(cell, bio);
                remap_and_issue(tc, bio, lookup_result->block);
        }
 }
@@ -1427,7 +1056,7 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block
         * Remap empty bios (flushes) immediately, without provisioning.
         */
        if (!bio->bi_size) {
-               cell_release_singleton(cell, bio);
+               dm_cell_release_singleton(cell, bio);
                remap_and_issue(tc, bio, 0);
                return;
        }
@@ -1437,7 +1066,7 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block
         */
        if (bio_data_dir(bio) == READ) {
                zero_fill_bio(bio);
-               cell_release_singleton(cell, bio);
+               dm_cell_release_singleton(cell, bio);
                bio_endio(bio, 0);
                return;
        }
@@ -1458,7 +1087,7 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block
        default:
                DMERR("%s: alloc_data_block() failed, error = %d", __func__, r);
                set_pool_mode(tc->pool, PM_READ_ONLY);
-               cell_error(cell);
+               dm_cell_error(cell);
                break;
        }
 }
@@ -1468,7 +1097,7 @@ static void process_bio(struct thin_c *tc, struct bio *bio)
        int r;
        dm_block_t block = get_bio_block(tc, bio);
        struct dm_bio_prison_cell *cell;
-       struct cell_key key;
+       struct dm_cell_key key;
        struct dm_thin_lookup_result lookup_result;
 
        /*
@@ -1476,7 +1105,7 @@ static void process_bio(struct thin_c *tc, struct bio *bio)
         * being provisioned so we have nothing further to do here.
         */
        build_virtual_key(tc->td, block, &key);
-       if (bio_detain(tc->pool->prison, &key, bio, &cell))
+       if (dm_bio_detain(tc->pool->prison, &key, bio, &cell))
                return;
 
        r = dm_thin_find_block(tc->td, block, 1, &lookup_result);
@@ -1491,7 +1120,7 @@ static void process_bio(struct thin_c *tc, struct bio *bio)
                 * TODO: this will probably have to change when discard goes
                 * back in.
                 */
-               cell_release_singleton(cell, bio);
+               dm_cell_release_singleton(cell, bio);
 
                if (lookup_result.shared)
                        process_shared_bio(tc, bio, block, &lookup_result);
@@ -1501,7 +1130,7 @@ static void process_bio(struct thin_c *tc, struct bio *bio)
 
        case -ENODATA:
                if (bio_data_dir(bio) == READ && tc->origin_dev) {
-                       cell_release_singleton(cell, bio);
+                       dm_cell_release_singleton(cell, bio);
                        remap_to_origin_and_issue(tc, bio);
                } else
                        provision_block(tc, bio, block, cell);
@@ -1509,7 +1138,7 @@ static void process_bio(struct thin_c *tc, struct bio *bio)
 
        default:
                DMERR("dm_thin_find_block() failed, error = %d", r);
-               cell_release_singleton(cell, bio);
+               dm_cell_release_singleton(cell, bio);
                bio_io_error(bio);
                break;
        }
@@ -1718,7 +1347,7 @@ static struct dm_thin_endio_hook *thin_hook_bio(struct thin_c *tc, struct bio *b
 
        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->all_io_entry = bio->bi_rw & REQ_DISCARD ? NULL : dm_deferred_entry_inc(pool->all_io_ds);
        h->overwrite_mapping = NULL;
 
        return h;
@@ -1928,7 +1557,7 @@ static void __pool_destroy(struct pool *pool)
        if (dm_pool_metadata_close(pool->pmd) < 0)
                DMWARN("%s: dm_pool_metadata_close() failed.", __func__);
 
-       prison_destroy(pool->prison);
+       dm_bio_prison_destroy(pool->prison);
        dm_kcopyd_client_destroy(pool->copier);
 
        if (pool->wq)
@@ -1938,6 +1567,8 @@ static void __pool_destroy(struct pool *pool)
                mempool_free(pool->next_mapping, pool->mapping_pool);
        mempool_destroy(pool->mapping_pool);
        mempool_destroy(pool->endio_hook_pool);
+       dm_deferred_set_destroy(pool->shared_read_ds);
+       dm_deferred_set_destroy(pool->all_io_ds);
        kfree(pool);
 }
 
@@ -1976,7 +1607,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
                pool->sectors_per_block_shift = __ffs(block_size);
        pool->low_water_blocks = 0;
        pool_features_init(&pool->pf);
-       pool->prison = prison_create(PRISON_CELLS);
+       pool->prison = dm_bio_prison_create(PRISON_CELLS);
        if (!pool->prison) {
                *error = "Error creating pool's bio prison";
                err_p = ERR_PTR(-ENOMEM);
@@ -2012,8 +1643,20 @@ static struct pool *pool_create(struct mapped_device *pool_md,
        pool->low_water_triggered = 0;
        pool->no_free_space = 0;
        bio_list_init(&pool->retry_on_resume_list);
-       ds_init(&pool->shared_read_ds);
-       ds_init(&pool->all_io_ds);
+
+       pool->shared_read_ds = dm_deferred_set_create();
+       if (!pool->shared_read_ds) {
+               *error = "Error creating pool's shared read deferred set";
+               err_p = ERR_PTR(-ENOMEM);
+               goto bad_shared_read_ds;
+       }
+
+       pool->all_io_ds = dm_deferred_set_create();
+       if (!pool->all_io_ds) {
+               *error = "Error creating pool's all io deferred set";
+               err_p = ERR_PTR(-ENOMEM);
+               goto bad_all_io_ds;
+       }
 
        pool->next_mapping = NULL;
        pool->mapping_pool = mempool_create_slab_pool(MAPPING_POOL_SIZE,
@@ -2042,11 +1685,15 @@ static struct pool *pool_create(struct mapped_device *pool_md,
 bad_endio_hook_pool:
        mempool_destroy(pool->mapping_pool);
 bad_mapping_pool:
+       dm_deferred_set_destroy(pool->all_io_ds);
+bad_all_io_ds:
+       dm_deferred_set_destroy(pool->shared_read_ds);
+bad_shared_read_ds:
        destroy_workqueue(pool->wq);
 bad_wq:
        dm_kcopyd_client_destroy(pool->copier);
 bad_kcopyd_client:
-       prison_destroy(pool->prison);
+       dm_bio_prison_destroy(pool->prison);
 bad_prison:
        kfree(pool);
 bad_pool:
@@ -2272,15 +1919,6 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
                goto out_flags_changed;
        }
 
-       /*
-        * The block layer requires discard_granularity to be a power of 2.
-        */
-       if (pf.discard_enabled && !is_power_of_2(block_size)) {
-               ti->error = "Discard support must be disabled when the block size is not a power of 2";
-               r = -EINVAL;
-               goto out_flags_changed;
-       }
-
        pt->pool = pool;
        pt->ti = ti;
        pt->metadata_dev = metadata_dev;
@@ -2762,6 +2400,11 @@ 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 bool block_size_is_power_of_two(struct pool *pool)
+{
+       return pool->sectors_per_block_shift >= 0;
+}
+
 static void set_discard_limits(struct pool_c *pt, struct queue_limits *limits)
 {
        struct pool *pool = pt->pool;
@@ -2775,8 +2418,15 @@ static void set_discard_limits(struct pool_c *pt, struct queue_limits *limits)
        if (pt->adjusted_pf.discard_passdown) {
                data_limits = &bdev_get_queue(pt->data_dev->bdev)->limits;
                limits->discard_granularity = data_limits->discard_granularity;
-       } else
+       } else if (block_size_is_power_of_two(pool))
                limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
+       else
+               /*
+                * Use largest power of 2 that is a factor of sectors_per_block
+                * but at least DATA_DEV_BLOCK_SIZE_MIN_SECTORS.
+                */
+               limits->discard_granularity = max(1 << (ffs(pool->sectors_per_block) - 1),
+                                                 DATA_DEV_BLOCK_SIZE_MIN_SECTORS) << SECTOR_SHIFT;
 }
 
 static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
@@ -2804,7 +2454,7 @@ static struct target_type pool_target = {
        .name = "thin-pool",
        .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
                    DM_TARGET_IMMUTABLE,
-       .version = {1, 4, 0},
+       .version = {1, 5, 0},
        .module = THIS_MODULE,
        .ctr = pool_ctr,
        .dtr = pool_dtr,
@@ -2979,7 +2629,7 @@ static int thin_endio(struct dm_target *ti,
 
        if (h->shared_read_entry) {
                INIT_LIST_HEAD(&work);
-               ds_dec(h->shared_read_entry, &work);
+               dm_deferred_entry_dec(h->shared_read_entry, &work);
 
                spin_lock_irqsave(&pool->lock, flags);
                list_for_each_entry_safe(m, tmp, &work, list) {
@@ -2992,7 +2642,7 @@ static int thin_endio(struct dm_target *ti,
 
        if (h->all_io_entry) {
                INIT_LIST_HEAD(&work);
-               ds_dec(h->all_io_entry, &work);
+               dm_deferred_entry_dec(h->all_io_entry, &work);
                spin_lock_irqsave(&pool->lock, flags);
                list_for_each_entry_safe(m, tmp, &work, list)
                        list_add(&m->list, &pool->prepared_discards);
@@ -3095,7 +2745,7 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
 
 static struct target_type thin_target = {
        .name = "thin",
-       .version = {1, 4, 0},
+       .version = {1, 5, 0},
        .module = THIS_MODULE,
        .ctr = thin_ctr,
        .dtr = thin_dtr,
@@ -3125,10 +2775,6 @@ static int __init dm_thin_init(void)
 
        r = -ENOMEM;
 
-       _cell_cache = KMEM_CACHE(dm_bio_prison_cell, 0);
-       if (!_cell_cache)
-               goto bad_cell_cache;
-
        _new_mapping_cache = KMEM_CACHE(dm_thin_new_mapping, 0);
        if (!_new_mapping_cache)
                goto bad_new_mapping_cache;
@@ -3142,8 +2788,6 @@ static int __init dm_thin_init(void)
 bad_endio_hook_cache:
        kmem_cache_destroy(_new_mapping_cache);
 bad_new_mapping_cache:
-       kmem_cache_destroy(_cell_cache);
-bad_cell_cache:
        dm_unregister_target(&pool_target);
 bad_pool_target:
        dm_unregister_target(&thin_target);
@@ -3156,7 +2800,6 @@ static void dm_thin_exit(void)
        dm_unregister_target(&thin_target);
        dm_unregister_target(&pool_target);
 
-       kmem_cache_destroy(_cell_cache);
        kmem_cache_destroy(_new_mapping_cache);
        kmem_cache_destroy(_endio_hook_cache);
 }
index 892ae2766aa6adad52b6d99030a1d8d3bcf2ac38..9e7328bb40301e83a402e79173f84f1022b14159 100644 (file)
@@ -438,7 +438,7 @@ static void verity_prefetch_io(struct dm_verity *v, struct dm_verity_io *io)
                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;
+                       unsigned cluster = ACCESS_ONCE(dm_verity_prefetch_cluster);
 
                        cluster >>= v->data_dev_block_bits;
                        if (unlikely(!cluster))
index 67ffa391edcf1e70a0cc94e7085a1e99abd7a151..02db9183ca01e8b64ce54a649dacc943c883f38f 100644 (file)
@@ -71,6 +71,7 @@ struct dm_target_io {
        struct dm_io *io;
        struct dm_target *ti;
        union map_info info;
+       struct bio clone;
 };
 
 /*
@@ -86,12 +87,17 @@ struct dm_rq_target_io {
 };
 
 /*
- * For request-based dm.
- * One of these is allocated per bio.
+ * For request-based dm - the bio clones we allocate are embedded in these
+ * structs.
+ *
+ * We allocate these with bio_alloc_bioset, using the front_pad parameter when
+ * the bioset is created - this means the bio has to come at the end of the
+ * struct.
  */
 struct dm_rq_clone_bio_info {
        struct bio *orig;
        struct dm_rq_target_io *tio;
+       struct bio clone;
 };
 
 union map_info *dm_get_mapinfo(struct bio *bio)
@@ -209,8 +215,12 @@ struct dm_md_mempools {
 
 #define MIN_IOS 256
 static struct kmem_cache *_io_cache;
-static struct kmem_cache *_tio_cache;
 static struct kmem_cache *_rq_tio_cache;
+
+/*
+ * Unused now, and needs to be deleted. But since io_pool is overloaded and it's
+ * still used for _io_cache, I'm leaving this for a later cleanup
+ */
 static struct kmem_cache *_rq_bio_info_cache;
 
 static int __init local_init(void)
@@ -222,14 +232,9 @@ static int __init local_init(void)
        if (!_io_cache)
                return r;
 
-       /* allocate a slab for the target ios */
-       _tio_cache = KMEM_CACHE(dm_target_io, 0);
-       if (!_tio_cache)
-               goto out_free_io_cache;
-
        _rq_tio_cache = KMEM_CACHE(dm_rq_target_io, 0);
        if (!_rq_tio_cache)
-               goto out_free_tio_cache;
+               goto out_free_io_cache;
 
        _rq_bio_info_cache = KMEM_CACHE(dm_rq_clone_bio_info, 0);
        if (!_rq_bio_info_cache)
@@ -255,8 +260,6 @@ out_free_rq_bio_info_cache:
        kmem_cache_destroy(_rq_bio_info_cache);
 out_free_rq_tio_cache:
        kmem_cache_destroy(_rq_tio_cache);
-out_free_tio_cache:
-       kmem_cache_destroy(_tio_cache);
 out_free_io_cache:
        kmem_cache_destroy(_io_cache);
 
@@ -267,7 +270,6 @@ static void local_exit(void)
 {
        kmem_cache_destroy(_rq_bio_info_cache);
        kmem_cache_destroy(_rq_tio_cache);
-       kmem_cache_destroy(_tio_cache);
        kmem_cache_destroy(_io_cache);
        unregister_blkdev(_major, _name);
        dm_uevent_exit();
@@ -453,7 +455,7 @@ static void free_io(struct mapped_device *md, struct dm_io *io)
 
 static void free_tio(struct mapped_device *md, struct dm_target_io *tio)
 {
-       mempool_free(tio, md->tio_pool);
+       bio_put(&tio->clone);
 }
 
 static struct dm_rq_target_io *alloc_rq_tio(struct mapped_device *md,
@@ -467,16 +469,6 @@ static void free_rq_tio(struct dm_rq_target_io *tio)
        mempool_free(tio, tio->md->tio_pool);
 }
 
-static struct dm_rq_clone_bio_info *alloc_bio_info(struct mapped_device *md)
-{
-       return mempool_alloc(md->io_pool, GFP_ATOMIC);
-}
-
-static void free_bio_info(struct dm_rq_clone_bio_info *info)
-{
-       mempool_free(info, info->tio->md->io_pool);
-}
-
 static int md_in_flight(struct mapped_device *md)
 {
        return atomic_read(&md->pending[READ]) +
@@ -681,13 +673,7 @@ static void clone_endio(struct bio *bio, int error)
                }
        }
 
-       /*
-        * Store md for cleanup instead of tio which is about to get freed.
-        */
-       bio->bi_private = md->bs;
-
        free_tio(md, tio);
-       bio_put(bio);
        dec_pending(io, error);
 }
 
@@ -1007,12 +993,12 @@ int dm_set_target_max_io_len(struct dm_target *ti, sector_t len)
 }
 EXPORT_SYMBOL_GPL(dm_set_target_max_io_len);
 
-static void __map_bio(struct dm_target *ti, struct bio *clone,
-                     struct dm_target_io *tio)
+static void __map_bio(struct dm_target *ti, struct dm_target_io *tio)
 {
        int r;
        sector_t sector;
        struct mapped_device *md;
+       struct bio *clone = &tio->clone;
 
        clone->bi_end_io = clone_endio;
        clone->bi_private = tio;
@@ -1036,12 +1022,6 @@ static void __map_bio(struct dm_target *ti, struct bio *clone,
                /* error the io and bail out, or requeue it if needed */
                md = tio->io->md;
                dec_pending(tio->io, r);
-               /*
-                * Store bio_set for cleanup.
-                */
-               clone->bi_end_io = NULL;
-               clone->bi_private = md->bs;
-               bio_put(clone);
                free_tio(md, tio);
        } else if (r) {
                DMWARN("unimplemented target map return value: %d", r);
@@ -1059,25 +1039,16 @@ struct clone_info {
        unsigned short idx;
 };
 
-static void dm_bio_destructor(struct bio *bio)
-{
-       struct bio_set *bs = bio->bi_private;
-
-       bio_free(bio, bs);
-}
-
 /*
  * Creates a little bio that just does part of a bvec.
  */
-static struct bio *split_bvec(struct bio *bio, sector_t sector,
-                             unsigned short idx, unsigned int offset,
-                             unsigned int len, struct bio_set *bs)
+static void split_bvec(struct dm_target_io *tio, struct bio *bio,
+                      sector_t sector, unsigned short idx, unsigned int offset,
+                      unsigned int len, struct bio_set *bs)
 {
-       struct bio *clone;
+       struct bio *clone = &tio->clone;
        struct bio_vec *bv = bio->bi_io_vec + idx;
 
-       clone = bio_alloc_bioset(GFP_NOIO, 1, bs);
-       clone->bi_destructor = dm_bio_destructor;
        *clone->bi_io_vec = *bv;
 
        clone->bi_sector = sector;
@@ -1090,26 +1061,23 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector,
        clone->bi_flags |= 1 << BIO_CLONED;
 
        if (bio_integrity(bio)) {
-               bio_integrity_clone(clone, bio, GFP_NOIO, bs);
+               bio_integrity_clone(clone, bio, GFP_NOIO);
                bio_integrity_trim(clone,
                                   bio_sector_offset(bio, idx, offset), len);
        }
-
-       return clone;
 }
 
 /*
  * Creates a bio that consists of range of complete bvecs.
  */
-static struct bio *clone_bio(struct bio *bio, sector_t sector,
-                            unsigned short idx, unsigned short bv_count,
-                            unsigned int len, struct bio_set *bs)
+static void clone_bio(struct dm_target_io *tio, struct bio *bio,
+                     sector_t sector, unsigned short idx,
+                     unsigned short bv_count, unsigned int len,
+                     struct bio_set *bs)
 {
-       struct bio *clone;
+       struct bio *clone = &tio->clone;
 
-       clone = bio_alloc_bioset(GFP_NOIO, bio->bi_max_vecs, bs);
        __bio_clone(clone, bio);
-       clone->bi_destructor = dm_bio_destructor;
        clone->bi_sector = sector;
        clone->bi_idx = idx;
        clone->bi_vcnt = idx + bv_count;
@@ -1117,20 +1085,22 @@ static struct bio *clone_bio(struct bio *bio, sector_t sector,
        clone->bi_flags &= ~(1 << BIO_SEG_VALID);
 
        if (bio_integrity(bio)) {
-               bio_integrity_clone(clone, bio, GFP_NOIO, bs);
+               bio_integrity_clone(clone, bio, GFP_NOIO);
 
                if (idx != bio->bi_idx || clone->bi_size < bio->bi_size)
                        bio_integrity_trim(clone,
                                           bio_sector_offset(bio, idx, 0), len);
        }
-
-       return clone;
 }
 
 static struct dm_target_io *alloc_tio(struct clone_info *ci,
-                                     struct dm_target *ti)
+                                     struct dm_target *ti, int nr_iovecs)
 {
-       struct dm_target_io *tio = mempool_alloc(ci->md->tio_pool, GFP_NOIO);
+       struct dm_target_io *tio;
+       struct bio *clone;
+
+       clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, ci->md->bs);
+       tio = container_of(clone, struct dm_target_io, clone);
 
        tio->io = ci->io;
        tio->ti = ti;
@@ -1142,8 +1112,8 @@ static struct dm_target_io *alloc_tio(struct clone_info *ci,
 static void __issue_target_request(struct clone_info *ci, struct dm_target *ti,
                                   unsigned request_nr, sector_t len)
 {
-       struct dm_target_io *tio = alloc_tio(ci, ti);
-       struct bio *clone;
+       struct dm_target_io *tio = alloc_tio(ci, ti, ci->bio->bi_max_vecs);
+       struct bio *clone = &tio->clone;
 
        tio->info.target_request_nr = request_nr;
 
@@ -1152,15 +1122,14 @@ static void __issue_target_request(struct clone_info *ci, struct dm_target *ti,
         * ci->bio->bi_max_vecs is BIO_INLINE_VECS anyway, for both flush
         * and discard, so no need for concern about wasted bvec allocations.
         */
-       clone = bio_alloc_bioset(GFP_NOIO, ci->bio->bi_max_vecs, ci->md->bs);
-       __bio_clone(clone, ci->bio);
-       clone->bi_destructor = dm_bio_destructor;
+
+        __bio_clone(clone, ci->bio);
        if (len) {
                clone->bi_sector = ci->sector;
                clone->bi_size = to_bytes(len);
        }
 
-       __map_bio(ti, clone, tio);
+       __map_bio(ti, tio);
 }
 
 static void __issue_target_requests(struct clone_info *ci, struct dm_target *ti,
@@ -1189,14 +1158,13 @@ static int __clone_and_map_empty_flush(struct clone_info *ci)
  */
 static void __clone_and_map_simple(struct clone_info *ci, struct dm_target *ti)
 {
-       struct bio *clone, *bio = ci->bio;
+       struct bio *bio = ci->bio;
        struct dm_target_io *tio;
 
-       tio = alloc_tio(ci, ti);
-       clone = clone_bio(bio, ci->sector, ci->idx,
-                         bio->bi_vcnt - ci->idx, ci->sector_count,
-                         ci->md->bs);
-       __map_bio(ti, clone, tio);
+       tio = alloc_tio(ci, ti, bio->bi_max_vecs);
+       clone_bio(tio, bio, ci->sector, ci->idx, bio->bi_vcnt - ci->idx,
+                 ci->sector_count, ci->md->bs);
+       __map_bio(ti, tio);
        ci->sector_count = 0;
 }
 
@@ -1234,7 +1202,7 @@ static int __clone_and_map_discard(struct clone_info *ci)
 
 static int __clone_and_map(struct clone_info *ci)
 {
-       struct bio *clone, *bio = ci->bio;
+       struct bio *bio = ci->bio;
        struct dm_target *ti;
        sector_t len = 0, max;
        struct dm_target_io *tio;
@@ -1274,10 +1242,10 @@ static int __clone_and_map(struct clone_info *ci)
                        len += bv_len;
                }
 
-               tio = alloc_tio(ci, ti);
-               clone = clone_bio(bio, ci->sector, ci->idx, i - ci->idx, len,
-                                 ci->md->bs);
-               __map_bio(ti, clone, tio);
+               tio = alloc_tio(ci, ti, bio->bi_max_vecs);
+               clone_bio(tio, bio, ci->sector, ci->idx, i - ci->idx, len,
+                         ci->md->bs);
+               __map_bio(ti, tio);
 
                ci->sector += len;
                ci->sector_count -= len;
@@ -1302,12 +1270,11 @@ static int __clone_and_map(struct clone_info *ci)
 
                        len = min(remaining, max);
 
-                       tio = alloc_tio(ci, ti);
-                       clone = split_bvec(bio, ci->sector, ci->idx,
-                                          bv->bv_offset + offset, len,
-                                          ci->md->bs);
+                       tio = alloc_tio(ci, ti, 1);
+                       split_bvec(tio, bio, ci->sector, ci->idx,
+                                  bv->bv_offset + offset, len, ci->md->bs);
 
-                       __map_bio(ti, clone, tio);
+                       __map_bio(ti, tio);
 
                        ci->sector += len;
                        ci->sector_count -= len;
@@ -1484,30 +1451,17 @@ void dm_dispatch_request(struct request *rq)
 }
 EXPORT_SYMBOL_GPL(dm_dispatch_request);
 
-static void dm_rq_bio_destructor(struct bio *bio)
-{
-       struct dm_rq_clone_bio_info *info = bio->bi_private;
-       struct mapped_device *md = info->tio->md;
-
-       free_bio_info(info);
-       bio_free(bio, md->bs);
-}
-
 static int dm_rq_bio_constructor(struct bio *bio, struct bio *bio_orig,
                                 void *data)
 {
        struct dm_rq_target_io *tio = data;
-       struct mapped_device *md = tio->md;
-       struct dm_rq_clone_bio_info *info = alloc_bio_info(md);
-
-       if (!info)
-               return -ENOMEM;
+       struct dm_rq_clone_bio_info *info =
+               container_of(bio, struct dm_rq_clone_bio_info, clone);
 
        info->orig = bio_orig;
        info->tio = tio;
        bio->bi_end_io = end_clone_bio;
        bio->bi_private = info;
-       bio->bi_destructor = dm_rq_bio_destructor;
 
        return 0;
 }
@@ -1988,7 +1942,7 @@ static void __bind_mempools(struct mapped_device *md, struct dm_table *t)
 {
        struct dm_md_mempools *p;
 
-       if (md->io_pool && md->tio_pool && md->bs)
+       if (md->io_pool && (md->tio_pool || dm_table_get_type(t) == DM_TYPE_BIO_BASED) && md->bs)
                /* the md already has necessary mempools */
                goto out;
 
@@ -2765,13 +2719,18 @@ struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity)
        if (!pools->io_pool)
                goto free_pools_and_out;
 
-       pools->tio_pool = (type == DM_TYPE_BIO_BASED) ?
-                         mempool_create_slab_pool(MIN_IOS, _tio_cache) :
-                         mempool_create_slab_pool(MIN_IOS, _rq_tio_cache);
-       if (!pools->tio_pool)
-               goto free_io_pool_and_out;
+       pools->tio_pool = NULL;
+       if (type == DM_TYPE_REQUEST_BASED) {
+               pools->tio_pool = mempool_create_slab_pool(MIN_IOS, _rq_tio_cache);
+               if (!pools->tio_pool)
+                       goto free_io_pool_and_out;
+       }
 
-       pools->bs = bioset_create(pool_size, 0);
+       pools->bs = (type == DM_TYPE_BIO_BASED) ?
+               bioset_create(pool_size,
+                             offsetof(struct dm_target_io, clone)) :
+               bioset_create(pool_size,
+                             offsetof(struct dm_rq_clone_bio_info, clone));
        if (!pools->bs)
                goto free_tio_pool_and_out;
 
@@ -2784,7 +2743,8 @@ free_bioset_and_out:
        bioset_free(pools->bs);
 
 free_tio_pool_and_out:
-       mempool_destroy(pools->tio_pool);
+       if (pools->tio_pool)
+               mempool_destroy(pools->tio_pool);
 
 free_io_pool_and_out:
        mempool_destroy(pools->io_pool);
index 308e87b417e05a74e4429bac63e1eb2e7af43885..95c88012a3b9c71fb5581871d89f5e7de86ae396 100644 (file)
@@ -155,32 +155,17 @@ static int start_readonly;
  * like bio_clone, but with a local bio set
  */
 
-static void mddev_bio_destructor(struct bio *bio)
-{
-       struct mddev *mddev, **mddevp;
-
-       mddevp = (void*)bio;
-       mddev = mddevp[-1];
-
-       bio_free(bio, mddev->bio_set);
-}
-
 struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
                            struct mddev *mddev)
 {
        struct bio *b;
-       struct mddev **mddevp;
 
        if (!mddev || !mddev->bio_set)
                return bio_alloc(gfp_mask, nr_iovecs);
 
-       b = bio_alloc_bioset(gfp_mask, nr_iovecs,
-                            mddev->bio_set);
+       b = bio_alloc_bioset(gfp_mask, nr_iovecs, mddev->bio_set);
        if (!b)
                return NULL;
-       mddevp = (void*)b;
-       mddevp[-1] = mddev;
-       b->bi_destructor = mddev_bio_destructor;
        return b;
 }
 EXPORT_SYMBOL_GPL(bio_alloc_mddev);
@@ -188,32 +173,10 @@ EXPORT_SYMBOL_GPL(bio_alloc_mddev);
 struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask,
                            struct mddev *mddev)
 {
-       struct bio *b;
-       struct mddev **mddevp;
-
        if (!mddev || !mddev->bio_set)
                return bio_clone(bio, gfp_mask);
 
-       b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs,
-                            mddev->bio_set);
-       if (!b)
-               return NULL;
-       mddevp = (void*)b;
-       mddevp[-1] = mddev;
-       b->bi_destructor = mddev_bio_destructor;
-       __bio_clone(b, bio);
-       if (bio_integrity(bio)) {
-               int ret;
-
-               ret = bio_integrity_clone(b, bio, gfp_mask, mddev->bio_set);
-
-               if (ret < 0) {
-                       bio_put(b);
-                       return NULL;
-               }
-       }
-
-       return b;
+       return bio_clone_bioset(bio, gfp_mask, mddev->bio_set);
 }
 EXPORT_SYMBOL_GPL(bio_clone_mddev);
 
@@ -5006,8 +4969,7 @@ int md_run(struct mddev *mddev)
        }
 
        if (mddev->bio_set == NULL)
-               mddev->bio_set = bioset_create(BIO_POOL_SIZE,
-                                              sizeof(struct mddev *));
+               mddev->bio_set = bioset_create(BIO_POOL_SIZE, 0);
 
        spin_lock(&pers_lock);
        pers = find_pers(mddev->level, mddev->clevel);
index d77602d63c83f8b98e341dd07c1dd50c397986e4..f3a9af8cdec3514448ae3f6ce9cb12ecca7f20ae 100644 (file)
@@ -434,14 +434,14 @@ int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
        if (ref_count && !old) {
                *ev = SM_ALLOC;
                ll->nr_allocated++;
-               ie_disk.nr_free = cpu_to_le32(le32_to_cpu(ie_disk.nr_free) - 1);
+               le32_add_cpu(&ie_disk.nr_free, -1);
                if (le32_to_cpu(ie_disk.none_free_before) == bit)
                        ie_disk.none_free_before = cpu_to_le32(bit + 1);
 
        } else if (old && !ref_count) {
                *ev = SM_FREE;
                ll->nr_allocated--;
-               ie_disk.nr_free = cpu_to_le32(le32_to_cpu(ie_disk.nr_free) + 1);
+               le32_add_cpu(&ie_disk.nr_free, 1);
                ie_disk.none_free_before = cpu_to_le32(min(le32_to_cpu(ie_disk.none_free_before), bit));
        }
 
index de63a1fc3737b7ac2af3c0f7cbf60cd99b495a31..a9e4fa95dfaa76ac1d38434ac8153a6ffe1132c6 100644 (file)
@@ -422,6 +422,7 @@ static int raid0_run(struct mddev *mddev)
        if (md_check_no_bitmap(mddev))
                return -EINVAL;
        blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
+       blk_queue_max_write_same_sectors(mddev->queue, mddev->chunk_sectors);
 
        /* if private is not null, we are here after takeover */
        if (mddev->private == NULL) {
index 8f58f241c10dfa7047f92423cb917c67d908f4b1..7e92793260f0deffbf6bdb0a3024a95f3bf59ff5 100644 (file)
@@ -966,6 +966,8 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
                break;
        }
 
+       c->lna = LNA_AUTO;
+
        return 0;
 }
 
@@ -1054,6 +1056,8 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
        _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B, 0, 0),
        _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C, 0, 0),
        _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0),
+
+       _DTV_CMD(DTV_LNA, 0, 0),
 };
 
 static void dtv_property_dump(struct dvb_frontend *fe, struct dtv_property *tvp)
@@ -1440,6 +1444,10 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
                tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_d;
                break;
 
+       case DTV_LNA:
+               tvp->u.data = c->lna;
+               break;
+
        default:
                return -EINVAL;
        }
@@ -1731,10 +1739,6 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
        case DTV_INTERLEAVING:
                c->interleaving = tvp->u.data;
                break;
-       case DTV_LNA:
-               if (fe->ops.set_lna)
-                       r = fe->ops.set_lna(fe, tvp->u.data);
-               break;
 
        /* ISDB-T Support here */
        case DTV_ISDBT_PARTIAL_RECEPTION:
@@ -1806,6 +1810,12 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
                fe->dtv_property_cache.atscmh_rs_frame_ensemble = tvp->u.data;
                break;
 
+       case DTV_LNA:
+               c->lna = tvp->u.data;
+               if (fe->ops.set_lna)
+                       r = fe->ops.set_lna(fe);
+               break;
+
        default:
                return -EINVAL;
        }
@@ -2309,7 +2319,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
                fepriv->tune_mode_flags = (unsigned long) parg;
                err = 0;
                break;
-       };
+       }
 
        return err;
 }
index 44a445cee74f53b2fe5aa010323bd09308f293b1..97112cd88a177f4ad66fafa8bd66e540aaf86dcf 100644 (file)
@@ -303,7 +303,7 @@ struct dvb_frontend_ops {
        int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
        int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
        int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
-       int (*set_lna)(struct dvb_frontend *, int);
+       int (*set_lna)(struct dvb_frontend *);
 
        /* These callbacks are for devices that implement their own
         * tuning algorithms, rather than a simple swzigzag
@@ -391,6 +391,8 @@ struct dtv_frontend_properties {
        u8                      atscmh_sccc_code_mode_b;
        u8                      atscmh_sccc_code_mode_c;
        u8                      atscmh_sccc_code_mode_d;
+
+       u32                     lna;
 };
 
 struct dvb_frontend {
index cff44a389b404c1c492fe7e25d7925a29b076d05..74fbb5d58bed73a28d2c1f7356f0b732b78b67a5 100644 (file)
@@ -90,7 +90,7 @@ static int a8293_set_voltage(struct dvb_frontend *fe,
        default:
                ret = -EINVAL;
                goto err;
-       };
+       }
 
        ret = a8293_wr(priv, &priv->reg[0], 1);
        if (ret)
index e9f04a36577b582849f5f5d9ae29f7466462dac0..a204f2828820412f94152928f9ba20e9126b25e6 100644 (file)
@@ -241,7 +241,7 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
                                KBUILD_MODNAME, gpio);
                ret = -EINVAL;
                goto err;
-       };
+       }
 
        switch (gpio) {
        case 0:
@@ -253,7 +253,7 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
        default:
                pos = 4;
                break;
-       };
+       }
 
        ret = af9013_wr_reg_bits(state, addr, pos, 4, gpioval);
        if (ret)
@@ -726,7 +726,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
        default:
                dev_dbg(&state->i2c->dev, "%s: invalid hierarchy\n", __func__);
                auto_mode = 1;
-       };
+       }
 
        switch (c->modulation) {
        case QAM_AUTO:
index 8162d939c4b2d460a2d12111b256e6600dc19f6f..464ad878490bb5026dcd5a2ffd9ae95004c17366 100644 (file)
@@ -408,7 +408,7 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
 {
        struct af9033_state *state = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       int ret, i, spec_inv;
+       int ret, i, spec_inv, sampling_freq;
        u8 tmp, buf[3], bandwidth_reg_val;
        u32 if_frequency, freq_cw, adc_freq;
 
@@ -465,18 +465,20 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
                else
                        if_frequency = 0;
 
-               while (if_frequency > (adc_freq / 2))
-                       if_frequency -= adc_freq;
+               sampling_freq = if_frequency;
 
-               if (if_frequency >= 0)
+               while (sampling_freq > (adc_freq / 2))
+                       sampling_freq -= adc_freq;
+
+               if (sampling_freq >= 0)
                        spec_inv *= -1;
                else
-                       if_frequency *= -1;
+                       sampling_freq *= -1;
 
-               freq_cw = af9033_div(state, if_frequency, adc_freq, 23ul);
+               freq_cw = af9033_div(state, sampling_freq, adc_freq, 23ul);
 
                if (spec_inv == -1)
-                       freq_cw *= -1;
+                       freq_cw = 0x800000 - freq_cw;
 
                /* get adc multiplies */
                ret = af9033_rd_reg(state, 0x800045, &tmp);
index 033cd7ad3ca2cb9d76f7bace048fdb1f72974bdd..1b77909c0c7116c3cff03b6788912a29c2f240f3 100644 (file)
@@ -527,7 +527,7 @@ static int bcm3510_set_frontend(struct dvb_frontend *fe)
                        cmd.ACQUIRE1.IF_FREQ = 0x0;
                default:
                        return -EINVAL;
-       };
+       }
        cmd.ACQUIRE0.OFFSET = 0;
        cmd.ACQUIRE0.NTSCSWEEP = 1;
        cmd.ACQUIRE0.FA = 1;
index 3180f5b2a6a60d8bf3930876e788b3217efa8814..0cd6927e654c110b804def49677b71f8b26cc1a9 100644 (file)
@@ -218,7 +218,7 @@ static int cx24110_set_fec (struct cx24110_state* state, fe_code_rate_t fec)
           } else
                   return -EOPNOTSUPP;
 /* fixme (low): which is the correct return code? */
-       };
+       }
        return 0;
 }
 
@@ -275,7 +275,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
                cx24110_writereg(state,0x07,tmp|0x3);
                cx24110_writereg(state,0x06,0x78);
                fclk=90999000UL;
-       };
+       }
        dprintk("cx24110 debug: fclk %d Hz\n",fclk);
        /* we need to divide two integers with approx. 27 bits in 32 bit
           arithmetic giving a 25 bit result */
@@ -362,7 +362,7 @@ static int cx24110_initfe(struct dvb_frontend* fe)
 
        for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) {
                cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
-       };
+       }
 
        return 0;
 }
index 42648643693e0ab1fe06bb6975a0d40f8db54968..9b658c1cf39a48b77edd9341140bae751e80a527 100644 (file)
@@ -688,7 +688,7 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
 {
        struct cxd2820r_priv *priv;
        int ret;
-       u8 tmp, gpio[GPIO_COUNT];
+       u8 tmp;
 
        priv = kzalloc(sizeof(struct cxd2820r_priv), GFP_KERNEL);
        if (!priv) {
@@ -735,6 +735,7 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
                 * Use static GPIO configuration if GPIOLIB is undefined.
                 * This is fallback condition.
                 */
+               u8 gpio[GPIO_COUNT];
                gpio[0] = (*gpio_chip_base >> 0) & 0x07;
                gpio[1] = (*gpio_chip_base >> 3) & 0x07;
                gpio[2] = 0;
index f380eb43e9d5a66137fcff49615c1342040d158a..6d9853750d2b6dd96080dc68fb0dc1496626ddf4 100644 (file)
@@ -991,7 +991,7 @@ static int HI_Command(struct drxd_state *state, u16 cmd, u16 * pResult)
                if (nrRetries > DRXD_MAX_RETRIES) {
                        status = -1;
                        break;
-               };
+               }
                status = Read16(state, HI_RA_RAM_SRV_CMD__A, &waitCmd, 0);
        } while (waitCmd != 0);
 
index 4c8ac2657c4af0d602c0d776a8b98a03efcfdc21..5b639087ce45623f7a2f1be7e1b6216c1bc686a8 100644 (file)
@@ -30,6 +30,7 @@
 #include "ds3000.h"
 
 static int debug;
+static int force_fw_upload;
 
 #define dprintk(args...) \
        do { \
@@ -392,11 +393,13 @@ static int ds3000_firmware_ondemand(struct dvb_frontend *fe)
 
        dprintk("%s()\n", __func__);
 
-       if (ds3000_readreg(state, 0xb2) <= 0)
+       ret = ds3000_readreg(state, 0xb2);
+       if (ret < 0)
                return ret;
 
-       if (state->skip_fw_load)
-               return 0;
+       if (state->skip_fw_load || !force_fw_upload)
+               return 0;       /* Firmware already uploaded, skipping */
+
        /* Load firmware */
        /* request the firmware, this will block until someone uploads it */
        printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__,
@@ -1306,6 +1309,9 @@ static struct dvb_frontend_ops ds3000_ops = {
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
 
+module_param(force_fw_upload, int, 0644);
+MODULE_PARM_DESC(force_fw_upload, "Force firmware upload (default:0)");
+
 MODULE_DESCRIPTION("DVB Frontend module for Montage Technology "
                        "DS3000/TS2020 hardware");
 MODULE_AUTHOR("Konstantin Dimitrov");
index dcfc902c8678be0c64b04989f549639e8114fa47..d5acc304786bf9b3531212b60501da308ff0937e 100644 (file)
@@ -121,16 +121,13 @@ struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void)
 
        /* allocate memory for the internal state */
        state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
-       if (state == NULL) goto error;
+       if (!state)
+               return NULL;
 
        /* create dvb_frontend */
        memcpy(&state->frontend.ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
-
-error:
-       kfree(state);
-       return NULL;
 }
 
 static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops;
@@ -141,16 +138,13 @@ struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void)
 
        /* allocate memory for the internal state */
        state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
-       if (state == NULL) goto error;
+       if (!state)
+               return NULL;
 
        /* create dvb_frontend */
        memcpy(&state->frontend.ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
-
-error:
-       kfree(state);
-       return NULL;
 }
 
 static struct dvb_frontend_ops dvb_dummy_fe_qam_ops;
@@ -161,16 +155,13 @@ struct dvb_frontend *dvb_dummy_fe_qam_attach(void)
 
        /* allocate memory for the internal state */
        state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
-       if (state == NULL) goto error;
+       if (!state)
+               return NULL;
 
        /* create dvb_frontend */
        memcpy(&state->frontend.ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
-
-error:
-       kfree(state);
-       return NULL;
 }
 
 static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = {
index 33d33f4d8867a409d15e32bbc4d45991efdd14c9..0c642a5bf8235462da1a26d3b407a58432dc6138 100644 (file)
@@ -77,7 +77,7 @@ static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage
                        break;
                default:
                        return -EINVAL;
-               };
+               }
        }
        isl6405->config |= isl6405->override_or;
        isl6405->config &= isl6405->override_and;
index 684c8ec166cbc7bfbdaed883a18c664ec59dd428..0cb3f0f74c9c9040b48f586212fae0680ad02145 100644 (file)
@@ -63,7 +63,7 @@ static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        isl6421->config |= isl6421->override_or;
        isl6421->config &= isl6421->override_and;
index 316457584fe7a6fe7a18ae430fe1c194393dbf7c..c1c3400b2173508d3ce2ba77b236d16c2eec48c9 100644 (file)
@@ -231,7 +231,7 @@ static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
        state->frequency = ((plln * 1000) + (pllf * 1000)/1048576) * 2*FREF;
        itd_dbg("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d\n", freq_khz, state->frequency, pllf, plln);
 
-       itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */;
+       itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */
        itd1000_write_reg(state, PLLNL, plln & 0xff);
        itd1000_write_reg(state, PLLFH, (itd1000_read_reg(state, PLLFH) & 0xf0) | ((pllf >> 16) & 0x0f));
        itd1000_write_reg(state, PLLFM, (pllf >> 8) & 0xff);
index cc11260e99df96f7ce19837e6ba268811aa825cf..5fd14f840ab0ffcd38cc32656a24fae3684c62c0 100644 (file)
@@ -1421,8 +1421,8 @@ struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
               config ? config->i2c_addr : 0);
 
        state = kzalloc(sizeof(struct lg216x_state), GFP_KERNEL);
-       if (state == NULL)
-               goto fail;
+       if (!state)
+               return NULL;
 
        state->cfg = config;
        state->i2c_adap = i2c_adap;
@@ -1449,10 +1449,6 @@ struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
        state->frontend.dtv_property_cache.atscmh_parade_id = 1;
 
        return &state->frontend;
-fail:
-       lg_warn("unable to detect LG216x hardware\n");
-       kfree(state);
-       return NULL;
 }
 EXPORT_SYMBOL(lg2160_attach);
 
index 13437259eeac211d69ef8c0cd8f4c96ce9103998..f3ba7b5faa2ed9fdfcda57391dfdaac73a189287 100644 (file)
@@ -65,7 +65,7 @@ static int lnbp21_set_voltage(struct dvb_frontend *fe,
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        lnbp21->config |= lnbp21->override_or;
        lnbp21->config &= lnbp21->override_and;
@@ -108,7 +108,7 @@ static int lnbp21_set_tone(struct dvb_frontend *fe,
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        lnbp21->config |= lnbp21->override_or;
        lnbp21->config &= lnbp21->override_and;
index 84ad0390a4a12db9a6c201f2749bed749b97011b..c463da7f6dcceb53b77a7cd5f3360238d8ebde59 100644 (file)
@@ -73,7 +73,7 @@ static int lnbp22_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        dprintk(1, "%s: 0x%02x)\n", __func__, lnbp22->config[3]);
        return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
index 8352ce1c95563798c06f86e4b0f68bec85c6cd7f..6ec16a24374172f9eb3052e9b1c27e6463be95bb 100644 (file)
@@ -351,8 +351,8 @@ struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
        printk(KERN_INFO " Enter s5h1432_attach(). attach success!\n");
        /* allocate memory for the internal state */
        state = kmalloc(sizeof(struct s5h1432_state), GFP_KERNEL);
-       if (state == NULL)
-               goto error;
+       if (!state)
+               return NULL;
 
        /* setup the state */
        state->config = config;
@@ -367,10 +367,6 @@ struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
        state->frontend.demodulator_priv = state;
 
        return &state->frontend;
-
-error:
-       kfree(state);
-       return NULL;
 }
 EXPORT_SYMBOL(s5h1432_attach);
 
index cd2288c07147a7614d7d37ef0022400e6b05d318..a271ac3eaec04dc4e85c62a616837bfb4f27ff4f 100644 (file)
@@ -487,9 +487,9 @@ struct dvb_frontend *s921_attach(const struct s921_config *config,
                kzalloc(sizeof(struct s921_state), GFP_KERNEL);
 
        dprintk("\n");
-       if (state == NULL) {
+       if (!state) {
                rc("Unable to kzalloc\n");
-               goto rcor;
+               return NULL;
        }
 
        /* setup the state */
@@ -502,11 +502,6 @@ struct dvb_frontend *s921_attach(const struct s921_config *config,
        state->frontend.demodulator_priv = state;
 
        return &state->frontend;
-
-rcor:
-       kfree(state);
-
-       return NULL;
 }
 EXPORT_SYMBOL(s921_attach);
 
index a68a64800df77ff7123ae6d18434820d6c95a2b4..73b47cc6a13b3b8c2f6ca85d0ee1d9eee71120c1 100644 (file)
@@ -343,7 +343,7 @@ static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout)
                        return -ETIMEDOUT;
                }
                msleep(10);
-       };
+       }
 
        return 0;
 }
@@ -472,7 +472,7 @@ static int si21xx_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
                break;
        default:
                return -EINVAL;
-       };
+       }
 }
 
 static int si21xx_init(struct dvb_frontend *fe)
index e37274c8f14e004c6058c64d053304704f8196ee..2aa8ef76eba259efba6490590f5201f0882e5805 100644 (file)
@@ -188,7 +188,7 @@ static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        switch (p->hierarchy) {
        case HIERARCHY_NONE:
@@ -207,7 +207,7 @@ static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        switch (p->code_rate_HP) {
        case FEC_1_2:
@@ -229,7 +229,7 @@ static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        if (known_parameters)
                *reg0xc05 |= (2 << 1);  /* use specified parameters */
index f4096ccb226e4b76146e001a4d78db1f52d7d756..1bb81b5ae6e0c69516ed4b7a65c9bef1280459ab 100644 (file)
@@ -229,7 +229,7 @@ static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05)
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        switch (p->hierarchy) {
        case HIERARCHY_NONE:
@@ -248,7 +248,7 @@ static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05)
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        switch (p->code_rate_HP) {
        case FEC_1_2:
@@ -270,7 +270,7 @@ static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05)
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        if (known_parameters)
                *reg0xc05 |= (2 << 1);  /* use specified parameters */
index 2e93e65d2cdb0e336f881d8b0b5efbd50fd1bbce..45f9523f968f903d463d56f5baf927662b7ffbc0 100644 (file)
@@ -575,8 +575,8 @@ struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
        struct stb6100_state *state = NULL;
 
        state = kzalloc(sizeof (struct stb6100_state), GFP_KERNEL);
-       if (state == NULL)
-               goto error;
+       if (!state)
+               return NULL;
 
        state->config           = config;
        state->i2c              = i2c;
@@ -587,10 +587,6 @@ struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
 
        printk("%s: Attaching STB6100 \n", __func__);
        return fe;
-
-error:
-       kfree(state);
-       return NULL;
 }
 
 static int stb6100_release(struct dvb_frontend *fe)
index 057b5f8effc0dec16c24f3753329bf8ed354e8bb..92a6075cd82f343f0f91fcd0b6cb13b4f07972fd 100644 (file)
@@ -199,7 +199,7 @@ static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout)
                        return -ETIMEDOUT;
                }
                msleep(10);
-       };
+       }
 
        return 0;
 }
@@ -216,7 +216,7 @@ static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout)
                        return -ETIMEDOUT;
                }
                msleep(10);
-       };
+       }
 
        return 0;
 }
@@ -387,7 +387,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        if (state->config->op0_off)
                reg0x0c &= ~0x10;
index 7f1badaf0d03044b2c2e4779ed746e2d03bbae0c..262dfa503c2a3e2db6cca50a5028d57ca46736df 100644 (file)
@@ -1552,8 +1552,8 @@ static int stv0900_status(struct stv0900_internal *intp,
                bitrate = (stv0900_get_mclk_freq(intp, intp->quartz)/1000000)
                        * (tsbitrate1_val << 8 | tsbitrate0_val);
                bitrate /= 16384;
-               dprintk("TS bitrate = %d Mbit/sec \n", bitrate);
-       };
+               dprintk("TS bitrate = %d Mbit/sec\n", bitrate);
+       }
 
        return locked;
 }
index 2c1c759a4f42f2ee1b073bba1b4d127da1d00f6b..63cc12378d9aac4cfc7c2ad23be3e851ce9e361e 100644 (file)
@@ -228,8 +228,8 @@ struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
        struct dvb_tuner_info *info;
 
        state = kzalloc(sizeof(struct tda665x_state), GFP_KERNEL);
-       if (state == NULL)
-               goto exit;
+       if (!state)
+               return NULL;
 
        state->config           = config;
        state->i2c              = i2c;
@@ -246,10 +246,6 @@ struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
        printk(KERN_DEBUG "%s: Attaching TDA665x (%s) tuner\n", __func__, info->name);
 
        return fe;
-
-exit:
-       kfree(state);
-       return NULL;
 }
 EXPORT_SYMBOL(tda665x_attach);
 
index 15912c96926adde19a7fbb7c50663efb146ccdf3..9d08350fe4b035cca635d3368d75591897e4e035 100644 (file)
@@ -175,7 +175,7 @@ static void tda8083_wait_diseqc_fifo (struct tda8083_state* state, int timeout)
               !(tda8083_readreg(state, 0x02) & 0x80))
        {
                msleep(50);
-       };
+       }
 }
 
 static int tda8083_set_tone (struct tda8083_state* state, fe_sec_tone_mode_t tone)
@@ -215,7 +215,7 @@ static int tda8083_send_diseqc_burst (struct tda8083_state* state, fe_sec_mini_c
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        tda8083_wait_diseqc_fifo (state, 100);
 
index d8eac3e30a7ea99217e5b149de79752e73f594cf..2cee69e34184304b7824752aadfd14d4b1d205b8 100644 (file)
@@ -599,7 +599,7 @@ static void cx23885_initialize(struct i2c_client *client)
                cx25840_write4(client, 0x114, 0x01bf0c9e);
                cx25840_write4(client, 0x110, 0x000a030c);
                break;
-       };
+       }
 
        /* ADC2 input select */
        cx25840_write(client, 0x102, 0x10);
index 86c815be348cbe9214de2f87d1915b01a2452555..90a6c520f115587f96d5e0174c01dd55480bd768 100644 (file)
 #ifndef M5MOLS_H
 #define M5MOLS_H
 
+#include <linux/sizes.h>
 #include <media/v4l2-subdev.h>
 #include "m5mols_reg.h"
 
+
+/* An amount of data transmitted in addition to the value
+ * determined by CAPP_JPEG_SIZE_MAX register.
+ */
+#define M5MOLS_JPEG_TAGS_SIZE          0x20000
+#define M5MOLS_MAIN_JPEG_SIZE_MAX      (5 * SZ_1M)
+
 extern int m5mols_debug;
 
 enum m5mols_restype {
@@ -67,12 +75,14 @@ struct m5mols_exif {
 /**
  * struct m5mols_capture - Structure for the capture capability
  * @exif: EXIF information
+ * @buf_size: internal JPEG frame buffer size, in bytes
  * @main: size in bytes of the main image
  * @thumb: size in bytes of the thumb image, if it was accompanied
  * @total: total size in bytes of the produced image
  */
 struct m5mols_capture {
        struct m5mols_exif exif;
+       unsigned int buf_size;
        u32 main;
        u32 thumb;
        u32 total;
index cb243bd278ceecce60163b6eed41ce8cb2d5c019..ab34ccedf31ea7a1a72adfe9d3324103de92b7f7 100644 (file)
@@ -105,6 +105,7 @@ static int m5mols_capture_info(struct m5mols_info *info)
 
 int m5mols_start_capture(struct m5mols_info *info)
 {
+       unsigned int framesize = info->cap.buf_size - M5MOLS_JPEG_TAGS_SIZE;
        struct v4l2_subdev *sd = &info->sd;
        int ret;
 
@@ -120,6 +121,8 @@ int m5mols_start_capture(struct m5mols_info *info)
                ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);
        if (!ret)
                ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, info->resolution);
+       if (!ret)
+               ret = m5mols_write(sd, CAPP_JPEG_SIZE_MAX, framesize);
        if (!ret)
                ret = m5mols_set_mode(info, REG_CAPTURE);
        if (!ret)
index 2f490ef26c388e2b868369dd189299430288efa3..8131d651de9ef11ea5c10d8e4111e9c8e4468896 100644 (file)
@@ -599,6 +599,51 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        return ret;
 }
 
+static int m5mols_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+                                struct v4l2_mbus_frame_desc *fd)
+{
+       struct m5mols_info *info = to_m5mols(sd);
+
+       if (pad != 0 || fd == NULL)
+               return -EINVAL;
+
+       mutex_lock(&info->lock);
+       /*
+        * .get_frame_desc is only used for compressed formats,
+        * thus we always return the capture frame parameters here.
+        */
+       fd->entry[0].length = info->cap.buf_size;
+       fd->entry[0].pixelcode = info->ffmt[M5MOLS_RESTYPE_CAPTURE].code;
+       mutex_unlock(&info->lock);
+
+       fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
+       fd->num_entries = 1;
+
+       return 0;
+}
+
+static int m5mols_set_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+                                struct v4l2_mbus_frame_desc *fd)
+{
+       struct m5mols_info *info = to_m5mols(sd);
+       struct v4l2_mbus_framefmt *mf = &info->ffmt[M5MOLS_RESTYPE_CAPTURE];
+
+       if (pad != 0 || fd == NULL)
+               return -EINVAL;
+
+       fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
+       fd->num_entries = 1;
+       fd->entry[0].length = clamp_t(u32, fd->entry[0].length,
+                                     mf->width * mf->height,
+                                     M5MOLS_MAIN_JPEG_SIZE_MAX);
+       mutex_lock(&info->lock);
+       info->cap.buf_size = fd->entry[0].length;
+       mutex_unlock(&info->lock);
+
+       return 0;
+}
+
+
 static int m5mols_enum_mbus_code(struct v4l2_subdev *sd,
                                 struct v4l2_subdev_fh *fh,
                                 struct v4l2_subdev_mbus_code_enum *code)
@@ -615,6 +660,8 @@ static struct v4l2_subdev_pad_ops m5mols_pad_ops = {
        .enum_mbus_code = m5mols_enum_mbus_code,
        .get_fmt        = m5mols_get_fmt,
        .set_fmt        = m5mols_set_fmt,
+       .get_frame_desc = m5mols_get_frame_desc,
+       .set_frame_desc = m5mols_set_frame_desc,
 };
 
 /**
index 14d4be72aeff67b09c9dafc98416490b1acc3412..58d8027508dfe338a7b4497b2fe77793cdf3312e 100644 (file)
 #define REG_JPEG               0x10
 
 #define CAPP_MAIN_IMAGE_SIZE   I2C_REG(CAT_CAPT_PARM, 0x01, 1)
+#define CAPP_JPEG_SIZE_MAX     I2C_REG(CAT_CAPT_PARM, 0x0f, 4)
 #define CAPP_JPEG_RATIO                I2C_REG(CAT_CAPT_PARM, 0x17, 1)
 
 #define CAPP_MCC_MODE          I2C_REG(CAT_CAPT_PARM, 0x1d, 1)
index 2c0f4077c4916215da4cff1580b79fbce27c4fe6..e32833262d32a6323c75f74e47dc89c9663d3ff4 100644 (file)
@@ -574,7 +574,6 @@ static int mt9p031_set_crop(struct v4l2_subdev *subdev,
  * V4L2 subdev control operations
  */
 
-#define V4L2_CID_TEST_PATTERN          (V4L2_CID_USER_BASE | 0x1001)
 #define V4L2_CID_BLC_AUTO              (V4L2_CID_USER_BASE | 0x1002)
 #define V4L2_CID_BLC_TARGET_LEVEL      (V4L2_CID_USER_BASE | 0x1003)
 #define V4L2_CID_BLC_ANALOG_OFFSET     (V4L2_CID_USER_BASE | 0x1004)
@@ -739,18 +738,6 @@ static const char * const mt9p031_test_pattern_menu[] = {
 
 static const struct v4l2_ctrl_config mt9p031_ctrls[] = {
        {
-               .ops            = &mt9p031_ctrl_ops,
-               .id             = V4L2_CID_TEST_PATTERN,
-               .type           = V4L2_CTRL_TYPE_MENU,
-               .name           = "Test Pattern",
-               .min            = 0,
-               .max            = ARRAY_SIZE(mt9p031_test_pattern_menu) - 1,
-               .step           = 0,
-               .def            = 0,
-               .flags          = 0,
-               .menu_skip_mask = 0,
-               .qmenu          = mt9p031_test_pattern_menu,
-       }, {
                .ops            = &mt9p031_ctrl_ops,
                .id             = V4L2_CID_BLC_AUTO,
                .type           = V4L2_CTRL_TYPE_BOOLEAN,
@@ -950,7 +937,7 @@ static int mt9p031_probe(struct i2c_client *client,
        mt9p031->model = did->driver_data;
        mt9p031->reset = -1;
 
-       v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 5);
+       v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 6);
 
        v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
                          V4L2_CID_EXPOSURE, MT9P031_SHUTTER_WIDTH_MIN,
@@ -966,6 +953,10 @@ static int mt9p031_probe(struct i2c_client *client,
        v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
                          V4L2_CID_PIXEL_RATE, pdata->target_freq,
                          pdata->target_freq, 1, pdata->target_freq);
+       v4l2_ctrl_new_std_menu_items(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+                         V4L2_CID_TEST_PATTERN,
+                         ARRAY_SIZE(mt9p031_test_pattern_menu) - 1, 0,
+                         0, mt9p031_test_pattern_menu);
 
        for (i = 0; i < ARRAY_SIZE(mt9p031_ctrls); ++i)
                v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL);
index 6d343adf891d1a5497b4cb4a4ecebaaf9328d1d0..2e189d8b71bb218725b76d894172420d30bdfe6a 100644 (file)
@@ -371,7 +371,7 @@ static int mt9t001_set_crop(struct v4l2_subdev *subdev,
  * V4L2 subdev control operations
  */
 
-#define V4L2_CID_TEST_PATTERN          (V4L2_CID_USER_BASE | 0x1001)
+#define V4L2_CID_TEST_PATTERN_COLOR    (V4L2_CID_USER_BASE | 0x1001)
 #define V4L2_CID_BLACK_LEVEL_AUTO      (V4L2_CID_USER_BASE | 0x1002)
 #define V4L2_CID_BLACK_LEVEL_OFFSET    (V4L2_CID_USER_BASE | 0x1003)
 #define V4L2_CID_BLACK_LEVEL_CALIBRATE (V4L2_CID_USER_BASE | 0x1004)
@@ -487,12 +487,11 @@ static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl)
                                     ctrl->val >> 16);
 
        case V4L2_CID_TEST_PATTERN:
-               ret = mt9t001_set_output_control(mt9t001,
+               return mt9t001_set_output_control(mt9t001,
                        ctrl->val ? 0 : MT9T001_OUTPUT_CONTROL_TEST_DATA,
                        ctrl->val ? MT9T001_OUTPUT_CONTROL_TEST_DATA : 0);
-               if (ret < 0)
-                       return ret;
 
+       case V4L2_CID_TEST_PATTERN_COLOR:
                return mt9t001_write(client, MT9T001_TEST_DATA, ctrl->val << 2);
 
        case V4L2_CID_BLACK_LEVEL_AUTO:
@@ -533,12 +532,17 @@ static struct v4l2_ctrl_ops mt9t001_ctrl_ops = {
        .s_ctrl = mt9t001_s_ctrl,
 };
 
+static const char * const mt9t001_test_pattern_menu[] = {
+       "Disabled",
+       "Enabled",
+};
+
 static const struct v4l2_ctrl_config mt9t001_ctrls[] = {
        {
                .ops            = &mt9t001_ctrl_ops,
-               .id             = V4L2_CID_TEST_PATTERN,
+               .id             = V4L2_CID_TEST_PATTERN_COLOR,
                .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Test pattern",
+               .name           = "Test Pattern Color",
                .min            = 0,
                .max            = 1023,
                .step           = 1,
@@ -741,7 +745,7 @@ static int mt9t001_probe(struct i2c_client *client,
                return -ENOMEM;
 
        v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) +
-                                               ARRAY_SIZE(mt9t001_gains) + 3);
+                                               ARRAY_SIZE(mt9t001_gains) + 4);
 
        v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
                          V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN,
@@ -752,6 +756,10 @@ static int mt9t001_probe(struct i2c_client *client,
        v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
                          V4L2_CID_PIXEL_RATE, pdata->ext_clk, pdata->ext_clk,
                          1, pdata->ext_clk);
+       v4l2_ctrl_new_std_menu_items(&mt9t001->ctrls, &mt9t001_ctrl_ops,
+                       V4L2_CID_TEST_PATTERN,
+                       ARRAY_SIZE(mt9t001_test_pattern_menu) - 1, 0,
+                       0, mt9t001_test_pattern_menu);
 
        for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i)
                v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL);
index e2177405dad2eb65de2bbc635727dca3f86099d1..3f356cb282567e882361b7958146090d9092cb43 100644 (file)
@@ -141,6 +141,10 @@ struct mt9v032 {
        u16 chip_control;
        u16 aec_agc;
        u16 hblank;
+       struct {
+               struct v4l2_ctrl *test_pattern;
+               struct v4l2_ctrl *test_pattern_color;
+       };
 };
 
 static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
@@ -500,7 +504,7 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev,
  * V4L2 subdev control operations
  */
 
-#define V4L2_CID_TEST_PATTERN          (V4L2_CID_USER_BASE | 0x1001)
+#define V4L2_CID_TEST_PATTERN_COLOR    (V4L2_CID_USER_BASE | 0x1001)
 
 static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
 {
@@ -545,7 +549,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
                break;
 
        case V4L2_CID_TEST_PATTERN:
-               switch (ctrl->val) {
+               switch (mt9v032->test_pattern->val) {
                case 0:
                        data = 0;
                        break;
@@ -562,13 +566,13 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
                             | MT9V032_TEST_PATTERN_ENABLE;
                        break;
                default:
-                       data = (ctrl->val << MT9V032_TEST_PATTERN_DATA_SHIFT)
+                       data = (mt9v032->test_pattern_color->val <<
+                               MT9V032_TEST_PATTERN_DATA_SHIFT)
                             | MT9V032_TEST_PATTERN_USE_DATA
                             | MT9V032_TEST_PATTERN_ENABLE
                             | MT9V032_TEST_PATTERN_FLIP;
                        break;
                }
-
                return mt9v032_write(client, MT9V032_TEST_PATTERN, data);
        }
 
@@ -579,18 +583,24 @@ static struct v4l2_ctrl_ops mt9v032_ctrl_ops = {
        .s_ctrl = mt9v032_s_ctrl,
 };
 
-static const struct v4l2_ctrl_config mt9v032_ctrls[] = {
-       {
-               .ops            = &mt9v032_ctrl_ops,
-               .id             = V4L2_CID_TEST_PATTERN,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Test pattern",
-               .min            = 0,
-               .max            = 1023,
-               .step           = 1,
-               .def            = 0,
-               .flags          = 0,
-       }
+static const char * const mt9v032_test_pattern_menu[] = {
+       "Disabled",
+       "Gray Vertical Shade",
+       "Gray Horizontal Shade",
+       "Gray Diagonal Shade",
+       "Plain",
+};
+
+static const struct v4l2_ctrl_config mt9v032_test_pattern_color = {
+       .ops            = &mt9v032_ctrl_ops,
+       .id             = V4L2_CID_TEST_PATTERN_COLOR,
+       .type           = V4L2_CTRL_TYPE_INTEGER,
+       .name           = "Test Pattern Color",
+       .min            = 0,
+       .max            = 1023,
+       .step           = 1,
+       .def            = 0,
+       .flags          = 0,
 };
 
 /* -----------------------------------------------------------------------------
@@ -741,7 +751,7 @@ static int mt9v032_probe(struct i2c_client *client,
        mutex_init(&mt9v032->power_lock);
        mt9v032->pdata = pdata;
 
-       v4l2_ctrl_handler_init(&mt9v032->ctrls, ARRAY_SIZE(mt9v032_ctrls) + 8);
+       v4l2_ctrl_handler_init(&mt9v032->ctrls, 10);
 
        v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
                          V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
@@ -763,6 +773,14 @@ static int mt9v032_probe(struct i2c_client *client,
                          V4L2_CID_VBLANK, MT9V032_VERTICAL_BLANKING_MIN,
                          MT9V032_VERTICAL_BLANKING_MAX, 1,
                          MT9V032_VERTICAL_BLANKING_DEF);
+       mt9v032->test_pattern = v4l2_ctrl_new_std_menu_items(&mt9v032->ctrls,
+                               &mt9v032_ctrl_ops, V4L2_CID_TEST_PATTERN,
+                               ARRAY_SIZE(mt9v032_test_pattern_menu) - 1, 0, 0,
+                               mt9v032_test_pattern_menu);
+       mt9v032->test_pattern_color = v4l2_ctrl_new_custom(&mt9v032->ctrls,
+                                     &mt9v032_test_pattern_color, NULL);
+
+       v4l2_ctrl_cluster(2, &mt9v032->test_pattern);
 
        mt9v032->pixel_rate =
                v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
@@ -784,8 +802,6 @@ static int mt9v032_probe(struct i2c_client *client,
                v4l2_ctrl_cluster(2, &mt9v032->link_freq);
        }
 
-       for (i = 0; i < ARRAY_SIZE(mt9v032_ctrls); ++i)
-               v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_ctrls[i], NULL);
 
        mt9v032->subdev.ctrl_handler = &mt9v032->ctrls;
 
index 78ac5744cb5dd55ffda31edf6e7ead3e74fb1e0c..d2d298b6354e8038d95076fdc6a9bd8a68f256d4 100644 (file)
@@ -684,6 +684,11 @@ static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl)
                &container_of(ctrl->handler, struct ov2640_priv, hdl)->subdev;
        struct i2c_client  *client = v4l2_get_subdevdata(sd);
        u8 val;
+       int ret;
+
+       ret = i2c_smbus_write_byte_data(client, BANK_SEL, BANK_SEL_SENS);
+       if (ret < 0)
+               return ret;
 
        switch (ctrl->id) {
        case V4L2_CID_VFLIP:
index e5c0eedebc58b5129bbaf0bedd3b97d81ada4a19..c31cc04fffd282a6194ff7cb1d90bfb3a4634a2a 100644 (file)
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-chip-ident.h>
 
+#define THS7303_CHANNEL_1      1
+#define THS7303_CHANNEL_2      2
+#define THS7303_CHANNEL_3      3
+
+enum ths7303_filter_mode {
+       THS7303_FILTER_MODE_480I_576I,
+       THS7303_FILTER_MODE_480P_576P,
+       THS7303_FILTER_MODE_720P_1080I,
+       THS7303_FILTER_MODE_1080P,
+       THS7303_FILTER_MODE_DISABLE
+};
+
 MODULE_DESCRIPTION("TI THS7303 video amplifier driver");
 MODULE_AUTHOR("Chaithrika U S");
 MODULE_LICENSE("GPL");
@@ -37,35 +49,96 @@ module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Debug level 0-1");
 
 /* following function is used to set ths7303 */
-static int ths7303_setvalue(struct v4l2_subdev *sd, v4l2_std_id std)
+int ths7303_setval(struct v4l2_subdev *sd, enum ths7303_filter_mode mode)
 {
+       u8 input_bias_chroma = 3;
+       u8 input_bias_luma = 3;
+       int disable = 0;
        int err = 0;
-       u8 val;
-       struct i2c_client *client;
+       u8 val = 0;
+       u8 temp;
 
-       client = v4l2_get_subdevdata(sd);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (std & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) {
-               val = 0x02;
-               v4l2_dbg(1, debug, sd, "setting value for SDTV format\n");
-       } else {
-               val = 0x00;
-               v4l2_dbg(1, debug, sd, "disabling all channels\n");
+       if (!client)
+               return -EINVAL;
+
+       switch (mode) {
+       case THS7303_FILTER_MODE_1080P:
+               val = (3 << 6);
+               val |= (3 << 3);
+               break;
+       case THS7303_FILTER_MODE_720P_1080I:
+               val = (2 << 6);
+               val |= (2 << 3);
+               break;
+       case THS7303_FILTER_MODE_480P_576P:
+               val = (1 << 6);
+               val |= (1 << 3);
+               break;
+       case THS7303_FILTER_MODE_480I_576I:
+               break;
+       case THS7303_FILTER_MODE_DISABLE:
+               pr_info("mode disabled\n");
+               /* disable all channels */
+               disable = 1;
+       default:
+               /* disable all channels */
+               disable = 1;
        }
+       /* Setup channel 2 - Luma - Green */
+       temp = val;
+       if (!disable)
+               val |= input_bias_luma;
+       err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_2, val);
+       if (err)
+               goto out;
 
-       err |= i2c_smbus_write_byte_data(client, 0x01, val);
-       err |= i2c_smbus_write_byte_data(client, 0x02, val);
-       err |= i2c_smbus_write_byte_data(client, 0x03, val);
+       /* setup two chroma channels */
+       if (!disable)
+               temp |= input_bias_chroma;
 
+       err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_1, temp);
        if (err)
-               v4l2_err(sd, "write failed\n");
+               goto out;
 
+       err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_3, temp);
+       if (err)
+               goto out;
+       return err;
+out:
+       pr_info("write byte data failed\n");
        return err;
 }
 
 static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
 {
-       return ths7303_setvalue(sd, norm);
+       if (norm & (V4L2_STD_ALL & ~V4L2_STD_SECAM))
+               return ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I);
+       else
+               return ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
+}
+
+/* for setting filter for HD output */
+static int ths7303_s_dv_timings(struct v4l2_subdev *sd,
+                              struct v4l2_dv_timings *dv_timings)
+{
+       u32 height = dv_timings->bt.height;
+       int interlaced = dv_timings->bt.interlaced;
+       int res = 0;
+
+       if (height == 1080 && !interlaced)
+               res = ths7303_setval(sd, THS7303_FILTER_MODE_1080P);
+       else if ((height == 720 && !interlaced) ||
+                       (height == 1080 && interlaced))
+               res = ths7303_setval(sd, THS7303_FILTER_MODE_720P_1080I);
+       else if ((height == 480 || height == 576) && !interlaced)
+               res = ths7303_setval(sd, THS7303_FILTER_MODE_480P_576P);
+       else
+               /* disable all channels */
+               res = ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
+
+       return res;
 }
 
 static int ths7303_g_chip_ident(struct v4l2_subdev *sd,
@@ -78,6 +151,7 @@ static int ths7303_g_chip_ident(struct v4l2_subdev *sd,
 
 static const struct v4l2_subdev_video_ops ths7303_video_ops = {
        .s_std_output   = ths7303_s_std_output,
+       .s_dv_timings    = ths7303_s_dv_timings,
 };
 
 static const struct v4l2_subdev_core_ops ths7303_core_ops = {
@@ -107,7 +181,7 @@ static int ths7303_probe(struct i2c_client *client,
 
        v4l2_i2c_subdev_init(sd, client, &ths7303_ops);
 
-       return ths7303_setvalue(sd, std_id);
+       return ths7303_s_std_output(sd, std_id);
 }
 
 static int ths7303_remove(struct i2c_client *client)
index 1f3943bb87d531bdc16337feb7f6a36c2e232fbb..d5e10215a28f46197d480aa51156cab605d7ef21 100644 (file)
@@ -519,6 +519,12 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
 
        *std_id = V4L2_STD_UNKNOWN;
 
+       /* To query the standard the TVP514x must power on the ADCs. */
+       if (!decoder->streaming) {
+               tvp514x_s_stream(sd, 1);
+               msleep(LOCK_RETRY_DELAY);
+       }
+
        /* query the current standard */
        current_std = tvp514x_query_current_std(sd);
        if (current_std == STD_INVALID)
@@ -625,25 +631,12 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd,
        int err;
        enum tvp514x_input input_sel;
        enum tvp514x_output output_sel;
-       u8 sync_lock_status, lock_mask;
-       int try_count = LOCK_RETRY_COUNT;
 
        if ((input >= INPUT_INVALID) ||
                        (output >= OUTPUT_INVALID))
                /* Index out of bound */
                return -EINVAL;
 
-       /*
-        * For the sequence streamon -> streamoff and again s_input
-        * it fails to lock the signal, since streamoff puts TVP514x
-        * into power off state which leads to failure in sub-sequent s_input.
-        *
-        * So power up the TVP514x device here, since it is important to lock
-        * the signal at this stage.
-        */
-       if (!decoder->streaming)
-               tvp514x_s_stream(sd, 1);
-
        input_sel = input;
        output_sel = output;
 
@@ -660,64 +653,6 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd,
 
        decoder->tvp514x_regs[REG_INPUT_SEL].val = input_sel;
        decoder->tvp514x_regs[REG_OUTPUT_FORMATTER1].val = output_sel;
-
-       /* Clear status */
-       msleep(LOCK_RETRY_DELAY);
-       err =
-           tvp514x_write_reg(sd, REG_CLEAR_LOST_LOCK, 0x01);
-       if (err)
-               return err;
-
-       switch (input_sel) {
-       case INPUT_CVBS_VI1A:
-       case INPUT_CVBS_VI1B:
-       case INPUT_CVBS_VI1C:
-       case INPUT_CVBS_VI2A:
-       case INPUT_CVBS_VI2B:
-       case INPUT_CVBS_VI2C:
-       case INPUT_CVBS_VI3A:
-       case INPUT_CVBS_VI3B:
-       case INPUT_CVBS_VI3C:
-       case INPUT_CVBS_VI4A:
-               lock_mask = STATUS_CLR_SUBCAR_LOCK_BIT |
-                       STATUS_HORZ_SYNC_LOCK_BIT |
-                       STATUS_VIRT_SYNC_LOCK_BIT;
-               break;
-
-       case INPUT_SVIDEO_VI2A_VI1A:
-       case INPUT_SVIDEO_VI2B_VI1B:
-       case INPUT_SVIDEO_VI2C_VI1C:
-       case INPUT_SVIDEO_VI2A_VI3A:
-       case INPUT_SVIDEO_VI2B_VI3B:
-       case INPUT_SVIDEO_VI2C_VI3C:
-       case INPUT_SVIDEO_VI4A_VI1A:
-       case INPUT_SVIDEO_VI4A_VI1B:
-       case INPUT_SVIDEO_VI4A_VI1C:
-       case INPUT_SVIDEO_VI4A_VI3A:
-       case INPUT_SVIDEO_VI4A_VI3B:
-       case INPUT_SVIDEO_VI4A_VI3C:
-               lock_mask = STATUS_HORZ_SYNC_LOCK_BIT |
-                       STATUS_VIRT_SYNC_LOCK_BIT;
-               break;
-       /* Need to add other interfaces*/
-       default:
-               return -EINVAL;
-       }
-
-       while (try_count-- > 0) {
-               /* Allow decoder to sync up with new input */
-               msleep(LOCK_RETRY_DELAY);
-
-               sync_lock_status = tvp514x_read_reg(sd,
-                               REG_STATUS1);
-               if (lock_mask == (sync_lock_status & lock_mask))
-                       /* Input detected */
-                       break;
-       }
-
-       if (try_count < 0)
-               return -EINVAL;
-
        decoder->input = input;
        decoder->output = output;
 
index b68918c97f66868baaa1ece4da01ad286f391747..56c6c77793d726f48c50eefbe6cb399a46b19ffe 100644 (file)
@@ -668,6 +668,12 @@ static const struct v4l2_queryctrl bttv_ctls[] = {
                .default_value = 32768,
                .type          = V4L2_CTRL_TYPE_INTEGER,
        },{
+               .id            = V4L2_CID_COLOR_KILLER,
+               .name          = "Color killer",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       }, {
                .id            = V4L2_CID_HUE,
                .name          = "Hue",
                .minimum       = 0,
@@ -1474,6 +1480,9 @@ static int bttv_g_ctrl(struct file *file, void *priv,
        case V4L2_CID_SATURATION:
                c->value = btv->saturation;
                break;
+       case V4L2_CID_COLOR_KILLER:
+               c->value = btv->opt_color_killer;
+               break;
 
        case V4L2_CID_AUDIO_MUTE:
        case V4L2_CID_AUDIO_VOLUME:
@@ -1526,7 +1535,6 @@ static int bttv_s_ctrl(struct file *file, void *f,
                                        struct v4l2_control *c)
 {
        int err;
-       int val;
        struct bttv_fh *fh = f;
        struct bttv *btv = fh->btv;
 
@@ -1547,6 +1555,16 @@ static int bttv_s_ctrl(struct file *file, void *f,
        case V4L2_CID_SATURATION:
                bt848_sat(btv, c->value);
                break;
+       case V4L2_CID_COLOR_KILLER:
+               btv->opt_color_killer = c->value;
+               if (btv->opt_color_killer) {
+                       btor(BT848_SCLOOP_CKILL, BT848_E_SCLOOP);
+                       btor(BT848_SCLOOP_CKILL, BT848_O_SCLOOP);
+               } else {
+                       btand(~BT848_SCLOOP_CKILL, BT848_E_SCLOOP);
+                       btand(~BT848_SCLOOP_CKILL, BT848_O_SCLOOP);
+               }
+               break;
        case V4L2_CID_AUDIO_MUTE:
                audio_mute(btv, c->value);
                /* fall through */
@@ -1564,9 +1582,13 @@ static int bttv_s_ctrl(struct file *file, void *f,
 
        case V4L2_CID_PRIVATE_CHROMA_AGC:
                btv->opt_chroma_agc = c->value;
-               val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
-               btwrite(val, BT848_E_SCLOOP);
-               btwrite(val, BT848_O_SCLOOP);
+               if (btv->opt_chroma_agc) {
+                       btor(BT848_SCLOOP_CAGC, BT848_E_SCLOOP);
+                       btor(BT848_SCLOOP_CAGC, BT848_O_SCLOOP);
+               } else {
+                       btand(~BT848_SCLOOP_CAGC, BT848_E_SCLOOP);
+                       btand(~BT848_SCLOOP_CAGC, BT848_O_SCLOOP);
+               }
                break;
        case V4L2_CID_PRIVATE_COMBFILTER:
                btv->opt_combfilter = c->value;
index 70fd4f23f605aa8374799239ca71ca18219bf9d2..9ec0adba236c5bf559fecfeab02f8ab7bd394c0c 100644 (file)
@@ -429,6 +429,7 @@ struct bttv {
        int opt_lumafilter;
        int opt_automute;
        int opt_chroma_agc;
+       int opt_color_killer;
        int opt_adc_crush;
        int opt_vcr_hack;
        int opt_whitecrush_upper;
index ee3884fbc9ce3e95120e2e421724833629c6cb11..7d96fab7d2463bd8ba6254581547a258a61329bc 100644 (file)
@@ -646,7 +646,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct
                dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_PID Success !");
        default:
                result = -EOPNOTSUPP;
-       };
+       }
  free_mem_and_exit:
        kfree (p_ca_message);
        kfree (p_ca_slot_info);
index aee7f0dacff11a8a61764c274559bf5454909fad..495781ee47113e88e792199d2ce4181e8bf1b953 100644 (file)
@@ -416,7 +416,7 @@ static void netup_read_ci_status(struct work_struct *work)
                                DVB_CA_EN50221_POLL_CAM_READY : 0);
                ci_dbg_print("%s: setting CI[1] status = 0x%x\n",
                                __func__, inter->state[1]->status);
-       };
+       }
 
        if (inter->state[0] != NULL) {
                inter->state[0]->status =
@@ -425,7 +425,7 @@ static void netup_read_ci_status(struct work_struct *work)
                                DVB_CA_EN50221_POLL_CAM_READY : 0);
                ci_dbg_print("%s: setting CI[0] status = 0x%x\n",
                                __func__, inter->state[0]->status);
-       };
+       }
 }
 
 /* CI irq handler */
index c9f15d6dec40ffa0cc4844313b6a5f7ce56d6946..6617774a326a38f98bd611816003a4907e596aff 100644 (file)
@@ -193,7 +193,7 @@ int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
                                0, &store, 1);
                if (ret != 0)
                        return ret;
-       };
+       }
        state->current_ci_flag = flag;
 
        mutex_lock(&dev->gpio_lock);
index 39a4a4b9ed7e893d97fe3460dcef33dc663de5b8..5acdf954ff6bcdadec1c1dfe248012f5a3bf7f84 100644 (file)
@@ -542,11 +542,13 @@ struct cx23885_board cx23885_boards[] = {
                        {
                                .type   = CX23885_VMUX_COMPOSITE1,
                                .vmux   = CX25840_COMPOSITE8,
+                               .amux   = CX25840_AUDIO7,
                        },
                        {
                                .type   = CX23885_VMUX_SVIDEO,
                                .vmux   = CX25840_SVIDEO_LUMA3 |
                                                CX25840_SVIDEO_CHROMA4,
+                               .amux   = CX25840_AUDIO7,
                        },
                        {
                                .type   = CX23885_VMUX_COMPONENT,
@@ -554,6 +556,7 @@ struct cx23885_board cx23885_boards[] = {
                                        CX25840_VIN1_CH1 |
                                        CX25840_VIN6_CH2 |
                                        CX25840_VIN7_CH3,
+                               .amux   = CX25840_AUDIO7,
                        },
                },
        },
index 8c4a9a5f9a504ff2959df17d189ab148644f6a03..1a21926ca412cbdab3cdb00841e40e930818f470 100644 (file)
@@ -508,7 +508,8 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
                (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1250) ||
                (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
                (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) ||
-               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850)) {
+               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) ||
+               (dev->board == CX23885_BOARD_MYGICA_X8507)) {
                /* Configure audio routing */
                v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
                        INPUT(input)->amux, 0, 0);
index c8c94fbf5d8d2c68382e2edd3901b93fb1be340d..d33fc1a2303087ccb416ed158708c31c9ddec4d3 100644 (file)
@@ -761,7 +761,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
        }
 
        /* Default if filename is empty string */
-       if (strcmp(dev->input_filename_ch2, "") == 0) {
+       if (strcmp(dev->_filename_ch2, "") == 0) {
                if (dev->_isNTSC_ch2) {
                        dev->_filename_ch2 = (dev->_pixel_format_ch2 ==
                                PIXEL_FRMT_411) ? "/root/vid411.yuv" :
index 52c13e0b6492c601400d3e999cd747307beba271..6759fff8eb640b57b4b9048bb48f3ef0dfa777c8 100644 (file)
@@ -808,7 +808,7 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
        }
 
        /* Default if filename is empty string */
-       if (strcmp(dev->input_filename, "") == 0) {
+       if (strcmp(dev->_filename, "") == 0) {
                if (dev->_isNTSC) {
                        dev->_filename =
                                (dev->_pixel_format == PIXEL_FRMT_411) ?
index def363fb71c0664a72e6cf8fff5d54d398b7d3bc..62184eb919e5d7563ab0c8d4a9c286c45131c92b 100644 (file)
@@ -721,7 +721,7 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
 
        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
        f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
+       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
        f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
        f->fmt.pix.width        = dev->width;
        f->fmt.pix.height       = dev->height;
@@ -739,7 +739,7 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
 
        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
        f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
+       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
        f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
        dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
                dev->width, dev->height, fh->mpegq.field );
@@ -755,7 +755,7 @@ static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
 
        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
        f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
+       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
        f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
        dev->width              = f->fmt.pix.width;
        dev->height             = f->fmt.pix.height;
index d803bba09525206e9710d401829251d829e04ede..666f83b2f3c01da335a825d7d7a567211a58b90d 100644 (file)
@@ -896,7 +896,7 @@ static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe,
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO;
 }
index c04fb618e10b78a22209575c2506e4aae270e575..d154bc19735688de10c35e47e65b719d71dbfecd 100644 (file)
@@ -450,7 +450,7 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id)
                        cx88_core_irq(core,status);
                if (status & PCI_INT_TSINT)
                        cx8802_mpeg_irq(dev);
-       };
+       }
        if (MAX_IRQ_LOOP == loop) {
                dprintk( 0, "clearing mask\n" );
                printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
index 770ec05b5e9b7da789db5f1ae3a2823066be1f23..424fd97495dcc8144852ee15417c991e30c10a89 100644 (file)
@@ -373,7 +373,7 @@ static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode)
                set_audio_registers(core, nicam_bgdki_common);
                set_audio_registers(core, nicam_default);
                break;
-       };
+       }
 
        mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS;
        set_audio_finish(core, mode);
@@ -639,7 +639,7 @@ static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
                dprintk("%s Warning: wrong value\n", __func__);
                return;
                break;
-       };
+       }
 
        mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
        set_audio_finish(core, mode);
index a146d50d77952fda04871e9a51c3136818d45f22..05171457bf282e42c47dfe00c4410c33cde74518 100644 (file)
@@ -1535,7 +1535,7 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id)
                        cx88_core_irq(core,status);
                if (status & PCI_INT_VIDINT)
                        cx8800_vid_irq(dev);
-       };
+       }
        if (10 == loop) {
                printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
                       core->name);
index 22f8758d047f247084814db5e70a75a3b6edd6a6..4a77124ee70e2cbda80a414413a85346b7a832c3 100644 (file)
@@ -1204,7 +1204,7 @@ int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, str
                break;
        default:
                /* nothing */;
-       };
+       }
        switch (c->id) {
        case V4L2_CID_BRIGHTNESS:
                dev->ctl_bright = c->value;
index f588d6296c769bbad1f2222a98bd3394cf1b6aa4..181c7686e412aa485e755867d8fad8e7f5f13bf8 100644 (file)
@@ -165,12 +165,12 @@ config VIDEO_SAMSUNG_S5P_JPEG
          This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
 
 config VIDEO_SAMSUNG_S5P_MFC
-       tristate "Samsung S5P MFC 5.1 Video Codec"
+       tristate "Samsung S5P MFC Video Codec"
        depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
        select VIDEOBUF2_DMA_CONTIG
        default n
        help
-           MFC 5.1 driver for V4L2.
+           MFC 5.1 and 6.x driver for V4L2
 
 config VIDEO_MX2_EMMAPRP
        tristate "MX2 eMMa-PrP support"
index c4a82a1a8a977f42431e47e5fba269173c48c272..69d7a58c92c3e81191adcd3d227f7352a9e5d4d0 100644 (file)
@@ -174,26 +174,6 @@ static int vpbe_get_current_mode_info(struct vpbe_device *vpbe_dev,
        return 0;
 }
 
-static int vpbe_get_dv_preset_info(struct vpbe_device *vpbe_dev,
-                                  unsigned int dv_preset)
-{
-       struct vpbe_config *cfg = vpbe_dev->cfg;
-       struct vpbe_enc_mode_info var;
-       int curr_output = vpbe_dev->current_out_index;
-       int i;
-
-       for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
-               var = cfg->outputs[curr_output].modes[i];
-               if ((var.timings_type & VPBE_ENC_DV_PRESET) &&
-                 (var.timings.dv_preset == dv_preset)) {
-                       vpbe_dev->current_timings = var;
-                       return 0;
-               }
-       }
-
-       return -EINVAL;
-}
-
 /* Get std by std id */
 static int vpbe_get_std_info(struct vpbe_device *vpbe_dev,
                             v4l2_std_id std_id)
@@ -206,7 +186,7 @@ static int vpbe_get_std_info(struct vpbe_device *vpbe_dev,
        for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
                var = cfg->outputs[curr_output].modes[i];
                if ((var.timings_type & VPBE_ENC_STD) &&
-                 (var.timings.std_id & std_id)) {
+                 (var.std_id & std_id)) {
                        vpbe_dev->current_timings = var;
                        return 0;
                }
@@ -344,38 +324,42 @@ static unsigned int vpbe_get_output(struct vpbe_device *vpbe_dev)
 }
 
 /**
- * vpbe_s_dv_preset - Set the given preset timings in the encoder
+ * vpbe_s_dv_timings - Set the given preset timings in the encoder
  *
- * Sets the preset if supported by the current encoder. Return the status.
+ * Sets the timings if supported by the current encoder. Return the status.
  * 0 - success & -EINVAL on error
  */
-static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev,
-                    struct v4l2_dv_preset *dv_preset)
+static int vpbe_s_dv_timings(struct vpbe_device *vpbe_dev,
+                   struct v4l2_dv_timings *dv_timings)
 {
        struct vpbe_config *cfg = vpbe_dev->cfg;
        int out_index = vpbe_dev->current_out_index;
+       struct vpbe_output *output = &cfg->outputs[out_index];
        int sd_index = vpbe_dev->current_sd_index;
-       int ret;
+       int ret, i;
 
 
        if (!(cfg->outputs[out_index].output.capabilities &
-           V4L2_OUT_CAP_PRESETS))
+           V4L2_OUT_CAP_DV_TIMINGS))
                return -EINVAL;
 
-       ret = vpbe_get_dv_preset_info(vpbe_dev, dv_preset->preset);
-
-       if (ret)
-               return ret;
-
+       for (i = 0; i < output->num_modes; i++) {
+               if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS &&
+                   !memcmp(&output->modes[i].dv_timings,
+                               dv_timings, sizeof(*dv_timings)))
+                       break;
+       }
+       if (i >= output->num_modes)
+               return -EINVAL;
+       vpbe_dev->current_timings = output->modes[i];
        mutex_lock(&vpbe_dev->lock);
 
-
        ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
-                                       s_dv_preset, dv_preset);
+                                       s_dv_timings, dv_timings);
        if (!ret && (vpbe_dev->amp != NULL)) {
                /* Call amplifier subdevice */
                ret = v4l2_subdev_call(vpbe_dev->amp, video,
-                               s_dv_preset, dv_preset);
+                               s_dv_timings, dv_timings);
        }
        /* set the lcd controller output for the given mode */
        if (!ret) {
@@ -392,17 +376,17 @@ static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev,
 }
 
 /**
- * vpbe_g_dv_preset - Get the preset in the current encoder
+ * vpbe_g_dv_timings - Get the timings in the current encoder
  *
- * Get the preset in the current encoder. Return the status. 0 - success
+ * Get the timings in the current encoder. Return the status. 0 - success
  * -EINVAL on error
  */
-static int vpbe_g_dv_preset(struct vpbe_device *vpbe_dev,
-                    struct v4l2_dv_preset *dv_preset)
+static int vpbe_g_dv_timings(struct vpbe_device *vpbe_dev,
+                    struct v4l2_dv_timings *dv_timings)
 {
        if (vpbe_dev->current_timings.timings_type &
-         VPBE_ENC_DV_PRESET) {
-               dv_preset->preset = vpbe_dev->current_timings.timings.dv_preset;
+         VPBE_ENC_CUSTOM_TIMINGS) {
+               *dv_timings = vpbe_dev->current_timings.dv_timings;
                return 0;
        }
 
@@ -410,13 +394,13 @@ static int vpbe_g_dv_preset(struct vpbe_device *vpbe_dev,
 }
 
 /**
- * vpbe_enum_dv_presets - Enumerate the dv presets in the current encoder
+ * vpbe_enum_dv_timings - Enumerate the dv timings in the current encoder
  *
- * Get the preset in the current encoder. Return the status. 0 - success
+ * Get the timings in the current encoder. Return the status. 0 - success
  * -EINVAL on error
  */
-static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev,
-                        struct v4l2_dv_enum_preset *preset_info)
+static int vpbe_enum_dv_timings(struct vpbe_device *vpbe_dev,
+                        struct v4l2_enum_dv_timings *timings)
 {
        struct vpbe_config *cfg = vpbe_dev->cfg;
        int out_index = vpbe_dev->current_out_index;
@@ -424,12 +408,12 @@ static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev,
        int j = 0;
        int i;
 
-       if (!(output->output.capabilities & V4L2_OUT_CAP_PRESETS))
+       if (!(output->output.capabilities & V4L2_OUT_CAP_DV_TIMINGS))
                return -EINVAL;
 
        for (i = 0; i < output->num_modes; i++) {
-               if (output->modes[i].timings_type == VPBE_ENC_DV_PRESET) {
-                       if (j == preset_info->index)
+               if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS) {
+                       if (j == timings->index)
                                break;
                        j++;
                }
@@ -437,9 +421,8 @@ static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev,
 
        if (i == output->num_modes)
                return -EINVAL;
-
-       return v4l_fill_dv_preset_info(output->modes[i].timings.dv_preset,
-                                       preset_info);
+       timings->timings = output->modes[i].dv_timings;
+       return 0;
 }
 
 /**
@@ -489,10 +472,10 @@ static int vpbe_s_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
  */
 static int vpbe_g_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
 {
-       struct vpbe_enc_mode_info cur_timings = vpbe_dev->current_timings;
+       struct vpbe_enc_mode_info *cur_timings = &vpbe_dev->current_timings;
 
-       if (cur_timings.timings_type & VPBE_ENC_STD) {
-               *std_id = cur_timings.timings.std_id;
+       if (cur_timings->timings_type & VPBE_ENC_STD) {
+               *std_id = cur_timings->std_id;
                return 0;
        }
 
@@ -511,7 +494,7 @@ static int vpbe_set_mode(struct vpbe_device *vpbe_dev,
 {
        struct vpbe_enc_mode_info *preset_mode = NULL;
        struct vpbe_config *cfg = vpbe_dev->cfg;
-       struct v4l2_dv_preset dv_preset;
+       struct v4l2_dv_timings dv_timings;
        struct osd_state *osd_device;
        int out_index = vpbe_dev->current_out_index;
        int ret = 0;
@@ -530,11 +513,12 @@ static int vpbe_set_mode(struct vpbe_device *vpbe_dev,
                         */
                        if (preset_mode->timings_type & VPBE_ENC_STD)
                                return vpbe_s_std(vpbe_dev,
-                                                &preset_mode->timings.std_id);
-                       if (preset_mode->timings_type & VPBE_ENC_DV_PRESET) {
-                               dv_preset.preset =
-                                       preset_mode->timings.dv_preset;
-                               return vpbe_s_dv_preset(vpbe_dev, &dv_preset);
+                                                &preset_mode->std_id);
+                       if (preset_mode->timings_type &
+                                               VPBE_ENC_CUSTOM_TIMINGS) {
+                               dv_timings =
+                                       preset_mode->dv_timings;
+                               return vpbe_s_dv_timings(vpbe_dev, &dv_timings);
                        }
                }
        }
@@ -626,11 +610,11 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
                vpbe_dev->dac_clk = clk_get(vpbe_dev->pdev, "vpss_dac");
                if (IS_ERR(vpbe_dev->dac_clk)) {
                        ret =  PTR_ERR(vpbe_dev->dac_clk);
-                       goto vpbe_unlock;
+                       goto fail_mutex_unlock;
                }
                if (clk_enable(vpbe_dev->dac_clk)) {
                        ret =  -ENODEV;
-                       goto vpbe_unlock;
+                       goto fail_mutex_unlock;
                }
        }
 
@@ -642,7 +626,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
        if (ret) {
                v4l2_err(dev->driver,
                        "Unable to register v4l2 device.\n");
-               goto vpbe_fail_clock;
+               goto fail_clk_put;
        }
        v4l2_info(&vpbe_dev->v4l2_dev, "vpbe v4l2 device registered\n");
 
@@ -658,7 +642,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
                v4l2_err(&vpbe_dev->v4l2_dev,
                        "vpbe unable to init venc sub device\n");
                ret = -ENODEV;
-               goto vpbe_fail_v4l2_device;
+               goto fail_dev_unregister;
        }
        /* initialize osd device */
        osd_device = vpbe_dev->osd_device;
@@ -669,7 +653,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
                        v4l2_err(&vpbe_dev->v4l2_dev,
                                 "unable to initialize the OSD device");
                        err = -ENOMEM;
-                       goto vpbe_fail_v4l2_device;
+                       goto fail_dev_unregister;
                }
        }
 
@@ -685,7 +669,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
                v4l2_err(&vpbe_dev->v4l2_dev,
                        "unable to allocate memory for encoders sub devices");
                ret = -ENOMEM;
-               goto vpbe_fail_v4l2_device;
+               goto fail_dev_unregister;
        }
 
        i2c_adap = i2c_get_adapter(vpbe_dev->cfg->i2c_adapter_id);
@@ -711,7 +695,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
                                         " failed to register",
                                         enc_info->module_name);
                                ret = -ENODEV;
-                               goto vpbe_fail_sd_register;
+                               goto fail_kfree_encoders;
                        }
                } else
                        v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders"
@@ -730,7 +714,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
                                         "amplifier %s failed to register",
                                         amp_info->module_name);
                                ret = -ENODEV;
-                               goto vpbe_fail_amp_register;
+                               goto fail_kfree_encoders;
                        }
                        v4l2_info(&vpbe_dev->v4l2_dev,
                                          "v4l2 sub device %s registered\n",
@@ -770,16 +754,14 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
        /* TBD handling of bootargs for default output and mode */
        return 0;
 
-vpbe_fail_amp_register:
-       kfree(vpbe_dev->amp);
-vpbe_fail_sd_register:
+fail_kfree_encoders:
        kfree(vpbe_dev->encoders);
-vpbe_fail_v4l2_device:
+fail_dev_unregister:
        v4l2_device_unregister(&vpbe_dev->v4l2_dev);
-vpbe_fail_clock:
+fail_clk_put:
        if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0)
                clk_put(vpbe_dev->dac_clk);
-vpbe_unlock:
+fail_mutex_unlock:
        mutex_unlock(&vpbe_dev->lock);
        return ret;
 }
@@ -810,9 +792,9 @@ static struct vpbe_device_ops vpbe_dev_ops = {
        .enum_outputs = vpbe_enum_outputs,
        .set_output = vpbe_set_output,
        .get_output = vpbe_get_output,
-       .s_dv_preset = vpbe_s_dv_preset,
-       .g_dv_preset = vpbe_g_dv_preset,
-       .enum_dv_presets = vpbe_enum_dv_presets,
+       .s_dv_timings = vpbe_s_dv_timings,
+       .g_dv_timings = vpbe_g_dv_timings,
+       .enum_dv_timings = vpbe_enum_dv_timings,
        .s_std = vpbe_s_std,
        .g_std = vpbe_g_std,
        .initialize = vpbe_initialize,
index 239f37bfa313b40903d8ac4d54192747165cd87d..161c77650e2f88ea13fedd063c43ef306a734d67 100644 (file)
@@ -393,7 +393,7 @@ vpbe_disp_calculate_scale_factor(struct vpbe_display *disp_dev,
        int h_scale;
        int v_scale;
 
-       v4l2_std_id standard_id = vpbe_dev->current_timings.timings.std_id;
+       v4l2_std_id standard_id = vpbe_dev->current_timings.std_id;
 
        /*
         * Application initially set the image format. Current display
@@ -637,7 +637,7 @@ static int vpbe_display_s_crop(struct file *file, void *priv,
        struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
        struct osd_layer_config *cfg = &layer->layer_info.config;
        struct osd_state *osd_device = disp_dev->osd_device;
-       struct v4l2_rect *rect = &crop->c;
+       struct v4l2_rect rect = crop->c;
        int ret;
 
        v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
@@ -648,21 +648,21 @@ static int vpbe_display_s_crop(struct file *file, void *priv,
                return -EINVAL;
        }
 
-       if (rect->top < 0)
-               rect->top = 0;
-       if (rect->left < 0)
-               rect->left = 0;
+       if (rect.top < 0)
+               rect.top = 0;
+       if (rect.left < 0)
+               rect.left = 0;
 
-       vpbe_disp_check_window_params(disp_dev, rect);
+       vpbe_disp_check_window_params(disp_dev, &rect);
 
        osd_device->ops.get_layer_config(osd_device,
                        layer->layer_info.id, cfg);
 
        vpbe_disp_calculate_scale_factor(disp_dev, layer,
-                                       rect->width,
-                                       rect->height);
-       vpbe_disp_adj_position(disp_dev, layer, rect->top,
-                                       rect->left);
+                                       rect.width,
+                                       rect.height);
+       vpbe_disp_adj_position(disp_dev, layer, rect.top,
+                                       rect.left);
        ret = osd_device->ops.set_layer_config(osd_device,
                                layer->layer_info.id, cfg);
        if (ret < 0) {
@@ -943,7 +943,7 @@ static int vpbe_display_g_std(struct file *file, void *priv,
 
        /* Get the standard from the current encoder */
        if (vpbe_dev->current_timings.timings_type & VPBE_ENC_STD) {
-               *std_id = vpbe_dev->current_timings.timings.std_id;
+               *std_id = vpbe_dev->current_timings.std_id;
                return 0;
        }
 
@@ -1029,29 +1029,29 @@ static int vpbe_display_g_output(struct file *file, void *priv,
 }
 
 /**
- * vpbe_display_enum_dv_presets - Enumerate the dv presets
+ * vpbe_display_enum_dv_timings - Enumerate the dv timings
  *
- * enum the preset in the current encoder. Return the status. 0 - success
+ * enum the timings in the current encoder. Return the status. 0 - success
  * -EINVAL on error
  */
 static int
-vpbe_display_enum_dv_presets(struct file *file, void *priv,
-                       struct v4l2_dv_enum_preset *preset)
+vpbe_display_enum_dv_timings(struct file *file, void *priv,
+                       struct v4l2_enum_dv_timings *timings)
 {
        struct vpbe_fh *fh = priv;
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
        int ret;
 
-       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_PRESETS\n");
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_TIMINGS\n");
 
        /* Enumerate outputs */
-       if (NULL == vpbe_dev->ops.enum_dv_presets)
+       if (NULL == vpbe_dev->ops.enum_dv_timings)
                return -EINVAL;
 
-       ret = vpbe_dev->ops.enum_dv_presets(vpbe_dev, preset);
+       ret = vpbe_dev->ops.enum_dv_timings(vpbe_dev, timings);
        if (ret) {
                v4l2_err(&vpbe_dev->v4l2_dev,
-                       "Failed to enumerate dv presets info\n");
+                       "Failed to enumerate dv timings info\n");
                return -EINVAL;
        }
 
@@ -1059,21 +1059,21 @@ vpbe_display_enum_dv_presets(struct file *file, void *priv,
 }
 
 /**
- * vpbe_display_s_dv_preset - Set the dv presets
+ * vpbe_display_s_dv_timings - Set the dv timings
  *
- * Set the preset in the current encoder. Return the status. 0 - success
+ * Set the timings in the current encoder. Return the status. 0 - success
  * -EINVAL on error
  */
 static int
-vpbe_display_s_dv_preset(struct file *file, void *priv,
-                               struct v4l2_dv_preset *preset)
+vpbe_display_s_dv_timings(struct file *file, void *priv,
+                               struct v4l2_dv_timings *timings)
 {
        struct vpbe_fh *fh = priv;
        struct vpbe_layer *layer = fh->layer;
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
        int ret;
 
-       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_PRESETS\n");
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_TIMINGS\n");
 
 
        /* If streaming is started, return error */
@@ -1083,13 +1083,13 @@ vpbe_display_s_dv_preset(struct file *file, void *priv,
        }
 
        /* Set the given standard in the encoder */
-       if (!vpbe_dev->ops.s_dv_preset)
+       if (!vpbe_dev->ops.s_dv_timings)
                return -EINVAL;
 
-       ret = vpbe_dev->ops.s_dv_preset(vpbe_dev, preset);
+       ret = vpbe_dev->ops.s_dv_timings(vpbe_dev, timings);
        if (ret) {
                v4l2_err(&vpbe_dev->v4l2_dev,
-                       "Failed to set the dv presets info\n");
+                       "Failed to set the dv timings info\n");
                return -EINVAL;
        }
        /* set the current norm to zero to be consistent. If STD is used
@@ -1101,26 +1101,25 @@ vpbe_display_s_dv_preset(struct file *file, void *priv,
 }
 
 /**
- * vpbe_display_g_dv_preset - Set the dv presets
+ * vpbe_display_g_dv_timings - Set the dv timings
  *
- * Get the preset in the current encoder. Return the status. 0 - success
+ * Get the timings in the current encoder. Return the status. 0 - success
  * -EINVAL on error
  */
 static int
-vpbe_display_g_dv_preset(struct file *file, void *priv,
-                               struct v4l2_dv_preset *dv_preset)
+vpbe_display_g_dv_timings(struct file *file, void *priv,
+                               struct v4l2_dv_timings *dv_timings)
 {
        struct vpbe_fh *fh = priv;
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 
-       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_PRESETS\n");
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_TIMINGS\n");
 
        /* Get the given standard in the encoder */
 
        if (vpbe_dev->current_timings.timings_type &
-                               VPBE_ENC_DV_PRESET) {
-               dv_preset->preset =
-                       vpbe_dev->current_timings.timings.dv_preset;
+                               VPBE_ENC_CUSTOM_TIMINGS) {
+               *dv_timings = vpbe_dev->current_timings.dv_timings;
        } else {
                return -EINVAL;
        }
@@ -1572,9 +1571,9 @@ static const struct v4l2_ioctl_ops vpbe_ioctl_ops = {
        .vidioc_enum_output      = vpbe_display_enum_output,
        .vidioc_s_output         = vpbe_display_s_output,
        .vidioc_g_output         = vpbe_display_g_output,
-       .vidioc_s_dv_preset      = vpbe_display_s_dv_preset,
-       .vidioc_g_dv_preset      = vpbe_display_g_dv_preset,
-       .vidioc_enum_dv_presets  = vpbe_display_enum_dv_presets,
+       .vidioc_s_dv_timings     = vpbe_display_s_dv_timings,
+       .vidioc_g_dv_timings     = vpbe_display_g_dv_timings,
+       .vidioc_enum_dv_timings  = vpbe_display_enum_dv_timings,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .vidioc_g_register       = vpbe_display_g_register,
        .vidioc_s_register       = vpbe_display_s_register,
@@ -1639,8 +1638,7 @@ static __devinit int init_vpbe_layer(int i, struct vpbe_display *disp_dev,
                        VPBE_ENC_STD) {
                vbd->tvnorms = (V4L2_STD_525_60 | V4L2_STD_625_50);
                vbd->current_norm =
-                       disp_dev->vpbe_dev->
-                       current_timings.timings.std_id;
+                       disp_dev->vpbe_dev->current_timings.std_id;
        } else
                vbd->current_norm = 0;
 
index 0302669622d6d6e2b409be2221d4d34f4d25a5e8..aed7369b962a7da5a5c7e6c826ce06944d12136c 100644 (file)
@@ -298,7 +298,7 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd)
                return -EINVAL;
 
        /* Setup clock at VPSS & VENC for SD */
-       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_480P59_94) < 0)
+       if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0)
                return -EINVAL;
 
        venc_enabledigitaloutput(sd, 0);
@@ -345,7 +345,7 @@ static int venc_set_576p50(struct v4l2_subdev *sd)
          (pdata->venc_type != VPBE_VERSION_2))
                return -EINVAL;
        /* Setup clock at VPSS & VENC for SD */
-       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_576P50) < 0)
+       if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0)
                return -EINVAL;
 
        venc_enabledigitaloutput(sd, 0);
@@ -385,7 +385,7 @@ static int venc_set_720p60_internal(struct v4l2_subdev *sd)
        struct venc_state *venc = to_state(sd);
        struct venc_platform_data *pdata = venc->pdata;
 
-       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_720P60) < 0)
+       if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 74250000) < 0)
                return -EINVAL;
 
        venc_enabledigitaloutput(sd, 0);
@@ -413,7 +413,7 @@ static int venc_set_1080i30_internal(struct v4l2_subdev *sd)
        struct venc_state *venc = to_state(sd);
        struct venc_platform_data *pdata = venc->pdata;
 
-       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_1080P30) < 0)
+       if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 74250000) < 0)
                return -EINVAL;
 
        venc_enabledigitaloutput(sd, 0);
@@ -446,26 +446,27 @@ static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
        return -EINVAL;
 }
 
-static int venc_s_dv_preset(struct v4l2_subdev *sd,
-                           struct v4l2_dv_preset *dv_preset)
+static int venc_s_dv_timings(struct v4l2_subdev *sd,
+                           struct v4l2_dv_timings *dv_timings)
 {
        struct venc_state *venc = to_state(sd);
+       u32 height = dv_timings->bt.height;
        int ret;
 
-       v4l2_dbg(debug, 1, sd, "venc_s_dv_preset\n");
+       v4l2_dbg(debug, 1, sd, "venc_s_dv_timings\n");
 
-       if (dv_preset->preset == V4L2_DV_576P50)
+       if (height == 576)
                return venc_set_576p50(sd);
-       else if (dv_preset->preset == V4L2_DV_480P59_94)
+       else if (height == 480)
                return venc_set_480p59_94(sd);
-       else if ((dv_preset->preset == V4L2_DV_720P60) &&
+       else if ((height == 720) &&
                        (venc->pdata->venc_type == VPBE_VERSION_2)) {
                /* TBD setup internal 720p mode here */
                ret = venc_set_720p60_internal(sd);
                /* for DM365 VPBE, there is DAC inside */
                vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
                return ret;
-       } else if ((dv_preset->preset == V4L2_DV_1080I30) &&
+       } else if ((height == 1080) &&
                (venc->pdata->venc_type == VPBE_VERSION_2)) {
                /* TBD setup internal 1080i mode here */
                ret = venc_set_1080i30_internal(sd);
@@ -518,7 +519,7 @@ static const struct v4l2_subdev_core_ops venc_core_ops = {
 static const struct v4l2_subdev_video_ops venc_video_ops = {
        .s_routing = venc_s_routing,
        .s_std_output = venc_s_std_output,
-       .s_dv_preset = venc_s_dv_preset,
+       .s_dv_timings = venc_s_dv_timings,
 };
 
 static const struct v4l2_subdev_ops venc_ops = {
index 48052cbffc2ba36d123faba417116a980706f894..8be492cd8ed46bf58a9cd79ce4d26ed8474404aa 100644 (file)
@@ -1669,6 +1669,7 @@ static int vpfe_s_crop(struct file *file, void *priv,
                             const struct v4l2_crop *crop)
 {
        struct vpfe_device *vpfe_dev = video_drvdata(file);
+       struct v4l2_rect rect = crop->c;
        int ret = 0;
 
        v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_crop\n");
@@ -1684,7 +1685,7 @@ static int vpfe_s_crop(struct file *file, void *priv,
        if (ret)
                return ret;
 
-       if (crop->c.top < 0 || crop->c.left < 0) {
+       if (rect.top < 0 || rect.left < 0) {
                v4l2_err(&vpfe_dev->v4l2_dev,
                        "doesn't support negative values for top & left\n");
                ret = -EINVAL;
@@ -1692,26 +1693,26 @@ static int vpfe_s_crop(struct file *file, void *priv,
        }
 
        /* adjust the width to 16 pixel boundary */
-       crop->c.width = ((crop->c.width + 15) & ~0xf);
+       rect.width = ((rect.width + 15) & ~0xf);
 
        /* make sure parameters are valid */
-       if ((crop->c.left + crop->c.width >
+       if ((rect.left + rect.width >
                vpfe_dev->std_info.active_pixels) ||
-           (crop->c.top + crop->c.height >
+           (rect.top + rect.height >
                vpfe_dev->std_info.active_lines)) {
                v4l2_err(&vpfe_dev->v4l2_dev, "Error in S_CROP params\n");
                ret = -EINVAL;
                goto unlock_out;
        }
-       ccdc_dev->hw_ops.set_image_window(&crop->c);
-       vpfe_dev->fmt.fmt.pix.width = crop->c.width;
-       vpfe_dev->fmt.fmt.pix.height = crop->c.height;
+       ccdc_dev->hw_ops.set_image_window(&rect);
+       vpfe_dev->fmt.fmt.pix.width = rect.width;
+       vpfe_dev->fmt.fmt.pix.height = rect.height;
        vpfe_dev->fmt.fmt.pix.bytesperline =
                ccdc_dev->hw_ops.get_line_length();
        vpfe_dev->fmt.fmt.pix.sizeimage =
                vpfe_dev->fmt.fmt.pix.bytesperline *
                vpfe_dev->fmt.fmt.pix.height;
-       vpfe_dev->crop = crop->c;
+       vpfe_dev->crop = rect;
 unlock_out:
        mutex_unlock(&vpfe_dev->lock);
        return ret;
index 0bafecac4923bce09cef1850ebb3660a62401609..fcabc023885d06c66b33db117d5c744f138a2e45 100644 (file)
@@ -311,12 +311,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
        }
 
        /* configure 1 or 2 channel mode */
-       ret = vpif_config_data->setup_input_channel_mode
-                                       (vpif->std_info.ycmux_mode);
-
-       if (ret < 0) {
-               vpif_dbg(1, debug, "can't set vpif channel mode\n");
-               return ret;
+       if (vpif_config_data->setup_input_channel_mode) {
+               ret = vpif_config_data->
+                       setup_input_channel_mode(vpif->std_info.ycmux_mode);
+               if (ret < 0) {
+                       vpif_dbg(1, debug, "can't set vpif channel mode\n");
+                       return ret;
+               }
        }
 
        /* Call vpif_set_params function to set the parameters and addresses */
@@ -863,13 +864,11 @@ static unsigned int vpif_poll(struct file *filep, poll_table * wait)
  */
 static int vpif_open(struct file *filep)
 {
-       struct vpif_capture_config *config = vpif_dev->platform_data;
        struct video_device *vdev = video_devdata(filep);
        struct common_obj *common;
        struct video_obj *vid_ch;
        struct channel_obj *ch;
        struct vpif_fh *fh;
-       int i;
 
        vpif_dbg(2, debug, "vpif_open\n");
 
@@ -878,26 +877,6 @@ static int vpif_open(struct file *filep)
        vid_ch = &ch->video;
        common = &ch->common[VPIF_VIDEO_INDEX];
 
-       if (NULL == ch->curr_subdev_info) {
-               /**
-                * search through the sub device to see a registered
-                * sub device and make it as current sub device
-                */
-               for (i = 0; i < config->subdev_count; i++) {
-                       if (vpif_obj.sd[i]) {
-                               /* the sub device is registered */
-                               ch->curr_subdev_info = &config->subdev_info[i];
-                               /* make first input as the current input */
-                               vid_ch->input_idx = 0;
-                               break;
-                       }
-               }
-               if (i == config->subdev_count) {
-                       vpif_err("No sub device registered\n");
-                       return -ENOENT;
-               }
-       }
-
        /* Allocate memory for the file handle object */
        fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL);
        if (NULL == fh) {
@@ -997,6 +976,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
        struct common_obj *common;
        u8 index = 0;
        struct vb2_queue *q;
+       int ret;
 
        vpif_dbg(2, debug, "vpif_reqbufs\n");
 
@@ -1036,8 +1016,12 @@ static int vpif_reqbufs(struct file *file, void *priv,
        q->mem_ops = &vb2_dma_contig_memops;
        q->buf_struct_size = sizeof(struct vpif_cap_buffer);
 
-       vb2_queue_init(q);
-
+       ret = vb2_queue_init(q);
+       if (ret) {
+               vpif_err("vpif_capture: vb2_queue_init() failed\n");
+               vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
+               return ret;
+       }
        /* Set io allowed member of file handle to TRUE */
        fh->io_allowed[index] = 1;
        /* Increment io usrs member of channel object to 1 */
@@ -1175,10 +1159,9 @@ static int vpif_streamon(struct file *file, void *priv,
                return ret;
 
        /* Enable streamon on the sub device */
-       ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
-                               s_stream, 1);
+       ret = v4l2_subdev_call(ch->sd, video, s_stream, 1);
 
-       if (ret && (ret != -ENOIOCTLCMD)) {
+       if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
                vpif_dbg(1, debug, "stream on failed in subdev\n");
                return ret;
        }
@@ -1238,73 +1221,105 @@ static int vpif_streamoff(struct file *file, void *priv,
 
        common->started = 0;
 
-       ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
-                               s_stream, 0);
+       ret = v4l2_subdev_call(ch->sd, video, s_stream, 0);
 
-       if (ret && (ret != -ENOIOCTLCMD))
+       if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
                vpif_dbg(1, debug, "stream off failed in subdev\n");
 
        return vb2_streamoff(&common->buffer_queue, buftype);
 }
 
 /**
- * vpif_map_sub_device_to_input() - Maps sub device to input
- * @ch - ptr to channel
- * @config - ptr to capture configuration
+ * vpif_input_to_subdev() - Maps input to sub device
+ * @vpif_cfg - global config ptr
+ * @chan_cfg - channel config ptr
  * @input_index - Given input index from application
- * @sub_device_index - index into sd table
  *
  * lookup the sub device information for a given input index.
  * we report all the inputs to application. inputs table also
  * has sub device name for the each input
  */
-static struct vpif_subdev_info *vpif_map_sub_device_to_input(
-                               struct channel_obj *ch,
-                               struct vpif_capture_config *vpif_cfg,
-                               int input_index,
-                               int *sub_device_index)
+static int vpif_input_to_subdev(
+               struct vpif_capture_config *vpif_cfg,
+               struct vpif_capture_chan_config *chan_cfg,
+               int input_index)
 {
-       struct vpif_capture_chan_config *chan_cfg;
-       struct vpif_subdev_info *subdev_info = NULL;
-       const char *subdev_name = NULL;
+       struct vpif_subdev_info *subdev_info;
+       const char *subdev_name;
        int i;
 
-       vpif_dbg(2, debug, "vpif_map_sub_device_to_input\n");
+       vpif_dbg(2, debug, "vpif_input_to_subdev\n");
 
-       chan_cfg = &vpif_cfg->chan_config[ch->channel_id];
-
-       /**
-        * search through the inputs to find the sub device supporting
-        * the input
-        */
-       for (i = 0; i < chan_cfg->input_count; i++) {
-               /* For each sub device, loop through input */
-               if (i == input_index) {
-                       subdev_name = chan_cfg->inputs[i].subdev_name;
-                       break;
-               }
-       }
-
-       /* if reached maximum. return null */
-       if (i == chan_cfg->input_count || (NULL == subdev_name))
-               return subdev_info;
+       subdev_name = chan_cfg->inputs[input_index].subdev_name;
+       if (subdev_name == NULL)
+               return -1;
 
        /* loop through the sub device list to get the sub device info */
        for (i = 0; i < vpif_cfg->subdev_count; i++) {
                subdev_info = &vpif_cfg->subdev_info[i];
                if (!strcmp(subdev_info->name, subdev_name))
-                       break;
+                       return i;
+       }
+       return -1;
+}
+
+/**
+ * vpif_set_input() - Select an input
+ * @vpif_cfg - global config ptr
+ * @ch - channel
+ * @_index - Given input index from application
+ *
+ * Select the given input.
+ */
+static int vpif_set_input(
+               struct vpif_capture_config *vpif_cfg,
+               struct channel_obj *ch,
+               int index)
+{
+       struct vpif_capture_chan_config *chan_cfg =
+                       &vpif_cfg->chan_config[ch->channel_id];
+       struct vpif_subdev_info *subdev_info = NULL;
+       struct v4l2_subdev *sd = NULL;
+       u32 input = 0, output = 0;
+       int sd_index;
+       int ret;
+
+       sd_index = vpif_input_to_subdev(vpif_cfg, chan_cfg, index);
+       if (sd_index >= 0) {
+               sd = vpif_obj.sd[sd_index];
+               subdev_info = &vpif_cfg->subdev_info[sd_index];
        }
 
-       if (i == vpif_cfg->subdev_count)
-               return subdev_info;
+       /* first setup input path from sub device to vpif */
+       if (sd && vpif_cfg->setup_input_path) {
+               ret = vpif_cfg->setup_input_path(ch->channel_id,
+                                      subdev_info->name);
+               if (ret < 0) {
+                       vpif_dbg(1, debug, "couldn't setup input path for the" \
+                       " sub device %s, for input index %d\n",
+                       subdev_info->name, index);
+                       return ret;
+               }
+       }
 
-       /* check if the sub device is registered */
-       if (NULL == vpif_obj.sd[i])
-               return NULL;
+       if (sd) {
+               input = chan_cfg->inputs[index].input_route;
+               output = chan_cfg->inputs[index].output_route;
+               ret = v4l2_subdev_call(sd, video, s_routing,
+                               input, output, 0);
+               if (ret < 0 && ret != -ENOIOCTLCMD) {
+                       vpif_dbg(1, debug, "Failed to set input\n");
+                       return ret;
+               }
+       }
+       ch->input_idx = index;
+       ch->sd = sd;
+       /* copy interface parameters to vpif */
+       ch->vpifparams.iface = chan_cfg->vpif_if;
 
-       *sub_device_index = i;
-       return subdev_info;
+       /* update tvnorms from the sub device input info */
+       ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std;
+       return 0;
 }
 
 /**
@@ -1324,12 +1339,16 @@ static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
        vpif_dbg(2, debug, "vpif_querystd\n");
 
        /* Call querystd function of decoder device */
-       ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
-                               querystd, std_id);
-       if (ret < 0)
-               vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
+       ret = v4l2_subdev_call(ch->sd, video, querystd, std_id);
 
-       return ret;
+       if (ret == -ENOIOCTLCMD || ret == -ENODEV)
+               return -ENODATA;
+       if (ret) {
+               vpif_dbg(1, debug, "Failed to query standard for sub devices\n");
+               return ret;
+       }
+
+       return 0;
 }
 
 /**
@@ -1397,11 +1416,12 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
        vpif_config_format(ch);
 
        /* set standard in the sub device */
-       ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
-                               s_std, *std_id);
-       if (ret < 0)
+       ret = v4l2_subdev_call(ch->sd, core, s_std, *std_id);
+       if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
                vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
-       return ret;
+               return ret;
+       }
+       return 0;
 }
 
 /**
@@ -1441,10 +1461,8 @@ static int vpif_g_input(struct file *file, void *priv, unsigned int *index)
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
-
-       *index = vid_ch->input_idx;
 
+       *index = ch->input_idx;
        return 0;
 }
 
@@ -1461,13 +1479,13 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index)
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
        struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
-       struct video_obj *vid_ch = &ch->video;
-       struct vpif_subdev_info *subdev_info;
-       int ret = 0, sd_index = 0;
-       u32 input = 0, output = 0;
+       int ret;
 
        chan_cfg = &config->chan_config[ch->channel_id];
 
+       if (index >= chan_cfg->input_count)
+               return -EINVAL;
+
        if (common->started) {
                vpif_err("Streaming in progress\n");
                return -EBUSY;
@@ -1486,45 +1504,7 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index)
                return ret;
 
        fh->initialized = 1;
-       subdev_info = vpif_map_sub_device_to_input(ch, config, index,
-                                                  &sd_index);
-       if (NULL == subdev_info) {
-               vpif_dbg(1, debug,
-                       "couldn't lookup sub device for the input index\n");
-               return -EINVAL;
-       }
-
-       /* first setup input path from sub device to vpif */
-       if (config->setup_input_path) {
-               ret = config->setup_input_path(ch->channel_id,
-                                              subdev_info->name);
-               if (ret < 0) {
-                       vpif_dbg(1, debug, "couldn't setup input path for the"
-                               " sub device %s, for input index %d\n",
-                               subdev_info->name, index);
-                       return ret;
-               }
-       }
-
-       if (subdev_info->can_route) {
-               input = subdev_info->input;
-               output = subdev_info->output;
-               ret = v4l2_subdev_call(vpif_obj.sd[sd_index], video, s_routing,
-                                       input, output, 0);
-               if (ret < 0) {
-                       vpif_dbg(1, debug, "Failed to set input\n");
-                       return ret;
-               }
-       }
-       vid_ch->input_idx = index;
-       ch->curr_subdev_info = subdev_info;
-       ch->curr_sd_index = sd_index;
-       /* copy interface parameters to vpif */
-       ch->vpifparams.iface = subdev_info->vpif_if;
-
-       /* update tvnorms from the sub device input info */
-       ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std;
-       return ret;
+       return vpif_set_input(config, ch, index);
 }
 
 /**
@@ -1655,9 +1635,11 @@ static int vpif_querycap(struct file *file, void  *priv,
 {
        struct vpif_capture_config *config = vpif_dev->platform_data;
 
-       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
-       strlcpy(cap->driver, "vpif capture", sizeof(cap->driver));
-       strlcpy(cap->bus_info, "VPIF Platform", sizeof(cap->bus_info));
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev));
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+                dev_name(vpif_dev));
        strlcpy(cap->card, config->card_name, sizeof(cap->card));
 
        return 0;
@@ -1730,9 +1712,12 @@ vpif_enum_dv_timings(struct file *file, void *priv,
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
+       int ret;
 
-       return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
-                               video, enum_dv_timings, timings);
+       ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+               return -EINVAL;
+       return ret;
 }
 
 /**
@@ -1747,9 +1732,12 @@ vpif_query_dv_timings(struct file *file, void *priv,
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
+       int ret;
 
-       return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
-                               video, query_dv_timings, timings);
+       ret = v4l2_subdev_call(ch->sd, video, query_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+               return -ENODATA;
+       return ret;
 }
 
 /**
@@ -1775,13 +1763,9 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
        }
 
        /* Configure subdevice timings, if any */
-       ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
-                       video, s_dv_timings, timings);
-       if (ret == -ENOIOCTLCMD) {
-               vpif_dbg(2, debug, "Custom DV timings not supported by "
-                               "subdevice\n");
-               return -EINVAL;
-       }
+       ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD || ret == -ENODEV)
+               ret = 0;
        if (ret < 0) {
                vpif_dbg(2, debug, "Error setting custom DV timings\n");
                return ret;
@@ -1906,8 +1890,7 @@ static int vpif_dbg_g_register(struct file *file, void *priv,
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
 
-       return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
-                       g_register, reg);
+       return v4l2_subdev_call(ch->sd, core, g_register, reg);
 }
 
 /*
@@ -1924,8 +1907,7 @@ static int vpif_dbg_s_register(struct file *file, void *priv,
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
 
-       return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
-                       s_register, reg);
+       return v4l2_subdev_call(ch->sd, core, s_register, reg);
 }
 #endif
 
@@ -2063,7 +2045,8 @@ static __init int vpif_probe(struct platform_device *pdev)
 {
        struct vpif_subdev_info *subdevdata;
        struct vpif_capture_config *config;
-       int i, j, k, m, q, err;
+       int i, j, k, err;
+       int res_idx = 0;
        struct i2c_adapter *i2c_adap;
        struct channel_obj *ch;
        struct common_obj *common;
@@ -2086,18 +2069,19 @@ static __init int vpif_probe(struct platform_device *pdev)
                return err;
        }
 
-       k = 0;
-       while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) {
+       while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) {
                for (i = res->start; i <= res->end; i++) {
                        if (request_irq(i, vpif_channel_isr, IRQF_SHARED,
-                                       "VPIF_Capture",
-                               (void *)(&vpif_obj.dev[k]->channel_id))) {
+                                       "VPIF_Capture", (void *)
+                                       (&vpif_obj.dev[res_idx]->channel_id))) {
                                err = -EBUSY;
-                               i--;
+                               for (j = 0; j < i; j++)
+                                       free_irq(j, (void *)
+                                       (&vpif_obj.dev[res_idx]->channel_id));
                                goto vpif_int_err;
                        }
                }
-               k++;
+               res_idx++;
        }
 
        for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
@@ -2111,7 +2095,7 @@ static __init int vpif_probe(struct platform_device *pdev)
                                video_device_release(ch->video_dev);
                        }
                        err = -ENOMEM;
-                       goto vpif_dev_alloc_err;
+                       goto vpif_int_err;
                }
 
                /* Initialize field of video device */
@@ -2142,24 +2126,6 @@ static __init int vpif_probe(struct platform_device *pdev)
                }
        }
 
-       for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
-               ch = vpif_obj.dev[j];
-               ch->channel_id = j;
-               common = &(ch->common[VPIF_VIDEO_INDEX]);
-               spin_lock_init(&common->irqlock);
-               mutex_init(&common->lock);
-               ch->video_dev->lock = &common->lock;
-               /* Initialize prio member of channel object */
-               v4l2_prio_init(&ch->prio);
-               err = video_register_device(ch->video_dev,
-                                           VFL_TYPE_GRABBER, (j ? 1 : 0));
-               if (err)
-                       goto probe_out;
-
-               video_set_drvdata(ch->video_dev, ch);
-
-       }
-
        i2c_adap = i2c_get_adapter(1);
        config = pdev->dev.platform_data;
 
@@ -2169,7 +2135,7 @@ static __init int vpif_probe(struct platform_device *pdev)
        if (vpif_obj.sd == NULL) {
                vpif_err("unable to allocate memory for subdevice pointers\n");
                err = -ENOMEM;
-               goto probe_out;
+               goto vpif_sd_error;
        }
 
        for (i = 0; i < subdev_count; i++) {
@@ -2186,19 +2152,32 @@ static __init int vpif_probe(struct platform_device *pdev)
                }
                v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n",
                          subdevdata->name);
-
-               if (vpif_obj.sd[i])
-                       vpif_obj.sd[i]->grp_id = 1 << i;
        }
 
+       for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
+               ch = vpif_obj.dev[j];
+               ch->channel_id = j;
+               common = &(ch->common[VPIF_VIDEO_INDEX]);
+               spin_lock_init(&common->irqlock);
+               mutex_init(&common->lock);
+               ch->video_dev->lock = &common->lock;
+               /* Initialize prio member of channel object */
+               v4l2_prio_init(&ch->prio);
+               video_set_drvdata(ch->video_dev, ch);
+
+               /* select input 0 */
+               err = vpif_set_input(config, ch, 0);
+               if (err)
+                       goto probe_out;
+
+               err = video_register_device(ch->video_dev,
+                                           VFL_TYPE_GRABBER, (j ? 1 : 0));
+               if (err)
+                       goto probe_out;
+       }
        v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n");
        return 0;
 
-probe_subdev_out:
-       /* free sub devices memory */
-       kfree(vpif_obj.sd);
-
-       j = VPIF_CAPTURE_MAX_DEVICES;
 probe_out:
        for (k = 0; k < j; k++) {
                /* Get the pointer to the channel object */
@@ -2206,22 +2185,23 @@ probe_out:
                /* Unregister video device */
                video_unregister_device(ch->video_dev);
        }
+probe_subdev_out:
+       /* free sub devices memory */
+       kfree(vpif_obj.sd);
 
-vpif_dev_alloc_err:
-       k = VPIF_CAPTURE_MAX_DEVICES-1;
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, k);
-       i = res->end;
-
-vpif_int_err:
-       for (q = k; q >= 0; q--) {
-               for (m = i; m >= (int)res->start; m--)
-                       free_irq(m, (void *)(&vpif_obj.dev[q]->channel_id));
-
-               res = platform_get_resource(pdev, IORESOURCE_IRQ, q-1);
-               if (res)
-                       i = res->end;
+vpif_sd_error:
+       for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
+               ch = vpif_obj.dev[i];
+               /* Note: does nothing if ch->video_dev == NULL */
+               video_device_release(ch->video_dev);
        }
+vpif_int_err:
        v4l2_device_unregister(&vpif_obj.v4l2_dev);
+       for (i = 0; i < res_idx; i++) {
+               res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+               for (j = res->start; j <= res->end; j++)
+                       free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id));
+       }
        return err;
 }
 
index d24efc17e4c876537933aeff8e7a95f6aded1e28..3d3c1e5cd5d4c63c1eb23b61be1574296ab27885 100644 (file)
@@ -54,8 +54,6 @@ struct video_obj {
        /* Currently selected or default standard */
        v4l2_std_id stdid;
        struct v4l2_dv_timings dv_timings;
-       /* This is to track the last input that is passed to application */
-       u32 input_idx;
 };
 
 struct vpif_cap_buffer {
@@ -119,10 +117,10 @@ struct channel_obj {
        u8 initialized;
        /* Identifies channel */
        enum vpif_channel_id channel_id;
-       /* index into sd table */
-       int curr_sd_index;
-       /* ptr to current sub device information */
-       struct vpif_subdev_info *curr_subdev_info;
+       /* Current input */
+       u32 input_idx;
+       /* subdev corresponding to the current input, may be NULL */
+       struct v4l2_subdev *sd;
        /* vpif configuration params */
        struct vpif_params vpifparams;
        /* common object array */
@@ -159,10 +157,6 @@ struct vpif_config_params {
        u32 video_limit[VPIF_CAPTURE_NUM_CHANNELS];
        u8 max_device_type;
 };
-/* Struct which keeps track of the line numbers for the sliced vbi service */
-struct vpif_service_line {
-       u16 service_id;
-       u16 service_line[2];
-};
+
 #endif                         /* End of __KERNEL__ */
 #endif                         /* VPIF_CAPTURE_H */
index a5b88689abad1d9055c45f6624190d68734dbf30..b716fbd4241f8599f90c8dbf7caf4b99e0f338bb 100644 (file)
@@ -280,12 +280,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
        }
 
        /* clock settings */
-       ret =
-           vpif_config_data->set_clock(ch->vpifparams.std_info.ycmux_mode,
-                                       ch->vpifparams.std_info.hd_sd);
-       if (ret < 0) {
-               vpif_err("can't set clock\n");
-               return ret;
+       if (vpif_config_data->set_clock) {
+               ret = vpif_config_data->set_clock(ch->vpifparams.std_info.
+               ycmux_mode, ch->vpifparams.std_info.hd_sd);
+               if (ret < 0) {
+                       vpif_err("can't set clock\n");
+                       return ret;
+               }
        }
 
        /* set the parameters and addresses */
@@ -307,7 +308,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
                channel2_intr_assert();
                channel2_intr_enable(1);
                enable_channel2(1);
-               if (vpif_config_data->ch2_clip_en)
+               if (vpif_config_data->chan_config[VPIF_CHANNEL2_VIDEO].clip_en)
                        channel2_clipping_enable(1);
        }
 
@@ -316,7 +317,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
                channel3_intr_assert();
                channel3_intr_enable(1);
                enable_channel3(1);
-               if (vpif_config_data->ch3_clip_en)
+               if (vpif_config_data->chan_config[VPIF_CHANNEL3_VIDEO].clip_en)
                        channel3_clipping_enable(1);
        }
 
@@ -826,9 +827,11 @@ static int vpif_querycap(struct file *file, void  *priv,
 {
        struct vpif_display_config *config = vpif_dev->platform_data;
 
-       cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
-       strlcpy(cap->driver, "vpif display", sizeof(cap->driver));
-       strlcpy(cap->bus_info, "Platform", sizeof(cap->bus_info));
+       cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev));
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+                dev_name(vpif_dev));
        strlcpy(cap->card, config->card_name, sizeof(cap->card));
 
        return 0;
@@ -935,6 +938,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
        enum v4l2_field field;
        struct vb2_queue *q;
        u8 index = 0;
+       int ret;
 
        /* This file handle has not initialized the channel,
           It is not allowed to do settings */
@@ -980,8 +984,12 @@ static int vpif_reqbufs(struct file *file, void *priv,
        q->mem_ops = &vb2_dma_contig_memops;
        q->buf_struct_size = sizeof(struct vpif_disp_buffer);
 
-       vb2_queue_init(q);
-
+       ret = vb2_queue_init(q);
+       if (ret) {
+               vpif_err("vpif_display: vb2_queue_init() failed\n");
+               vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
+               return ret;
+       }
        /* Set io allowed member of file handle to TRUE */
        fh->io_allowed[index] = 1;
        /* Increment io usrs member of channel object to 1 */
@@ -1173,14 +1181,16 @@ static int vpif_streamoff(struct file *file, void *priv,
        if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
                /* disable channel */
                if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
-                       if (vpif_config_data->ch2_clip_en)
+                       if (vpif_config_data->
+                               chan_config[VPIF_CHANNEL2_VIDEO].clip_en)
                                channel2_clipping_enable(0);
                        enable_channel2(0);
                        channel2_intr_enable(0);
                }
                if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) ||
                                        (2 == common->started)) {
-                       if (vpif_config_data->ch3_clip_en)
+                       if (vpif_config_data->
+                               chan_config[VPIF_CHANNEL3_VIDEO].clip_en)
                                channel3_clipping_enable(0);
                        enable_channel3(0);
                        channel3_intr_enable(0);
@@ -1213,49 +1223,126 @@ static int vpif_enum_output(struct file *file, void *fh,
 {
 
        struct vpif_display_config *config = vpif_dev->platform_data;
+       struct vpif_display_chan_config *chan_cfg;
+       struct vpif_fh *vpif_handler = fh;
+       struct channel_obj *ch = vpif_handler->channel;
 
-       if (output->index >= config->output_count) {
+       chan_cfg = &config->chan_config[ch->channel_id];
+       if (output->index >= chan_cfg->output_count) {
                vpif_dbg(1, debug, "Invalid output index\n");
                return -EINVAL;
        }
 
-       strcpy(output->name, config->output[output->index]);
-       output->type = V4L2_OUTPUT_TYPE_ANALOG;
-       output->std = VPIF_V4L2_STD;
+       *output = chan_cfg->outputs[output->index].output;
+       return 0;
+}
+
+/**
+ * vpif_output_to_subdev() - Maps output to sub device
+ * @vpif_cfg - global config ptr
+ * @chan_cfg - channel config ptr
+ * @index - Given output index from application
+ *
+ * lookup the sub device information for a given output index.
+ * we report all the output to application. output table also
+ * has sub device name for the each output
+ */
+static int
+vpif_output_to_subdev(struct vpif_display_config *vpif_cfg,
+                     struct vpif_display_chan_config *chan_cfg, int index)
+{
+       struct vpif_subdev_info *subdev_info;
+       const char *subdev_name;
+       int i;
+
+       vpif_dbg(2, debug, "vpif_output_to_subdev\n");
+
+       if (chan_cfg->outputs == NULL)
+               return -1;
+
+       subdev_name = chan_cfg->outputs[index].subdev_name;
+       if (subdev_name == NULL)
+               return -1;
+
+       /* loop through the sub device list to get the sub device info */
+       for (i = 0; i < vpif_cfg->subdev_count; i++) {
+               subdev_info = &vpif_cfg->subdevinfo[i];
+               if (!strcmp(subdev_info->name, subdev_name))
+                       return i;
+       }
+       return -1;
+}
+
+/**
+ * vpif_set_output() - Select an output
+ * @vpif_cfg - global config ptr
+ * @ch - channel
+ * @index - Given output index from application
+ *
+ * Select the given output.
+ */
+static int vpif_set_output(struct vpif_display_config *vpif_cfg,
+                     struct channel_obj *ch, int index)
+{
+       struct vpif_display_chan_config *chan_cfg =
+               &vpif_cfg->chan_config[ch->channel_id];
+       struct vpif_subdev_info *subdev_info = NULL;
+       struct v4l2_subdev *sd = NULL;
+       u32 input = 0, output = 0;
+       int sd_index;
+       int ret;
+
+       sd_index = vpif_output_to_subdev(vpif_cfg, chan_cfg, index);
+       if (sd_index >= 0) {
+               sd = vpif_obj.sd[sd_index];
+               subdev_info = &vpif_cfg->subdevinfo[sd_index];
+       }
+
+       if (sd) {
+               input = chan_cfg->outputs[index].input_route;
+               output = chan_cfg->outputs[index].output_route;
+               ret = v4l2_subdev_call(sd, video, s_routing, input, output, 0);
+               if (ret < 0 && ret != -ENOIOCTLCMD) {
+                       vpif_err("Failed to set output\n");
+                       return ret;
+               }
 
+       }
+       ch->output_idx = index;
+       ch->sd = sd;
+       if (chan_cfg->outputs != NULL)
+               /* update tvnorms from the sub device output info */
+               ch->video_dev->tvnorms = chan_cfg->outputs[index].output.std;
        return 0;
 }
 
 static int vpif_s_output(struct file *file, void *priv, unsigned int i)
 {
+       struct vpif_display_config *config = vpif_dev->platform_data;
+       struct vpif_display_chan_config *chan_cfg;
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
        struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
-       int ret = 0;
+
+       chan_cfg = &config->chan_config[ch->channel_id];
+
+       if (i >= chan_cfg->output_count)
+               return -EINVAL;
 
        if (common->started) {
                vpif_err("Streaming in progress\n");
                return -EBUSY;
        }
 
-       ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video,
-                                                       s_routing, 0, i, 0);
-
-       if (ret < 0)
-               vpif_err("Failed to set output standard\n");
-
-       vid_ch->output_id = i;
-       return ret;
+       return vpif_set_output(config, ch, i);
 }
 
 static int vpif_g_output(struct file *file, void *priv, unsigned int *i)
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
 
-       *i = vid_ch->output_id;
+       *i = ch->output_idx;
 
        return 0;
 }
@@ -1290,10 +1377,12 @@ vpif_enum_dv_timings(struct file *file, void *priv,
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
+       int ret;
 
-       return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
-                       video, enum_dv_timings, timings);
+       ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+               return -EINVAL;
+       return ret;
 }
 
 /**
@@ -1319,13 +1408,9 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
        }
 
        /* Configure subdevice timings, if any */
-       ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
-                       video, s_dv_timings, timings);
-       if (ret == -ENOIOCTLCMD) {
-               vpif_dbg(2, debug, "Custom DV timings not supported by "
-                               "subdevice\n");
-               return -EINVAL;
-       }
+       ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD || ret == -ENODEV)
+               ret = 0;
        if (ret < 0) {
                vpif_dbg(2, debug, "Error setting custom DV timings\n");
                return ret;
@@ -1450,10 +1535,8 @@ static int vpif_dbg_g_register(struct file *file, void *priv,
                struct v4l2_dbg_register *reg){
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
 
-       return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core,
-                       g_register, reg);
+       return v4l2_subdev_call(ch->sd, core, g_register, reg);
 }
 
 /*
@@ -1469,10 +1552,8 @@ static int vpif_dbg_s_register(struct file *file, void *priv,
                struct v4l2_dbg_register *reg){
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
 
-       return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core,
-                       s_register, reg);
+       return v4l2_subdev_call(ch->sd, core, s_register, reg);
 }
 #endif
 
@@ -1536,9 +1617,6 @@ static struct video_device vpif_video_template = {
        .name           = "vpif",
        .fops           = &vpif_fops,
        .ioctl_ops      = &vpif_ioctl_ops,
-       .tvnorms        = VPIF_V4L2_STD,
-       .current_norm   = V4L2_STD_625_50,
-
 };
 
 /*Configure the channels, buffer sizei, request irq */
@@ -1611,7 +1689,8 @@ static __init int vpif_probe(struct platform_device *pdev)
 {
        struct vpif_subdev_info *subdevdata;
        struct vpif_display_config *config;
-       int i, j = 0, k, q, m, err = 0;
+       int i, j = 0, k, err = 0;
+       int res_idx = 0;
        struct i2c_adapter *i2c_adap;
        struct common_obj *common;
        struct channel_obj *ch;
@@ -1634,21 +1713,22 @@ static __init int vpif_probe(struct platform_device *pdev)
                return err;
        }
 
-       k = 0;
-       while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) {
+       while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) {
                for (i = res->start; i <= res->end; i++) {
                        if (request_irq(i, vpif_channel_isr, IRQF_SHARED,
-                                       "VPIF_Display",
-                               (void *)(&vpif_obj.dev[k]->channel_id))) {
+                                       "VPIF_Display", (void *)
+                                       (&vpif_obj.dev[res_idx]->channel_id))) {
                                err = -EBUSY;
+                               for (j = 0; j < i; j++)
+                                       free_irq(j, (void *)
+                                       (&vpif_obj.dev[res_idx]->channel_id));
                                goto vpif_int_err;
                        }
                }
-               k++;
+               res_idx++;
        }
 
        for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
-
                /* Get the pointer to the channel object */
                ch = vpif_obj.dev[i];
 
@@ -1694,6 +1774,32 @@ static __init int vpif_probe(struct platform_device *pdev)
                }
        }
 
+       i2c_adap = i2c_get_adapter(1);
+       config = pdev->dev.platform_data;
+       subdev_count = config->subdev_count;
+       subdevdata = config->subdevinfo;
+       vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
+                                                               GFP_KERNEL);
+       if (vpif_obj.sd == NULL) {
+               vpif_err("unable to allocate memory for subdevice pointers\n");
+               err = -ENOMEM;
+               goto vpif_sd_error;
+       }
+
+       for (i = 0; i < subdev_count; i++) {
+               vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
+                                               i2c_adap,
+                                               &subdevdata[i].board_info,
+                                               NULL);
+               if (!vpif_obj.sd[i]) {
+                       vpif_err("Error registering v4l2 subdevice\n");
+                       goto probe_subdev_out;
+               }
+
+               if (vpif_obj.sd[i])
+                       vpif_obj.sd[i]->grp_id = 1 << i;
+       }
+
        for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {
                ch = vpif_obj.dev[j];
                /* Initialize field of the channel objects */
@@ -1715,6 +1821,8 @@ static __init int vpif_probe(struct platform_device *pdev)
 
                }
                ch->initialized = 0;
+               if (subdev_count)
+                       ch->sd = vpif_obj.sd[0];
                ch->channel_id = j;
                if (j < 2)
                        ch->common[VPIF_VIDEO_INDEX].numbuffers =
@@ -1729,6 +1837,12 @@ static __init int vpif_probe(struct platform_device *pdev)
                ch->common[VPIF_VIDEO_INDEX].fmt.type =
                                                V4L2_BUF_TYPE_VIDEO_OUTPUT;
                ch->video_dev->lock = &common->lock;
+               video_set_drvdata(ch->video_dev, ch);
+
+               /* select output 0 */
+               err = vpif_set_output(config, ch, 0);
+               if (err)
+                       goto probe_out;
 
                /* register video device */
                vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
@@ -1738,42 +1852,12 @@ static __init int vpif_probe(struct platform_device *pdev)
                                          VFL_TYPE_GRABBER, (j ? 3 : 2));
                if (err < 0)
                        goto probe_out;
-
-               video_set_drvdata(ch->video_dev, ch);
-       }
-
-       i2c_adap = i2c_get_adapter(1);
-       config = pdev->dev.platform_data;
-       subdev_count = config->subdev_count;
-       subdevdata = config->subdevinfo;
-       vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
-                                                               GFP_KERNEL);
-       if (vpif_obj.sd == NULL) {
-               vpif_err("unable to allocate memory for subdevice pointers\n");
-               err = -ENOMEM;
-               goto probe_out;
-       }
-
-       for (i = 0; i < subdev_count; i++) {
-               vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
-                                               i2c_adap,
-                                               &subdevdata[i].board_info,
-                                               NULL);
-               if (!vpif_obj.sd[i]) {
-                       vpif_err("Error registering v4l2 subdevice\n");
-                       goto probe_subdev_out;
-               }
-
-               if (vpif_obj.sd[i])
-                       vpif_obj.sd[i]->grp_id = 1 << i;
        }
 
        v4l2_info(&vpif_obj.v4l2_dev,
                        " VPIF display driver initialized\n");
        return 0;
 
-probe_subdev_out:
-       kfree(vpif_obj.sd);
 probe_out:
        for (k = 0; k < j; k++) {
                ch = vpif_obj.dev[k];
@@ -1781,14 +1865,21 @@ probe_out:
                video_device_release(ch->video_dev);
                ch->video_dev = NULL;
        }
+probe_subdev_out:
+       kfree(vpif_obj.sd);
+vpif_sd_error:
+       for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
+               ch = vpif_obj.dev[i];
+               /* Note: does nothing if ch->video_dev == NULL */
+               video_device_release(ch->video_dev);
+       }
 vpif_int_err:
        v4l2_device_unregister(&vpif_obj.v4l2_dev);
        vpif_err("VPIF IRQ request failed\n");
-       for (q = k; k >= 0; k--) {
-               for (m = i; m >= res->start; m--)
-                       free_irq(m, (void *)(&vpif_obj.dev[k]->channel_id));
-               res = platform_get_resource(pdev, IORESOURCE_IRQ, k-1);
-               m = res->end;
+       for (i = 0; i < res_idx; i++) {
+               res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+               for (j = res->start; j <= res->end; j++)
+                       free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id));
        }
 
        return err;
index f628ebcf36747110c78c86f4b904d76a5fca2ff8..a5a18f74395cdfa80a8f5e56d314f949afcb9f84 100644 (file)
@@ -62,13 +62,6 @@ struct video_obj {
        v4l2_std_id stdid;              /* Currently selected or default
                                         * standard */
        struct v4l2_dv_timings dv_timings;
-       u32 output_id;                  /* Current output id */
-};
-
-struct vbi_obj {
-       int num_services;
-       struct vpif_vbi_params vbiparams;       /* vpif parameters for the raw
-                                                * vbi data */
 };
 
 struct vpif_disp_buffer {
@@ -131,12 +124,13 @@ struct channel_obj {
                                         * which is being displayed */
        u8 initialized;                 /* flag to indicate whether
                                         * encoder is initialized */
+       u32 output_idx;                 /* Current output index */
+       struct v4l2_subdev *sd;         /* Current output subdev(may be NULL) */
 
        enum vpif_channel_id channel_id;/* Identifies channel */
        struct vpif_params vpifparams;
        struct common_obj common[VPIF_NUMOBJECTS];
        struct video_obj video;
-       struct vbi_obj vbi;
 };
 
 /* File handle structure */
@@ -168,12 +162,4 @@ struct vpif_config_params {
        u8 min_numbuffers;
 };
 
-/* Struct which keeps track of the line numbers for the sliced vbi service */
-struct vpif_service_line {
-       u16 service_id;
-       u16 service_line[2];
-       u16 enc_service_id;
-       u8 bytestowrite;
-};
-
 #endif                         /* DAVINCIHD_DISPLAY_H */
index 0d8625f03a32f9099920586a47e5f82ae0384332..0146b354dc22a785961dfe0e1dd5df6214311c53 100644 (file)
@@ -212,7 +212,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
                else
                        cfg |= GSC_IN_YUV422_3P;
                break;
-       };
+       }
 
        writel(cfg, dev->regs + GSC_IN_CON);
 }
@@ -332,7 +332,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
        case 3:
                cfg |= GSC_OUT_YUV420_3P;
                break;
-       };
+       }
 
 end_set:
        writel(cfg, dev->regs + GSC_OUT_CON);
index 897250b886474c0c950e23b0279e9f5e22343329..31ac4dc692475a5b5f1339941617569fd936f43e 100644 (file)
@@ -864,7 +864,7 @@ int vidioc_s_fbuf(struct file *file, void *priv, const struct v4l2_framebuffer *
 {
        struct viu_fh  *fh = priv;
        struct viu_dev *dev = fh->dev;
-       struct v4l2_framebuffer *fb = arg;
+       const struct v4l2_framebuffer *fb = arg;
        struct viu_fmt *fmt;
 
        if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
index d03637537118047a6ced26241cb55842de398d02..2e2121e98133d0ff56f7510c79a06cac8b9182d8 100644 (file)
@@ -397,8 +397,7 @@ static void device_isr(unsigned long priv)
        curr_ctx = v4l2_m2m_get_curr_priv(m2mtest_dev->m2m_dev);
 
        if (NULL == curr_ctx) {
-               printk(KERN_ERR
-                       "Instance released before the end of transaction\n");
+               pr_err("Instance released before the end of transaction\n");
                return;
        }
 
@@ -894,7 +893,7 @@ static int m2mtest_open(struct file *file)
 
        if (mutex_lock_interruptible(&dev->dev_mutex))
                return -ERESTARTSYS;
-       ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx) {
                rc = -ENOMEM;
                goto open_unlock;
@@ -1020,7 +1019,7 @@ static int m2mtest_probe(struct platform_device *pdev)
        struct video_device *vfd;
        int ret;
 
-       dev = kzalloc(sizeof *dev, GFP_KERNEL);
+       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
        if (!dev)
                return -ENOMEM;
 
@@ -1028,7 +1027,7 @@ static int m2mtest_probe(struct platform_device *pdev)
 
        ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
        if (ret)
-               goto free_dev;
+               return ret;
 
        atomic_set(&dev->num_inst, 0);
        mutex_init(&dev->dev_mutex);
@@ -1067,15 +1066,13 @@ static int m2mtest_probe(struct platform_device *pdev)
 
        return 0;
 
-       v4l2_m2m_release(dev->m2m_dev);
 err_m2m:
+       v4l2_m2m_release(dev->m2m_dev);
        video_unregister_device(dev->vfd);
 rel_vdev:
        video_device_release(vfd);
 unreg_dev:
        v4l2_device_unregister(&dev->v4l2_dev);
-free_dev:
-       kfree(dev);
 
        return ret;
 }
@@ -1090,7 +1087,6 @@ static int m2mtest_remove(struct platform_device *pdev)
        del_timer_sync(&dev->timer);
        video_unregister_device(dev->vfd);
        v4l2_device_unregister(&dev->v4l2_dev);
-       kfree(dev);
 
        return 0;
 }
index 134016f0e660dce4e76ad9cd8e13b184ea49d563..a3b1a34c896db9257000f6c1a3e8fb8bb7cd7df0 100644 (file)
@@ -455,11 +455,15 @@ static int omapvid_init(struct omap_vout_device *vout, u32 addr)
 
        win = &vout->win;
        for (i = 0; i < ovid->num_overlays; i++) {
+               struct omap_dss_device *dssdev;
+
                ovl = ovid->overlays[i];
-               if (!ovl->manager || !ovl->manager->device)
+               dssdev = ovl->get_device(ovl);
+
+               if (!dssdev)
                        return -EINVAL;
 
-               timing = &ovl->manager->device->panel.timings;
+               timing = &dssdev->panel.timings;
 
                outw = win->w.width;
                outh = win->w.height;
@@ -516,8 +520,11 @@ static int omapvid_apply_changes(struct omap_vout_device *vout)
        struct omapvideo_info *ovid = &vout->vid_info;
 
        for (i = 0; i < ovid->num_overlays; i++) {
+               struct omap_dss_device *dssdev;
+
                ovl = ovid->overlays[i];
-               if (!ovl->manager || !ovl->manager->device)
+               dssdev = ovl->get_device(ovl);
+               if (!dssdev)
                        return -EINVAL;
                ovl->manager->apply(ovl->manager);
        }
@@ -580,12 +587,14 @@ static void omap_vout_isr(void *arg, unsigned int irqstatus)
 
        ovid = &vout->vid_info;
        ovl = ovid->overlays[0];
-       /* get the display device attached to the overlay */
-       if (!ovl->manager || !ovl->manager->device)
-               return;
 
        mgr_id = ovl->manager->id;
-       cur_display = ovl->manager->device;
+
+       /* get the display device attached to the overlay */
+       cur_display = ovl->get_device(ovl);
+
+       if (!cur_display)
+               return;
 
        spin_lock(&vout->vbq_lock);
        do_gettimeofday(&timevalue);
@@ -949,7 +958,9 @@ static int omap_vout_release(struct file *file)
        /* Disable all the overlay managers connected with this interface */
        for (i = 0; i < ovid->num_overlays; i++) {
                struct omap_overlay *ovl = ovid->overlays[i];
-               if (ovl->manager && ovl->manager->device)
+               struct omap_dss_device *dssdev = ovl->get_device(ovl);
+
+               if (dssdev)
                        ovl->disable(ovl);
        }
        /* Turn off the pipeline */
@@ -1082,14 +1093,17 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *fh,
        struct omapvideo_info *ovid;
        struct omap_video_timings *timing;
        struct omap_vout_device *vout = fh;
+       struct omap_dss_device *dssdev;
 
        ovid = &vout->vid_info;
        ovl = ovid->overlays[0];
+       /* get the display device attached to the overlay */
+       dssdev = ovl->get_device(ovl);
 
-       if (!ovl->manager || !ovl->manager->device)
+       if (!dssdev)
                return -EINVAL;
-       /* get the display device attached to the overlay */
-       timing = &ovl->manager->device->panel.timings;
+
+       timing = &dssdev->panel.timings;
 
        vout->fbuf.fmt.height = timing->y_res;
        vout->fbuf.fmt.width = timing->x_res;
@@ -1106,6 +1120,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
        struct omapvideo_info *ovid;
        struct omap_video_timings *timing;
        struct omap_vout_device *vout = fh;
+       struct omap_dss_device *dssdev;
 
        if (vout->streaming)
                return -EBUSY;
@@ -1114,13 +1129,14 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
 
        ovid = &vout->vid_info;
        ovl = ovid->overlays[0];
+       dssdev = ovl->get_device(ovl);
 
        /* get the display device attached to the overlay */
-       if (!ovl->manager || !ovl->manager->device) {
+       if (!dssdev) {
                ret = -EINVAL;
                goto s_fmt_vid_out_exit;
        }
-       timing = &ovl->manager->device->panel.timings;
+       timing = &dssdev->panel.timings;
 
        /* We dont support RGB24-packed mode if vrfb rotation
         * is enabled*/
@@ -1299,6 +1315,7 @@ static int vidioc_s_crop(struct file *file, void *fh, const struct v4l2_crop *cr
        struct omapvideo_info *ovid;
        struct omap_overlay *ovl;
        struct omap_video_timings *timing;
+       struct omap_dss_device *dssdev;
 
        if (vout->streaming)
                return -EBUSY;
@@ -1306,13 +1323,15 @@ static int vidioc_s_crop(struct file *file, void *fh, const struct v4l2_crop *cr
        mutex_lock(&vout->lock);
        ovid = &vout->vid_info;
        ovl = ovid->overlays[0];
+       /* get the display device attached to the overlay */
+       dssdev = ovl->get_device(ovl);
 
-       if (!ovl->manager || !ovl->manager->device) {
+       if (!dssdev) {
                ret = -EINVAL;
                goto s_crop_err;
        }
-       /* get the display device attached to the overlay */
-       timing = &ovl->manager->device->panel.timings;
+
+       timing = &dssdev->panel.timings;
 
        if (is_rotation_90_or_270(vout)) {
                vout->fbuf.fmt.height = timing->x_res;
@@ -1668,7 +1687,7 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
        for (j = 0; j < ovid->num_overlays; j++) {
                struct omap_overlay *ovl = ovid->overlays[j];
 
-               if (ovl->manager && ovl->manager->device) {
+               if (ovl->get_device(ovl)) {
                        struct omap_overlay_info info;
                        ovl->get_overlay_info(ovl, &info);
                        info.paddr = addr;
@@ -1691,8 +1710,9 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
 
        for (j = 0; j < ovid->num_overlays; j++) {
                struct omap_overlay *ovl = ovid->overlays[j];
+               struct omap_dss_device *dssdev = ovl->get_device(ovl);
 
-               if (ovl->manager && ovl->manager->device) {
+               if (dssdev) {
                        ret = ovl->enable(ovl);
                        if (ret)
                                goto streamon_err1;
@@ -1727,8 +1747,9 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
 
        for (j = 0; j < ovid->num_overlays; j++) {
                struct omap_overlay *ovl = ovid->overlays[j];
+               struct omap_dss_device *dssdev = ovl->get_device(ovl);
 
-               if (ovl->manager && ovl->manager->device)
+               if (dssdev)
                        ovl->disable(ovl);
        }
 
@@ -1891,8 +1912,8 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
        struct video_device *vfd;
        struct v4l2_pix_format *pix;
        struct v4l2_control *control;
-       struct omap_dss_device *display =
-               vout->vid_info.overlays[0]->manager->device;
+       struct omap_overlay *ovl = vout->vid_info.overlays[0];
+       struct omap_dss_device *display = ovl->get_device(ovl);
 
        /* set the default pix */
        pix = &vout->pix;
@@ -2207,8 +2228,10 @@ static int __init omap_vout_probe(struct platform_device *pdev)
         */
        for (i = 1; i < vid_dev->num_overlays; i++) {
                ovl = omap_dss_get_overlay(i);
-               if (ovl->manager && ovl->manager->device) {
-                       def_display = ovl->manager->device;
+               dssdev = ovl->get_device(ovl);
+
+               if (dssdev) {
+                       def_display = dssdev;
                } else {
                        dev_warn(&pdev->dev, "cannot find display\n");
                        def_display = NULL;
@@ -2255,8 +2278,10 @@ probe_err1:
        for (i = 1; i < vid_dev->num_overlays; i++) {
                def_display = NULL;
                ovl = omap_dss_get_overlay(i);
-               if (ovl->manager && ovl->manager->device)
-                       def_display = ovl->manager->device;
+               dssdev = ovl->get_device(ovl);
+
+               if (dssdev)
+                       def_display = dssdev;
 
                if (def_display && def_display->driver)
                        def_display->driver->disable(def_display);
index 084ea77d65a75a454eccd76c1746b04cb5d4668a..e2c57f334c5d4a4da780069bf5869eb383f4b4a0 100644 (file)
 #ifndef OMAP3_ISP_REG_H
 #define OMAP3_ISP_REG_H
 
-#include <plat/omap34xx.h>
-
-
 #define CM_CAM_MCLK_HZ                 172800000       /* Hz */
 
 /* ISP Submodules offset */
 
+#define L4_34XX_BASE                   0x48000000
+#define OMAP3430_ISP_BASE              (L4_34XX_BASE + 0xBC000)
+
 #define OMAP3ISP_REG_BASE              OMAP3430_ISP_BASE
 #define OMAP3ISP_REG(offset)           (OMAP3ISP_REG_BASE + (offset))
 
index dded988152206e779c3f49844d5ade4a09f14663..367efd164d0f1c9580111b12b51c8e2a9f225bfa 100644 (file)
@@ -177,7 +177,9 @@ static int fimc_capture_config_update(struct fimc_ctx *ctx)
 
 void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
 {
+       struct v4l2_subdev *csis = fimc->pipeline.subdevs[IDX_CSIS];
        struct fimc_vid_cap *cap = &fimc->vid_cap;
+       struct fimc_frame *f = &cap->ctx->d_frame;
        struct fimc_vid_buffer *v_buf;
        struct timeval *tv;
        struct timespec ts;
@@ -216,6 +218,25 @@ void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
                if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
                        cap->buf_index = 0;
        }
+       /*
+        * Set up a buffer at MIPI-CSIS if current image format
+        * requires the frame embedded data capture.
+        */
+       if (f->fmt->mdataplanes && !list_empty(&cap->active_buf_q)) {
+               unsigned int plane = ffs(f->fmt->mdataplanes) - 1;
+               unsigned int size = f->payload[plane];
+               s32 index = fimc_hw_get_frame_index(fimc);
+               void *vaddr;
+
+               list_for_each_entry(v_buf, &cap->active_buf_q, list) {
+                       if (v_buf->index != index)
+                               continue;
+                       vaddr = vb2_plane_vaddr(&v_buf->vb, plane);
+                       v4l2_subdev_call(csis, video, s_rx_buffer,
+                                        vaddr, &size);
+                       break;
+               }
+       }
 
        if (cap->active_buf_cnt == 0) {
                if (deq_buf)
@@ -351,6 +372,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
                unsigned int size = (wh * fmt->depth[i]) / 8;
                if (pixm)
                        sizes[i] = max(size, pixm->plane_fmt[i].sizeimage);
+               else if (fimc_fmt_is_user_defined(fmt->color))
+                       sizes[i] = frame->payload[i];
                else
                        sizes[i] = max_t(u32, size, frame->payload[i]);
 
@@ -611,10 +634,10 @@ static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx,
        u32 mask = FMT_FLAGS_CAM;
        struct fimc_fmt *ffmt;
 
-       /* Color conversion from/to JPEG is not supported */
+       /* Conversion from/to JPEG or User Defined format is not supported */
        if (code && ctx->s_frame.fmt && pad == FIMC_SD_PAD_SOURCE &&
-           fimc_fmt_is_jpeg(ctx->s_frame.fmt->color))
-               *code = V4L2_MBUS_FMT_JPEG_1X8;
+           fimc_fmt_is_user_defined(ctx->s_frame.fmt->color))
+               *code = ctx->s_frame.fmt->mbus_code;
 
        if (fourcc && *fourcc != V4L2_PIX_FMT_JPEG && pad != FIMC_SD_PAD_SINK)
                mask |= FMT_FLAGS_M2M;
@@ -628,18 +651,19 @@ static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx,
                *fourcc = ffmt->fourcc;
 
        if (pad == FIMC_SD_PAD_SINK) {
-               max_w = fimc_fmt_is_jpeg(ffmt->color) ?
+               max_w = fimc_fmt_is_user_defined(ffmt->color) ?
                        pl->scaler_dis_w : pl->scaler_en_w;
                /* Apply the camera input interface pixel constraints */
                v4l_bound_align_image(width, max_t(u32, *width, 32), max_w, 4,
                                      height, max_t(u32, *height, 32),
                                      FIMC_CAMIF_MAX_HEIGHT,
-                                     fimc_fmt_is_jpeg(ffmt->color) ? 3 : 1,
+                                     fimc_fmt_is_user_defined(ffmt->color) ?
+                                     3 : 1,
                                      0);
                return ffmt;
        }
        /* Can't scale or crop in transparent (JPEG) transfer mode */
-       if (fimc_fmt_is_jpeg(ffmt->color)) {
+       if (fimc_fmt_is_user_defined(ffmt->color)) {
                *width  = ctx->s_frame.f_width;
                *height = ctx->s_frame.f_height;
                return ffmt;
@@ -684,7 +708,7 @@ static void fimc_capture_try_selection(struct fimc_ctx *ctx,
        u32 max_sc_h, max_sc_v;
 
        /* In JPEG transparent transfer mode cropping is not supported */
-       if (fimc_fmt_is_jpeg(ctx->d_frame.fmt->color)) {
+       if (fimc_fmt_is_user_defined(ctx->d_frame.fmt->color)) {
                r->width  = sink->f_width;
                r->height = sink->f_height;
                r->left   = r->top = 0;
@@ -847,6 +871,48 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
        return 0;
 }
 
+/**
+ * fimc_get_sensor_frame_desc - query the sensor for media bus frame parameters
+ * @sensor: pointer to the sensor subdev
+ * @plane_fmt: provides plane sizes corresponding to the frame layout entries
+ * @try: true to set the frame parameters, false to query only
+ *
+ * This function is used by this driver only for compressed/blob data formats.
+ */
+static int fimc_get_sensor_frame_desc(struct v4l2_subdev *sensor,
+                                     struct v4l2_plane_pix_format *plane_fmt,
+                                     unsigned int num_planes, bool try)
+{
+       struct v4l2_mbus_frame_desc fd;
+       int i, ret;
+
+       for (i = 0; i < num_planes; i++)
+               fd.entry[i].length = plane_fmt[i].sizeimage;
+
+       if (try)
+               ret = v4l2_subdev_call(sensor, pad, set_frame_desc, 0, &fd);
+       else
+               ret = v4l2_subdev_call(sensor, pad, get_frame_desc, 0, &fd);
+
+       if (ret < 0)
+               return ret;
+
+       if (num_planes != fd.num_entries)
+               return -EINVAL;
+
+       for (i = 0; i < num_planes; i++)
+               plane_fmt[i].sizeimage = fd.entry[i].length;
+
+       if (fd.entry[0].length > FIMC_MAX_JPEG_BUF_SIZE) {
+               v4l2_err(sensor->v4l2_dev,  "Unsupported buffer size: %u\n",
+                        fd.entry[0].length);
+
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int fimc_cap_g_fmt_mplane(struct file *file, void *fh,
                                 struct v4l2_format *f)
 {
@@ -865,7 +931,7 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
        struct v4l2_mbus_framefmt mf;
        struct fimc_fmt *ffmt = NULL;
 
-       if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+       if (fimc_jpeg_fourcc(pix->pixelformat)) {
                fimc_capture_try_format(ctx, &pix->width, &pix->height,
                                        NULL, &pix->pixelformat,
                                        FIMC_SD_PAD_SINK);
@@ -879,25 +945,32 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
                return -EINVAL;
 
        if (!fimc->vid_cap.user_subdev_api) {
-               mf.width  = pix->width;
+               mf.width = pix->width;
                mf.height = pix->height;
-               mf.code   = ffmt->mbus_code;
+               mf.code = ffmt->mbus_code;
                fimc_md_graph_lock(fimc);
                fimc_pipeline_try_format(ctx, &mf, &ffmt, false);
                fimc_md_graph_unlock(fimc);
-
-               pix->width       = mf.width;
-               pix->height      = mf.height;
+               pix->width = mf.width;
+               pix->height = mf.height;
                if (ffmt)
                        pix->pixelformat = ffmt->fourcc;
        }
 
        fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix);
+
+       if (ffmt->flags & FMT_FLAGS_COMPRESSED)
+               fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR],
+                                       pix->plane_fmt, ffmt->memplanes, true);
+
        return 0;
 }
 
-static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, bool jpeg)
+static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx,
+                                       enum fimc_color_fmt color)
 {
+       bool jpeg = fimc_fmt_is_user_defined(color);
+
        ctx->scaler.enabled = !jpeg;
        fimc_ctrls_activate(ctx, !jpeg);
 
@@ -920,7 +993,7 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
                return -EBUSY;
 
        /* Pre-configure format at camera interface input, for JPEG only */
-       if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+       if (fimc_jpeg_fourcc(pix->pixelformat)) {
                fimc_capture_try_format(ctx, &pix->width, &pix->height,
                                        NULL, &pix->pixelformat,
                                        FIMC_SD_PAD_SINK);
@@ -953,7 +1026,16 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
        }
 
        fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix);
-       for (i = 0; i < ff->fmt->colplanes; i++)
+
+       if (ff->fmt->flags & FMT_FLAGS_COMPRESSED) {
+               ret = fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR],
+                                       pix->plane_fmt, ff->fmt->memplanes,
+                                       true);
+               if (ret < 0)
+                       return ret;
+       }
+
+       for (i = 0; i < ff->fmt->memplanes; i++)
                ff->payload[i] = pix->plane_fmt[i].sizeimage;
 
        set_frame_bounds(ff, pix->width, pix->height);
@@ -961,7 +1043,7 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
        if (!(ctx->state & FIMC_COMPOSE))
                set_frame_crop(ff, 0, 0, pix->width, pix->height);
 
-       fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ff->fmt->color));
+       fimc_capture_mark_jpeg_xfer(ctx, ff->fmt->color);
 
        /* Reset cropping and set format at the camera interface input */
        if (!fimc->vid_cap.user_subdev_api) {
@@ -1063,6 +1145,23 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
                    src_fmt.format.height != sink_fmt.format.height ||
                    src_fmt.format.code != sink_fmt.format.code)
                        return -EPIPE;
+
+               if (sd == fimc->pipeline.subdevs[IDX_SENSOR] &&
+                   fimc_user_defined_mbus_fmt(src_fmt.format.code)) {
+                       struct v4l2_plane_pix_format plane_fmt[FIMC_MAX_PLANES];
+                       struct fimc_frame *frame = &vid_cap->ctx->d_frame;
+                       unsigned int i;
+
+                       ret = fimc_get_sensor_frame_desc(sd, plane_fmt,
+                                                        frame->fmt->memplanes,
+                                                        false);
+                       if (ret < 0)
+                               return -EPIPE;
+
+                       for (i = 0; i < frame->fmt->memplanes; i++)
+                               if (frame->payload[i] < plane_fmt[i].sizeimage)
+                                       return -EPIPE;
+               }
        }
        return 0;
 }
@@ -1424,7 +1523,7 @@ static int fimc_subdev_set_fmt(struct v4l2_subdev *sd,
        /* Update RGB Alpha control state and value range */
        fimc_alpha_ctrl_update(ctx);
 
-       fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ffmt->color));
+       fimc_capture_mark_jpeg_xfer(ctx, ffmt->color);
 
        ff = fmt->pad == FIMC_SD_PAD_SINK ?
                &ctx->s_frame : &ctx->d_frame;
index 1a445404e73d2bea57a2e788e21717a7f21fb6ac..8d0d2b94a135f45b0d8fa2c1378fd287aff7ef27 100644 (file)
@@ -184,7 +184,17 @@ static struct fimc_fmt fimc_formats[] = {
                .memplanes      = 1,
                .colplanes      = 1,
                .mbus_code      = V4L2_MBUS_FMT_JPEG_1X8,
-               .flags          = FMT_FLAGS_CAM,
+               .flags          = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
+       }, {
+               .name           = "S5C73MX interleaved UYVY/JPEG",
+               .fourcc         = V4L2_PIX_FMT_S5C_UYVY_JPG,
+               .color          = FIMC_FMT_YUYV_JPEG,
+               .depth          = { 8 },
+               .memplanes      = 2,
+               .colplanes      = 1,
+               .mdataplanes    = 0x2, /* plane 1 holds frame meta data */
+               .mbus_code      = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
+               .flags          = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
        },
 };
 
@@ -371,7 +381,7 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
                default:
                        return -EINVAL;
                }
-       } else {
+       } else if (!frame->fmt->mdataplanes) {
                if (frame->fmt->memplanes >= 2)
                        paddr->cb = vb2_dma_contig_plane_dma_addr(vb, 1);
 
@@ -698,6 +708,11 @@ int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f)
                if (frame->fmt->colplanes == 1) /* packed formats */
                        bpl = (bpl * frame->fmt->depth[0]) / 8;
                pixm->plane_fmt[i].bytesperline = bpl;
+
+               if (frame->fmt->flags & FMT_FLAGS_COMPRESSED) {
+                       pixm->plane_fmt[i].sizeimage = frame->payload[i];
+                       continue;
+               }
                pixm->plane_fmt[i].sizeimage = (frame->o_width *
                        frame->o_height * frame->fmt->depth[i]) / 8;
        }
index cd716ba6015f6e5c441c84a4fe34627f1121ee47..c0040d7924995051e71faaed70942cb2b74ec7c6 100644 (file)
@@ -40,6 +40,8 @@
 #define SCALER_MAX_VRATIO      64
 #define DMA_MIN_SIZE           8
 #define FIMC_CAMIF_MAX_HEIGHT  0x2000
+#define FIMC_MAX_JPEG_BUF_SIZE (10 * SZ_1M)
+#define FIMC_MAX_PLANES                3
 
 /* indices to the clocks array */
 enum {
@@ -83,7 +85,7 @@ enum fimc_datapath {
 };
 
 enum fimc_color_fmt {
-       FIMC_FMT_RGB444 = 0x10,
+       FIMC_FMT_RGB444 = 0x10,
        FIMC_FMT_RGB555,
        FIMC_FMT_RGB565,
        FIMC_FMT_RGB666,
@@ -95,14 +97,15 @@ enum fimc_color_fmt {
        FIMC_FMT_CBYCRY422,
        FIMC_FMT_CRYCBY422,
        FIMC_FMT_YCBCR444_LOCAL,
-       FIMC_FMT_JPEG = 0x40,
-       FIMC_FMT_RAW8 = 0x80,
+       FIMC_FMT_RAW8 = 0x40,
        FIMC_FMT_RAW10,
        FIMC_FMT_RAW12,
+       FIMC_FMT_JPEG = 0x80,
+       FIMC_FMT_YUYV_JPEG = 0x100,
 };
 
+#define fimc_fmt_is_user_defined(x) (!!((x) & 0x180))
 #define fimc_fmt_is_rgb(x) (!!((x) & 0x10))
-#define fimc_fmt_is_jpeg(x) (!!((x) & 0x40))
 
 #define IS_M2M(__strt) ((__strt) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || \
                        __strt == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
@@ -139,6 +142,7 @@ enum fimc_color_fmt {
  * @memplanes: number of physically non-contiguous data planes
  * @colplanes: number of physically contiguous data planes
  * @depth: per plane driver's private 'number of bits per pixel'
+ * @mdataplanes: bitmask indicating meta data plane(s), (1 << plane_no)
  * @flags: flags indicating which operation mode format applies to
  */
 struct fimc_fmt {
@@ -149,12 +153,14 @@ struct fimc_fmt {
        u16     memplanes;
        u16     colplanes;
        u8      depth[VIDEO_MAX_PLANES];
+       u16     mdataplanes;
        u16     flags;
 #define FMT_FLAGS_CAM          (1 << 0)
 #define FMT_FLAGS_M2M_IN       (1 << 1)
 #define FMT_FLAGS_M2M_OUT      (1 << 2)
 #define FMT_FLAGS_M2M          (1 << 1 | 1 << 2)
 #define FMT_HAS_ALPHA          (1 << 3)
+#define FMT_FLAGS_COMPRESSED   (1 << 4)
 };
 
 /**
@@ -272,7 +278,7 @@ struct fimc_frame {
        u32     offs_v;
        u32     width;
        u32     height;
-       unsigned long           payload[VIDEO_MAX_PLANES];
+       unsigned int            payload[VIDEO_MAX_PLANES];
        struct fimc_addr        paddr;
        struct fimc_dma_offset  dma_offset;
        struct fimc_fmt         *fmt;
@@ -577,6 +583,18 @@ static inline int tiled_fmt(struct fimc_fmt *fmt)
        return fmt->fourcc == V4L2_PIX_FMT_NV12MT;
 }
 
+static inline bool fimc_jpeg_fourcc(u32 pixelformat)
+{
+       return (pixelformat == V4L2_PIX_FMT_JPEG ||
+               pixelformat == V4L2_PIX_FMT_S5C_UYVY_JPG);
+}
+
+static inline bool fimc_user_defined_mbus_fmt(u32 code)
+{
+       return (code == V4L2_MBUS_FMT_JPEG_1X8 ||
+               code == V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8);
+}
+
 /* Return the alpha component bit mask */
 static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt)
 {
index 6b71d953fd15b1a533f90a39d0eb0b9ed112b17c..4500e44f6857c909adcbd74cb13ad4dc2ac85cbc 100644 (file)
@@ -551,30 +551,31 @@ static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
        return 0;
 }
 
-static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *cr)
+static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
 {
        struct fimc_ctx *ctx = fh_to_ctx(fh);
        struct fimc_dev *fimc = ctx->fimc_dev;
+       struct v4l2_crop cr = *crop;
        struct fimc_frame *f;
        int ret;
 
-       ret = fimc_m2m_try_crop(ctx, cr);
+       ret = fimc_m2m_try_crop(ctx, &cr);
        if (ret)
                return ret;
 
-       f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
+       f = (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
                &ctx->s_frame : &ctx->d_frame;
 
        /* Check to see if scaling ratio is within supported range */
        if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
-               if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-                       ret = fimc_check_scaler_ratio(ctx, cr->c.width,
-                                       cr->c.height, ctx->d_frame.width,
+               if (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+                       ret = fimc_check_scaler_ratio(ctx, cr.c.width,
+                                       cr.c.height, ctx->d_frame.width,
                                        ctx->d_frame.height, ctx->rotation);
                } else {
                        ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width,
-                                       ctx->s_frame.height, cr->c.width,
-                                       cr->c.height, ctx->rotation);
+                                       ctx->s_frame.height, cr.c.width,
+                                       cr.c.height, ctx->rotation);
                }
                if (ret) {
                        v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n");
@@ -582,10 +583,10 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *
                }
        }
 
-       f->offs_h = cr->c.left;
-       f->offs_v = cr->c.top;
-       f->width  = cr->c.width;
-       f->height = cr->c.height;
+       f->offs_h = cr.c.left;
+       f->offs_v = cr.c.top;
+       f->width  = cr.c.width;
+       f->height = cr.c.height;
 
        fimc_ctx_state_set(FIMC_PARAMS, ctx);
 
index 783408fd7d566b53b165e5bd896ee8aaef38c4ea..2c9d0c06c9e8faef0be5645508ad8495b9356844 100644 (file)
@@ -625,7 +625,7 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc,
                                cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT;
                } /* else defaults to ITU-R BT.656 8-bit */
        } else if (cam->bus_type == FIMC_MIPI_CSI2) {
-               if (fimc_fmt_is_jpeg(f->fmt->color))
+               if (fimc_fmt_is_user_defined(f->fmt->color))
                        cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
        }
 
@@ -680,6 +680,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
                        tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT;
                        break;
                case V4L2_MBUS_FMT_JPEG_1X8:
+               case V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8:
                        tmp = FIMC_REG_CSIIMGFMT_USER(1);
                        cfg |= FIMC_REG_CIGCTRL_CAM_JPEG;
                        break;
@@ -744,13 +745,13 @@ void fimc_hw_dis_capture(struct fimc_dev *dev)
 }
 
 /* Return an index to the buffer actually being written. */
-u32 fimc_hw_get_frame_index(struct fimc_dev *dev)
+s32 fimc_hw_get_frame_index(struct fimc_dev *dev)
 {
-       u32 reg;
+       s32 reg;
 
        if (dev->variant->has_cistatus2) {
-               reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3F;
-               return reg > 0 ? --reg : reg;
+               reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3f;
+               return reg - 1;
        }
 
        reg = readl(dev->regs + FIMC_REG_CISTATUS);
@@ -759,6 +760,18 @@ u32 fimc_hw_get_frame_index(struct fimc_dev *dev)
                FIMC_REG_CISTATUS_FRAMECNT_SHIFT;
 }
 
+/* Return an index to the buffer being written previously. */
+s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev)
+{
+       s32 reg;
+
+       if (!dev->variant->has_cistatus2)
+               return -1;
+
+       reg = readl(dev->regs + FIMC_REG_CISTATUS2);
+       return ((reg >> 7) & 0x3f) - 1;
+}
+
 /* Locking: the caller holds fimc->slock */
 void fimc_activate_capture(struct fimc_ctx *ctx)
 {
index 579ac8ac03deb76c2f78ef5f63ac63a35676f545..b6abfc7b72ace7472c7caea9d398500f3402be08 100644 (file)
@@ -307,7 +307,8 @@ void fimc_hw_clear_irq(struct fimc_dev *dev);
 void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on);
 void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on);
 void fimc_hw_dis_capture(struct fimc_dev *dev);
-u32 fimc_hw_get_frame_index(struct fimc_dev *dev);
+s32 fimc_hw_get_frame_index(struct fimc_dev *dev);
+s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev);
 void fimc_activate_capture(struct fimc_ctx *ctx);
 void fimc_deactivate_capture(struct fimc_dev *fimc);
 
index e92236ac5cfe86e5787f0f95bc057a920d3d4255..4c961b1b68e6004ab1dd98d578b0e6cc407e97f9 100644 (file)
@@ -2,7 +2,7 @@
  * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver
  *
  * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd.
- * Sylwester Nawrocki, <s.nawrocki@samsung.com>
+ * Sylwester Nawrocki <s.nawrocki@samsung.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
@@ -98,6 +98,11 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
 #define CSIS_MAX_PIX_WIDTH             0xffff
 #define CSIS_MAX_PIX_HEIGHT            0xffff
 
+/* Non-image packet data buffers */
+#define S5PCSIS_PKTDATA_ODD            0x2000
+#define S5PCSIS_PKTDATA_EVEN           0x3000
+#define S5PCSIS_PKTDATA_SIZE           SZ_4K
+
 enum {
        CSIS_CLK_MUX,
        CSIS_CLK_GATE,
@@ -110,8 +115,8 @@ static char *csi_clock_name[] = {
 #define NUM_CSIS_CLOCKS        ARRAY_SIZE(csi_clock_name)
 
 static const char * const csis_supply_name[] = {
-       "vdd11", /* 1.1V or 1.2V (s5pc100) MIPI CSI suppply */
-       "vdd18", /* VDD 1.8V and MIPI CSI PLL supply */
+       "vddcore",  /* CSIS Core (1.0V, 1.1V or 1.2V) suppply */
+       "vddio",    /* CSIS I/O and PLL (1.8V) supply */
 };
 #define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name)
 
@@ -144,12 +149,18 @@ static const struct s5pcsis_event s5pcsis_events[] = {
 };
 #define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events)
 
+struct csis_pktbuf {
+       u32 *data;
+       unsigned int len;
+};
+
 /**
  * struct csis_state - the driver's internal state data structure
  * @lock: mutex serializing the subdev and power management operations,
  *        protecting @format and @flags members
  * @pads: CSIS pads array
  * @sd: v4l2_subdev associated with CSIS device instance
+ * @index: the hardware instance index
  * @pdev: CSIS platform device
  * @regs: mmaped I/O registers memory
  * @supplies: CSIS regulator supplies
@@ -159,12 +170,14 @@ static const struct s5pcsis_event s5pcsis_events[] = {
  * @csis_fmt: current CSIS pixel format
  * @format: common media bus format for the source and sink pad
  * @slock: spinlock protecting structure members below
+ * @pkt_buf: the frame embedded (non-image) data buffer
  * @events: MIPI-CSIS event (error) counters
  */
 struct csis_state {
        struct mutex lock;
        struct media_pad pads[CSIS_PADS_NUM];
        struct v4l2_subdev sd;
+       u8 index;
        struct platform_device *pdev;
        void __iomem *regs;
        struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
@@ -175,6 +188,7 @@ struct csis_state {
        struct v4l2_mbus_framefmt format;
 
        struct spinlock slock;
+       struct csis_pktbuf pkt_buf;
        struct s5pcsis_event events[S5PCSIS_NUM_EVENTS];
 };
 
@@ -202,7 +216,11 @@ static const struct csis_pix_format s5pcsis_formats[] = {
                .code = V4L2_MBUS_FMT_JPEG_1X8,
                .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
                .data_alignment = 32,
-       },
+       }, {
+               .code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
+               .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
+               .data_alignment = 32,
+       }
 };
 
 #define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
@@ -266,7 +284,7 @@ static void __s5pcsis_set_format(struct csis_state *state)
        struct v4l2_mbus_framefmt *mf = &state->format;
        u32 val;
 
-       v4l2_dbg(1, debug, &state->sd, "fmt: %d, %d x %d\n",
+       v4l2_dbg(1, debug, &state->sd, "fmt: %#x, %d x %d\n",
                 mf->code, mf->width, mf->height);
 
        /* Color format */
@@ -304,8 +322,10 @@ static void s5pcsis_set_params(struct csis_state *state)
                val |= S5PCSIS_CTRL_ALIGN_32BIT;
        else /* 24-bits */
                val &= ~S5PCSIS_CTRL_ALIGN_32BIT;
-       /* Not using external clock. */
+
        val &= ~S5PCSIS_CTRL_WCLK_EXTCLK;
+       if (pdata->wclk_source)
+               val |= S5PCSIS_CTRL_WCLK_EXTCLK;
        s5pcsis_write(state, S5PCSIS_CTRL, val);
 
        /* Update the shadow register. */
@@ -529,6 +549,22 @@ static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        return 0;
 }
 
+static int s5pcsis_s_rx_buffer(struct v4l2_subdev *sd, void *buf,
+                              unsigned int *size)
+{
+       struct csis_state *state = sd_to_csis_state(sd);
+       unsigned long flags;
+
+       *size = min_t(unsigned int, *size, S5PCSIS_PKTDATA_SIZE);
+
+       spin_lock_irqsave(&state->slock, flags);
+       state->pkt_buf.data = buf;
+       state->pkt_buf.len = *size;
+       spin_unlock_irqrestore(&state->slock, flags);
+
+       return 0;
+}
+
 static int s5pcsis_log_status(struct v4l2_subdev *sd)
 {
        struct csis_state *state = sd_to_csis_state(sd);
@@ -566,6 +602,7 @@ static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = {
 };
 
 static struct v4l2_subdev_video_ops s5pcsis_video_ops = {
+       .s_rx_buffer = s5pcsis_s_rx_buffer,
        .s_stream = s5pcsis_s_stream,
 };
 
@@ -578,13 +615,26 @@ static struct v4l2_subdev_ops s5pcsis_subdev_ops = {
 static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
 {
        struct csis_state *state = dev_id;
+       struct csis_pktbuf *pktbuf = &state->pkt_buf;
        unsigned long flags;
        u32 status;
 
        status = s5pcsis_read(state, S5PCSIS_INTSRC);
-
        spin_lock_irqsave(&state->slock, flags);
 
+       if ((status & S5PCSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) {
+               u32 offset;
+
+               if (status & S5PCSIS_INTSRC_EVEN)
+                       offset = S5PCSIS_PKTDATA_EVEN;
+               else
+                       offset = S5PCSIS_PKTDATA_ODD;
+
+               memcpy(pktbuf->data, state->regs + offset, pktbuf->len);
+               pktbuf->data = NULL;
+               rmb();
+       }
+
        /* Update the event/error counters */
        if ((status & S5PCSIS_INTSRC_ERRORS) || debug) {
                int i;
@@ -620,14 +670,15 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
        spin_lock_init(&state->slock);
 
        state->pdev = pdev;
+       state->index = max(0, pdev->id);
 
        pdata = pdev->dev.platform_data;
-       if (pdata == NULL || pdata->phy_enable == NULL) {
+       if (pdata == NULL) {
                dev_err(&pdev->dev, "Platform data not fully specified\n");
                return -EINVAL;
        }
 
-       if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) ||
+       if ((state->index == 1 && pdata->lanes > CSIS1_MAX_LANES) ||
            pdata->lanes > CSIS0_MAX_LANES) {
                dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n",
                        pdata->lanes);
@@ -710,7 +761,6 @@ e_clkput:
 
 static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
 {
-       struct s5p_platform_mipi_csis *pdata = dev->platform_data;
        struct platform_device *pdev = to_platform_device(dev);
        struct v4l2_subdev *sd = platform_get_drvdata(pdev);
        struct csis_state *state = sd_to_csis_state(sd);
@@ -722,7 +772,7 @@ static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
        mutex_lock(&state->lock);
        if (state->flags & ST_POWERED) {
                s5pcsis_stop_stream(state);
-               ret = pdata->phy_enable(state->pdev, false);
+               ret = s5p_csis_phy_enable(state->index, false);
                if (ret)
                        goto unlock;
                ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
@@ -741,7 +791,6 @@ static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
 
 static int s5pcsis_pm_resume(struct device *dev, bool runtime)
 {
-       struct s5p_platform_mipi_csis *pdata = dev->platform_data;
        struct platform_device *pdev = to_platform_device(dev);
        struct v4l2_subdev *sd = platform_get_drvdata(pdev);
        struct csis_state *state = sd_to_csis_state(sd);
@@ -759,7 +808,7 @@ static int s5pcsis_pm_resume(struct device *dev, bool runtime)
                                            state->supplies);
                if (ret)
                        goto unlock;
-               ret = pdata->phy_enable(state->pdev, true);
+               ret = s5p_csis_phy_enable(state->index, true);
                if (!ret) {
                        state->flags |= ST_POWERED;
                } else {
index 1e3b9dd014c094655d7e5b6719c60d06c48d49a8..1bfbc325836b7077b9609da1af8f9958b92d4608 100644 (file)
@@ -507,7 +507,7 @@ static int vidioc_g_crop(struct file *file, void *prv, struct v4l2_crop *cr)
        return 0;
 }
 
-static int vidioc_try_crop(struct file *file, void *prv, struct v4l2_crop *cr)
+static int vidioc_try_crop(struct file *file, void *prv, const struct v4l2_crop *cr)
 {
        struct g2d_ctx *ctx = prv;
        struct g2d_dev *dev = ctx->dev;
index 394775ae5774f4d21d98719c3afae2343b658466..17983c4c9a9aca9a12e63e60853bde15a0f5f6ca 100644 (file)
@@ -1353,7 +1353,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
                return ret;
        }
        dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk);
-       clk_enable(jpeg->clk);
+       clk_prepare_enable(jpeg->clk);
 
        /* v4l2 device */
        ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
@@ -1460,7 +1460,7 @@ device_register_rollback:
        v4l2_device_unregister(&jpeg->v4l2_dev);
 
 clk_get_rollback:
-       clk_disable(jpeg->clk);
+       clk_disable_unprepare(jpeg->clk);
        clk_put(jpeg->clk);
 
        return ret;
@@ -1480,7 +1480,7 @@ static int s5p_jpeg_remove(struct platform_device *pdev)
        v4l2_m2m_release(jpeg->m2m_dev);
        v4l2_device_unregister(&jpeg->v4l2_dev);
 
-       clk_disable(jpeg->clk);
+       clk_disable_unprepare(jpeg->clk);
        clk_put(jpeg->clk);
 
        return 0;
index d0663409af0066d960b37da99a8e902359ffdfac..379008c6d09adfca74f45afda0109b2bb3640768 100644 (file)
@@ -1,5 +1,6 @@
 obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o
-s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o s5p_mfc_opr.o
+s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o
 s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
-s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_cmd.o
-s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_shm.o
+s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_pm.o
+s5p-mfc-y += s5p_mfc_opr.o s5p_mfc_opr_v5.o s5p_mfc_opr_v6.o
+s5p-mfc-y += s5p_mfc_cmd.o s5p_mfc_cmd_v5.o s5p_mfc_cmd_v6.o
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
new file mode 100644 (file)
index 0000000..363a97c
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * Register definition file for Samsung MFC V6.x Interface (FIMV) driver
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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 _REGS_FIMV_V6_H
+#define _REGS_FIMV_V6_H
+
+#include <linux/kernel.h>
+#include <linux/sizes.h>
+
+#define S5P_FIMV_REG_SIZE_V6   (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
+#define S5P_FIMV_REG_COUNT_V6  ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
+
+/* Number of bits that the buffer address should be shifted for particular
+ * MFC buffers.  */
+#define S5P_FIMV_MEM_OFFSET_V6         0
+
+#define S5P_FIMV_START_ADDR_V6         0x0000
+#define S5P_FIMV_END_ADDR_V6           0xfd80
+
+#define S5P_FIMV_REG_CLEAR_BEGIN_V6    0xf000
+#define S5P_FIMV_REG_CLEAR_COUNT_V6    1024
+
+/* Codec Common Registers */
+#define S5P_FIMV_RISC_ON_V6                    0x0000
+#define S5P_FIMV_RISC2HOST_INT_V6              0x003C
+#define S5P_FIMV_HOST2RISC_INT_V6              0x0044
+#define S5P_FIMV_RISC_BASE_ADDRESS_V6          0x0054
+
+#define S5P_FIMV_MFC_RESET_V6                  0x1070
+
+#define S5P_FIMV_HOST2RISC_CMD_V6              0x1100
+#define S5P_FIMV_H2R_CMD_EMPTY_V6              0
+#define S5P_FIMV_H2R_CMD_SYS_INIT_V6           1
+#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6      2
+#define S5P_FIMV_CH_SEQ_HEADER_V6              3
+#define S5P_FIMV_CH_INIT_BUFS_V6               4
+#define S5P_FIMV_CH_FRAME_START_V6             5
+#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6     6
+#define S5P_FIMV_H2R_CMD_SLEEP_V6              7
+#define S5P_FIMV_H2R_CMD_WAKEUP_V6             8
+#define S5P_FIMV_CH_LAST_FRAME_V6              9
+#define S5P_FIMV_H2R_CMD_FLUSH_V6              10
+/* RMVME: REALLOC used? */
+#define S5P_FIMV_CH_FRAME_START_REALLOC_V6     5
+
+#define S5P_FIMV_RISC2HOST_CMD_V6              0x1104
+#define S5P_FIMV_R2H_CMD_EMPTY_V6              0
+#define S5P_FIMV_R2H_CMD_SYS_INIT_RET_V6       1
+#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET_V6  2
+#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET_V6       3
+#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET_V6   4
+
+#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET_V6 6
+#define S5P_FIMV_R2H_CMD_SLEEP_RET_V6          7
+#define S5P_FIMV_R2H_CMD_WAKEUP_RET_V6         8
+#define S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET_V6   9
+#define S5P_FIMV_R2H_CMD_DPB_FLUSH_RET_V6      10
+#define S5P_FIMV_R2H_CMD_NAL_ABORT_RET_V6      11
+#define S5P_FIMV_R2H_CMD_FW_STATUS_RET_V6      12
+#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET_V6     13
+#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET_V6     14
+#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET_V6     15
+#define S5P_FIMV_R2H_CMD_ENC_BUFFER_FUL_RET_V6 16
+#define S5P_FIMV_R2H_CMD_ERR_RET_V6            32
+
+#define S5P_FIMV_FW_VERSION_V6                 0xf000
+
+#define S5P_FIMV_INSTANCE_ID_V6                        0xf008
+#define S5P_FIMV_CODEC_TYPE_V6                 0xf00c
+#define S5P_FIMV_CONTEXT_MEM_ADDR_V6           0xf014
+#define S5P_FIMV_CONTEXT_MEM_SIZE_V6           0xf018
+#define S5P_FIMV_PIXEL_FORMAT_V6               0xf020
+
+#define S5P_FIMV_METADATA_ENABLE_V6            0xf024
+#define S5P_FIMV_DBG_BUFFER_ADDR_V6            0xf030
+#define S5P_FIMV_DBG_BUFFER_SIZE_V6            0xf034
+#define S5P_FIMV_RET_INSTANCE_ID_V6            0xf070
+
+#define S5P_FIMV_ERROR_CODE_V6                 0xf074
+#define S5P_FIMV_ERR_WARNINGS_START_V6         160
+#define S5P_FIMV_ERR_DEC_MASK_V6               0xffff
+#define S5P_FIMV_ERR_DEC_SHIFT_V6              0
+#define S5P_FIMV_ERR_DSPL_MASK_V6              0xffff0000
+#define S5P_FIMV_ERR_DSPL_SHIFT_V6             16
+
+#define S5P_FIMV_DBG_BUFFER_OUTPUT_SIZE_V6     0xf078
+#define S5P_FIMV_METADATA_STATUS_V6            0xf07C
+#define S5P_FIMV_METADATA_ADDR_MB_INFO_V6      0xf080
+#define S5P_FIMV_METADATA_SIZE_MB_INFO_V6      0xf084
+
+/* Decoder Registers */
+#define S5P_FIMV_D_CRC_CTRL_V6                 0xf0b0
+#define S5P_FIMV_D_DEC_OPTIONS_V6              0xf0b4
+#define S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6    4
+#define S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6      3
+#define S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6                1
+#define S5P_FIMV_D_OPT_LF_CTRL_MASK_V6         0x3
+#define S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6      0
+
+#define S5P_FIMV_D_DISPLAY_DELAY_V6            0xf0b8
+
+#define S5P_FIMV_D_SET_FRAME_WIDTH_V6          0xf0bc
+#define S5P_FIMV_D_SET_FRAME_HEIGHT_V6         0xf0c0
+
+#define S5P_FIMV_D_SEI_ENABLE_V6               0xf0c4
+
+/* Buffer setting registers */
+#define S5P_FIMV_D_MIN_NUM_DPB_V6              0xf0f0
+#define S5P_FIMV_D_MIN_LUMA_DPB_SIZE_V6                0xf0f4
+#define S5P_FIMV_D_MIN_CHROMA_DPB_SIZE_V6      0xf0f8
+#define S5P_FIMV_D_MVC_NUM_VIEWS_V6            0xf0fc
+#define S5P_FIMV_D_MIN_NUM_MV_V6               0xf100
+#define S5P_FIMV_D_NUM_DPB_V6                  0xf130
+#define S5P_FIMV_D_LUMA_DPB_SIZE_V6            0xf134
+#define S5P_FIMV_D_CHROMA_DPB_SIZE_V6          0xf138
+#define S5P_FIMV_D_MV_BUFFER_SIZE_V6           0xf13c
+
+#define S5P_FIMV_D_LUMA_DPB_V6                 0xf140
+#define S5P_FIMV_D_CHROMA_DPB_V6               0xf240
+#define S5P_FIMV_D_MV_BUFFER_V6                        0xf340
+
+#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6      0xf440
+#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6      0xf444
+#define S5P_FIMV_D_METADATA_BUFFER_ADDR_V6     0xf448
+#define S5P_FIMV_D_METADATA_BUFFER_SIZE_V6     0xf44c
+#define S5P_FIMV_D_NUM_MV_V6                   0xf478
+#define S5P_FIMV_D_CPB_BUFFER_ADDR_V6          0xf4b0
+#define S5P_FIMV_D_CPB_BUFFER_SIZE_V6          0xf4b4
+
+#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER_V6 0xf4b8
+#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6 0xf4bc
+#define S5P_FIMV_D_CPB_BUFFER_OFFSET_V6                0xf4c0
+#define S5P_FIMV_D_SLICE_IF_ENABLE_V6          0xf4c4
+#define S5P_FIMV_D_PICTURE_TAG_V6              0xf4c8
+#define S5P_FIMV_D_STREAM_DATA_SIZE_V6         0xf4d0
+
+/* Display information register */
+#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6      0xf500
+#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6     0xf504
+
+/* Display status */
+#define S5P_FIMV_D_DISPLAY_STATUS_V6           0xf508
+
+#define S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6                0xf50c
+#define S5P_FIMV_D_DISPLAY_CHROMA_ADDR_V6      0xf510
+
+#define S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6       0xf514
+
+#define S5P_FIMV_D_DISPLAY_CROP_INFO1_V6       0xf518
+#define S5P_FIMV_D_DISPLAY_CROP_INFO2_V6       0xf51c
+#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE_V6  0xf520
+#define S5P_FIMV_D_DISPLAY_LUMA_CRC_TOP_V6     0xf524
+#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_TOP_V6   0xf528
+#define S5P_FIMV_D_DISPLAY_LUMA_CRC_BOT_V6     0xf52c
+#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_BOT_V6   0xf530
+#define S5P_FIMV_D_DISPLAY_ASPECT_RATIO_V6     0xf534
+#define S5P_FIMV_D_DISPLAY_EXTENDED_AR_V6      0xf538
+
+/* Decoded picture information register */
+#define S5P_FIMV_D_DECODED_FRAME_WIDTH_V6      0xf53c
+#define S5P_FIMV_D_DECODED_FRAME_HEIGHT_V6     0xf540
+#define S5P_FIMV_D_DECODED_STATUS_V6           0xf544
+#define S5P_FIMV_DEC_CRC_GEN_MASK_V6           0x1
+#define S5P_FIMV_DEC_CRC_GEN_SHIFT_V6          6
+
+#define S5P_FIMV_D_DECODED_LUMA_ADDR_V6                0xf548
+#define S5P_FIMV_D_DECODED_CHROMA_ADDR_V6      0xf54c
+
+#define S5P_FIMV_D_DECODED_FRAME_TYPE_V6       0xf550
+#define S5P_FIMV_DECODE_FRAME_MASK_V6          7
+
+#define S5P_FIMV_D_DECODED_CROP_INFO1_V6       0xf554
+#define S5P_FIMV_D_DECODED_CROP_INFO2_V6       0xf558
+#define S5P_FIMV_D_DECODED_PICTURE_PROFILE_V6  0xf55c
+#define S5P_FIMV_D_DECODED_NAL_SIZE_V6         0xf560
+#define S5P_FIMV_D_DECODED_LUMA_CRC_TOP_V6     0xf564
+#define S5P_FIMV_D_DECODED_CHROMA_CRC_TOP_V6   0xf568
+#define S5P_FIMV_D_DECODED_LUMA_CRC_BOT_V6     0xf56c
+#define S5P_FIMV_D_DECODED_CHROMA_CRC_BOT_V6   0xf570
+
+/* Returned value register for specific setting */
+#define S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6              0xf574
+#define S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6              0xf578
+#define S5P_FIMV_D_RET_PICTURE_TIME_TOP_V6             0xf57c
+#define S5P_FIMV_D_RET_PICTURE_TIME_BOT_V6             0xf580
+#define S5P_FIMV_D_CHROMA_FORMAT_V6                    0xf588
+#define S5P_FIMV_D_MPEG4_INFO_V6                       0xf58c
+#define S5P_FIMV_D_H264_INFO_V6                                0xf590
+
+#define S5P_FIMV_D_METADATA_ADDR_CONCEALED_MB_V6       0xf594
+#define S5P_FIMV_D_METADATA_SIZE_CONCEALED_MB_V6       0xf598
+#define S5P_FIMV_D_METADATA_ADDR_VC1_PARAM_V6          0xf59c
+#define S5P_FIMV_D_METADATA_SIZE_VC1_PARAM_V6          0xf5a0
+#define S5P_FIMV_D_METADATA_ADDR_SEI_NAL_V6            0xf5a4
+#define S5P_FIMV_D_METADATA_SIZE_SEI_NAL_V6            0xf5a8
+#define S5P_FIMV_D_METADATA_ADDR_VUI_V6                        0xf5ac
+#define S5P_FIMV_D_METADATA_SIZE_VUI_V6                        0xf5b0
+
+#define S5P_FIMV_D_MVC_VIEW_ID_V6              0xf5b4
+
+/* SEI related information */
+#define S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6     0xf5f0
+#define S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID_V6   0xf5f4
+#define S5P_FIMV_D_FRAME_PACK_SEI_INFO_V6      0xf5f8
+#define S5P_FIMV_D_FRAME_PACK_GRID_POS_V6      0xf5fc
+
+/* Encoder Registers */
+#define S5P_FIMV_E_FRAME_WIDTH_V6              0xf770
+#define S5P_FIMV_E_FRAME_HEIGHT_V6             0xf774
+#define S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6      0xf778
+#define S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6     0xf77c
+#define S5P_FIMV_E_FRAME_CROP_OFFSET_V6                0xf780
+#define S5P_FIMV_E_ENC_OPTIONS_V6              0xf784
+#define S5P_FIMV_E_PICTURE_PROFILE_V6          0xf788
+#define S5P_FIMV_E_FIXED_PICTURE_QP_V6         0xf790
+
+#define S5P_FIMV_E_RC_CONFIG_V6                        0xf794
+#define S5P_FIMV_E_RC_QP_BOUND_V6              0xf798
+#define S5P_FIMV_E_RC_RPARAM_V6                        0xf79c
+#define S5P_FIMV_E_MB_RC_CONFIG_V6             0xf7a0
+#define S5P_FIMV_E_PADDING_CTRL_V6             0xf7a4
+#define S5P_FIMV_E_MV_HOR_RANGE_V6             0xf7ac
+#define S5P_FIMV_E_MV_VER_RANGE_V6             0xf7b0
+
+#define S5P_FIMV_E_VBV_BUFFER_SIZE_V6          0xf84c
+#define S5P_FIMV_E_VBV_INIT_DELAY_V6           0xf850
+#define S5P_FIMV_E_NUM_DPB_V6                  0xf890
+#define S5P_FIMV_E_LUMA_DPB_V6                 0xf8c0
+#define S5P_FIMV_E_CHROMA_DPB_V6               0xf904
+#define S5P_FIMV_E_ME_BUFFER_V6                        0xf948
+
+#define S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6      0xf98c
+#define S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6      0xf990
+#define S5P_FIMV_E_TMV_BUFFER0_V6              0xf994
+#define S5P_FIMV_E_TMV_BUFFER1_V6              0xf998
+#define S5P_FIMV_E_SOURCE_LUMA_ADDR_V6         0xf9f0
+#define S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6       0xf9f4
+#define S5P_FIMV_E_STREAM_BUFFER_ADDR_V6       0xf9f8
+#define S5P_FIMV_E_STREAM_BUFFER_SIZE_V6       0xf9fc
+#define S5P_FIMV_E_ROI_BUFFER_ADDR_V6          0xfA00
+
+#define S5P_FIMV_E_PARAM_CHANGE_V6             0xfa04
+#define S5P_FIMV_E_IR_SIZE_V6                  0xfa08
+#define S5P_FIMV_E_GOP_CONFIG_V6               0xfa0c
+#define S5P_FIMV_E_MSLICE_MODE_V6              0xfa10
+#define S5P_FIMV_E_MSLICE_SIZE_MB_V6           0xfa14
+#define S5P_FIMV_E_MSLICE_SIZE_BITS_V6         0xfa18
+#define S5P_FIMV_E_FRAME_INSERTION_V6          0xfa1c
+
+#define S5P_FIMV_E_RC_FRAME_RATE_V6            0xfa20
+#define S5P_FIMV_E_RC_BIT_RATE_V6              0xfa24
+#define S5P_FIMV_E_RC_QP_OFFSET_V6             0xfa28
+#define S5P_FIMV_E_RC_ROI_CTRL_V6              0xfa2c
+#define S5P_FIMV_E_PICTURE_TAG_V6              0xfa30
+#define S5P_FIMV_E_BIT_COUNT_ENABLE_V6         0xfa34
+#define S5P_FIMV_E_MAX_BIT_COUNT_V6            0xfa38
+#define S5P_FIMV_E_MIN_BIT_COUNT_V6            0xfa3c
+
+#define S5P_FIMV_E_METADATA_BUFFER_ADDR_V6             0xfa40
+#define S5P_FIMV_E_METADATA_BUFFER_SIZE_V6             0xfa44
+#define S5P_FIMV_E_STREAM_SIZE_V6                      0xfa80
+#define S5P_FIMV_E_SLICE_TYPE_V6                       0xfa84
+#define S5P_FIMV_E_PICTURE_COUNT_V6                    0xfa88
+#define S5P_FIMV_E_RET_PICTURE_TAG_V6                  0xfa8c
+#define S5P_FIMV_E_STREAM_BUFFER_WRITE_POINTER_V6      0xfa90
+
+#define S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6         0xfa94
+#define S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6       0xfa98
+#define S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6              0xfa9c
+#define S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6            0xfaa0
+#define S5P_FIMV_E_METADATA_ADDR_ENC_SLICE_V6          0xfaa4
+#define S5P_FIMV_E_METADATA_SIZE_ENC_SLICE_V6          0xfaa8
+
+#define S5P_FIMV_E_MPEG4_OPTIONS_V6            0xfb10
+#define S5P_FIMV_E_MPEG4_HEC_PERIOD_V6         0xfb14
+#define S5P_FIMV_E_ASPECT_RATIO_V6             0xfb50
+#define S5P_FIMV_E_EXTENDED_SAR_V6             0xfb54
+
+#define S5P_FIMV_E_H264_OPTIONS_V6             0xfb58
+#define S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6     0xfb5c
+#define S5P_FIMV_E_H264_LF_BETA_OFFSET_V6      0xfb60
+#define S5P_FIMV_E_H264_I_PERIOD_V6            0xfb64
+
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6              0xfb68
+#define S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6            0xfb6c
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6            0xfb70
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6    0xfb74
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6             0xfb78
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_1_V6             0xfb7c
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_2_V6             0xfb80
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_3_V6             0xfb84
+
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6   0xfb88
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_1_V6   0xfb8c
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_2_V6   0xfb90
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_3_V6   0xfb94
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_4_V6   0xfb98
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_5_V6   0xfb9c
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_6_V6   0xfba0
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_7_V6   0xfba4
+
+#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET_V6    0xfba8
+#define S5P_FIMV_E_H264_NUM_T_LAYER_V6         0xfbac
+
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6      0xfbb0
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER1_V6      0xfbb4
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER2_V6      0xfbb8
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER3_V6      0xfbbc
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER4_V6      0xfbc0
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER5_V6      0xfbc4
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER6_V6      0xfbc8
+
+#define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6              0xfc4c
+#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE_V6       0
+#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TOP_BOTTOM_V6         1
+#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TEMPORAL_V6           2
+
+#define S5P_FIMV_E_MVC_FRAME_QP_VIEW1_V6               0xfd40
+#define S5P_FIMV_E_MVC_RC_FRAME_RATE_VIEW1_V6          0xfd44
+#define S5P_FIMV_E_MVC_RC_BIT_RATE_VIEW1_V6            0xfd48
+#define S5P_FIMV_E_MVC_RC_QBOUND_VIEW1_V6              0xfd4c
+#define S5P_FIMV_E_MVC_RC_RPARA_VIEW1_V6               0xfd50
+#define S5P_FIMV_E_MVC_INTER_VIEW_PREDICTION_ON_V6     0xfd80
+
+/* Codec numbers  */
+#define S5P_FIMV_CODEC_NONE_V6         -1
+
+
+#define S5P_FIMV_CODEC_H264_DEC_V6     0
+#define S5P_FIMV_CODEC_H264_MVC_DEC_V6 1
+
+#define S5P_FIMV_CODEC_MPEG4_DEC_V6    3
+#define S5P_FIMV_CODEC_FIMV1_DEC_V6    4
+#define S5P_FIMV_CODEC_FIMV2_DEC_V6    5
+#define S5P_FIMV_CODEC_FIMV3_DEC_V6    6
+#define S5P_FIMV_CODEC_FIMV4_DEC_V6    7
+#define S5P_FIMV_CODEC_H263_DEC_V6     8
+#define S5P_FIMV_CODEC_VC1RCV_DEC_V6   9
+#define S5P_FIMV_CODEC_VC1_DEC_V6      10
+/* FIXME: Add 11~12 */
+#define S5P_FIMV_CODEC_MPEG2_DEC_V6    13
+#define S5P_FIMV_CODEC_VP8_DEC_V6      14
+/* FIXME: Add 15~16 */
+#define S5P_FIMV_CODEC_H264_ENC_V6     20
+#define S5P_FIMV_CODEC_H264_MVC_ENC_V6 21
+
+#define S5P_FIMV_CODEC_MPEG4_ENC_V6    23
+#define S5P_FIMV_CODEC_H263_ENC_V6     24
+
+#define S5P_FIMV_NV12M_HALIGN_V6               16
+#define S5P_FIMV_NV12MT_HALIGN_V6              16
+#define S5P_FIMV_NV12MT_VALIGN_V6              16
+
+#define S5P_FIMV_TMV_BUFFER_ALIGN_V6           16
+#define S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6      256
+#define S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6    256
+#define S5P_FIMV_ME_BUFFER_ALIGN_V6            256
+#define S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6       256
+
+#define S5P_FIMV_LUMA_MB_TO_PIXEL_V6           256
+#define S5P_FIMV_CHROMA_MB_TO_PIXEL_V6         128
+#define S5P_FIMV_NUM_TMV_BUFFERS_V6            2
+
+#define S5P_FIMV_MAX_FRAME_SIZE_V6             (2 * SZ_1M)
+#define S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6       16
+#define S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6       16
+
+/* Buffer size requirements defined by hardware */
+#define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h)      (((w) + 1) * ((h) + 1) * 8)
+#define S5P_FIMV_ME_BUFFER_SIZE_V6(imw, imh, mbw, mbh) \
+       ((DIV_ROUND_UP(imw, 64) *  DIV_ROUND_UP(imh, 64) * 256) + \
+        (DIV_ROUND_UP((mbw) * (mbh), 32) * 16))
+#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(w, h)    (((w) * 192) + 64)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h) \
+                       ((w) * ((h) * 64 + 144) + (2048/16 * (h) * 64) + \
+                        (2048/16 * 256 + 8320))
+#define S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(w, h) \
+                                               (2096 * ((w) + (h) + 1))
+#define S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(w, h)    ((w) * 400)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6(w, h) \
+                       ((w) * 32 + (h) * 128 + (((w) + 1) / 2) * 64 + 2112)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6(w, h) \
+                       (((w) * 64) + (((w) + 1) * 16) + (4096 * 16))
+#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(w, h) \
+                       (((w) * 16) + (((w) + 1) * 16))
+
+/* MFC Context buffer sizes */
+#define MFC_CTX_BUF_SIZE_V6            (28 * SZ_1K)    /*  28KB */
+#define MFC_H264_DEC_CTX_BUF_SIZE_V6   (2 * SZ_1M)     /*  2MB */
+#define MFC_OTHER_DEC_CTX_BUF_SIZE_V6  (20 * SZ_1K)    /*  20KB */
+#define MFC_H264_ENC_CTX_BUF_SIZE_V6   (100 * SZ_1K)   /* 100KB */
+#define MFC_OTHER_ENC_CTX_BUF_SIZE_V6  (12 * SZ_1K)    /*  12KB */
+
+/* MFCv6 variant defines */
+#define MAX_FW_SIZE_V6                 (SZ_1M)         /* 1MB */
+#define MAX_CPB_SIZE_V6                        (3 * SZ_1M)     /* 3MB */
+#define MFC_VERSION_V6                 0x61
+#define MFC_NUM_PORTS_V6               1
+
+#endif /* _REGS_FIMV_V6_H */
index a19bece41ba9d0c4a53845943c8219e27659382b..9319e93599ae5731241b58535583bc1a04b77e73 100644 (file)
@@ -12,6 +12,9 @@
 #ifndef _REGS_FIMV_H
 #define _REGS_FIMV_H
 
+#include <linux/kernel.h>
+#include <linux/sizes.h>
+
 #define S5P_FIMV_REG_SIZE      (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
 #define S5P_FIMV_REG_COUNT     ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
 
 #define S5P_FIMV_ENC_PROFILE_H264_MAIN                 0
 #define S5P_FIMV_ENC_PROFILE_H264_HIGH                 1
 #define S5P_FIMV_ENC_PROFILE_H264_BASELINE             2
+#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE 3
 #define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE              0
 #define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE     1
 #define S5P_FIMV_ENC_PIC_STRUCT                0x083c /* picture field/frame flag */
 #define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK            (3<<4)
 #define S5P_FIMV_DEC_STATUS_RESOLUTION_INC             (1<<4)
 #define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC             (2<<4)
+#define S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT           4
 
 /* Decode frame address */
 #define S5P_FIMV_DECODE_Y_ADR                  0x2024
 #define S5P_FIMV_R2H_CMD_EDFU_INIT_RET         16
 #define S5P_FIMV_R2H_CMD_ERR_RET               32
 
+/* Dummy definition for MFCv6 compatibilty */
+#define S5P_FIMV_CODEC_H264_MVC_DEC            -1
+#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET                -1
+#define S5P_FIMV_MFC_RESET                     -1
+#define S5P_FIMV_RISC_ON                       -1
+#define S5P_FIMV_RISC_BASE_ADDRESS             -1
+#define S5P_FIMV_CODEC_VP8_DEC                 -1
+#define S5P_FIMV_REG_CLEAR_BEGIN               0
+#define S5P_FIMV_REG_CLEAR_COUNT               0
+
 /* Error handling defines */
 #define S5P_FIMV_ERR_WARNINGS_START            145
 #define S5P_FIMV_ERR_DEC_MASK                  0xFFFF
 #define S5P_FIMV_SHARED_EXTENDED_SAR           0x0078
 #define S5P_FIMV_SHARED_H264_I_PERIOD          0x009C
 #define S5P_FIMV_SHARED_RC_CONTROL_CONFIG      0x00A0
+#define S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT  2
+
+/* Offset used by the hardware to store addresses */
+#define MFC_OFFSET_SHIFT       11
+
+#define FIRMWARE_ALIGN         (128 * SZ_1K)   /* 128KB */
+#define MFC_H264_CTX_BUF_SIZE  (600 * SZ_1K)   /* 600KB per H264 instance */
+#define MFC_CTX_BUF_SIZE       (10 * SZ_1K)    /* 10KB per instance */
+#define DESC_BUF_SIZE          (128 * SZ_1K)   /* 128KB for DESC buffer */
+#define SHARED_BUF_SIZE                (8 * SZ_1K)     /* 8KB for shared buffer */
+
+#define DEF_CPB_SIZE           (256 * SZ_1K)   /* 256KB */
+#define MAX_CPB_SIZE           (4 * SZ_1M)     /* 4MB */
+#define MAX_FW_SIZE            (384 * SZ_1K)
+
+#define MFC_VERSION            0x51
+#define MFC_NUM_PORTS          2
+
+#define S5P_FIMV_SHARED_FRAME_PACK_SEI_AVAIL    0x16C
+#define S5P_FIMV_SHARED_FRAME_PACK_ARRGMENT_ID  0x170
+#define S5P_FIMV_SHARED_FRAME_PACK_SEI_INFO     0x174
+#define S5P_FIMV_SHARED_FRAME_PACK_GRID_POS     0x178
+
+/* Values for resolution change in display status */
+#define S5P_FIMV_RES_INCREASE  1
+#define S5P_FIMV_RES_DECREASE  2
 
 #endif /* _REGS_FIMV_H */
index 5587ef15ca4fa3d34a3db0e7fe70039ccbc62fc7..130f4ac8649ec644faf589e734145761f5d7cc91 100644 (file)
 #include <media/v4l2-event.h>
 #include <linux/workqueue.h>
 #include <media/videobuf2-core.h>
-#include "regs-mfc.h"
+#include "s5p_mfc_common.h"
 #include "s5p_mfc_ctrl.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_dec.h"
 #include "s5p_mfc_enc.h"
 #include "s5p_mfc_intr.h"
 #include "s5p_mfc_opr.h"
+#include "s5p_mfc_cmd.h"
 #include "s5p_mfc_pm.h"
-#include "s5p_mfc_shm.h"
 
 #define S5P_MFC_NAME           "s5p-mfc"
 #define S5P_MFC_DEC_NAME       "s5p-mfc-dec"
@@ -149,10 +149,12 @@ static void s5p_mfc_watchdog_worker(struct work_struct *work)
                if (!ctx)
                        continue;
                ctx->state = MFCINST_ERROR;
-               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
-               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
+                               &ctx->vq_dst);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
+                               &ctx->vq_src);
                clear_work_bit(ctx);
-               wake_up_ctx(ctx, S5P_FIMV_R2H_CMD_ERR_RET, 0);
+               wake_up_ctx(ctx, S5P_MFC_R2H_CMD_ERR_RET, 0);
        }
        clear_bit(0, &dev->hw_lock);
        spin_unlock_irqrestore(&dev->irqlock, flags);
@@ -199,6 +201,7 @@ static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
 static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
 {
        struct s5p_mfc_buf *dst_buf;
+       struct s5p_mfc_dev *dev = ctx->dev;
 
        ctx->state = MFCINST_FINISHED;
        ctx->sequence++;
@@ -213,8 +216,8 @@ static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
                ctx->dst_queue_cnt--;
                dst_buf->b->v4l2_buf.sequence = (ctx->sequence++);
 
-               if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
-                       s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
+               if (s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_top, ctx) ==
+                       s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_bot, ctx))
                        dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
                else
                        dst_buf->b->v4l2_buf.field = V4L2_FIELD_INTERLACED;
@@ -228,8 +231,11 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
 {
        struct s5p_mfc_dev *dev = ctx->dev;
        struct s5p_mfc_buf  *dst_buf, *src_buf;
-       size_t dec_y_addr = s5p_mfc_get_dec_y_adr();
-       unsigned int frame_type = s5p_mfc_get_frame_type();
+       size_t dec_y_addr;
+       unsigned int frame_type;
+
+       dec_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dec_y_adr, dev);
+       frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
 
        /* Copy timestamp / timecode from decoded src to dst and set
           appropraite flags */
@@ -265,10 +271,13 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
 {
        struct s5p_mfc_dev *dev = ctx->dev;
        struct s5p_mfc_buf  *dst_buf;
-       size_t dspl_y_addr = s5p_mfc_get_dspl_y_adr();
-       unsigned int frame_type = s5p_mfc_get_frame_type();
+       size_t dspl_y_addr;
+       unsigned int frame_type;
        unsigned int index;
 
+       dspl_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev);
+       frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
+
        /* If frame is same as previous then skip and do not dequeue */
        if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) {
                if (!ctx->after_packed_pb)
@@ -285,8 +294,10 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
                        list_del(&dst_buf->list);
                        ctx->dst_queue_cnt--;
                        dst_buf->b->v4l2_buf.sequence = ctx->sequence;
-                       if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
-                               s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
+                       if (s5p_mfc_hw_call(dev->mfc_ops,
+                                       get_pic_type_top, ctx) ==
+                               s5p_mfc_hw_call(dev->mfc_ops,
+                                       get_pic_type_bot, ctx))
                                dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
                        else
                                dst_buf->b->v4l2_buf.field =
@@ -317,21 +328,23 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
 
        unsigned int index;
 
-       dst_frame_status = s5p_mfc_get_dspl_status()
+       dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
                                & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
-       res_change = s5p_mfc_get_dspl_status()
-                               & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK;
+       res_change = (s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
+                               & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK)
+                               >> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT;
        mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
        if (ctx->state == MFCINST_RES_CHANGE_INIT)
                ctx->state = MFCINST_RES_CHANGE_FLUSH;
-       if (res_change) {
+       if (res_change == S5P_FIMV_RES_INCREASE ||
+               res_change == S5P_FIMV_RES_DECREASE) {
                ctx->state = MFCINST_RES_CHANGE_INIT;
-               s5p_mfc_clear_int_flags(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
                wake_up_ctx(ctx, reason, err);
                if (test_and_clear_bit(0, &dev->hw_lock) == 0)
                        BUG();
                s5p_mfc_clock_off();
-               s5p_mfc_try_run(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
                return;
        }
        if (ctx->dpb_flush_flag)
@@ -365,9 +378,12 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
                && !list_empty(&ctx->src_queue)) {
                src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
                                                                list);
-               ctx->consumed_stream += s5p_mfc_get_consumed_stream();
-               if (ctx->codec_mode != S5P_FIMV_CODEC_H264_DEC &&
-                       s5p_mfc_get_frame_type() == S5P_FIMV_DECODE_FRAME_P_FRAME
+               ctx->consumed_stream += s5p_mfc_hw_call(dev->mfc_ops,
+                                               get_consumed_stream, dev);
+               if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC &&
+                       s5p_mfc_hw_call(dev->mfc_ops,
+                               get_dec_frame_type, dev) ==
+                                       S5P_FIMV_DECODE_FRAME_P_FRAME
                                        && ctx->consumed_stream + STUFF_BYTE <
                                        src_buf->b->v4l2_planes[0].bytesused) {
                        /* Run MFC again on the same buffer */
@@ -379,7 +395,7 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
                        ctx->consumed_stream = 0;
                        list_del(&src_buf->list);
                        ctx->src_queue_cnt--;
-                       if (s5p_mfc_err_dec(err) > 0)
+                       if (s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) > 0)
                                vb2_buffer_done(src_buf->b, VB2_BUF_STATE_ERROR);
                        else
                                vb2_buffer_done(src_buf->b, VB2_BUF_STATE_DONE);
@@ -390,12 +406,12 @@ leave_handle_frame:
        if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING)
                                    || ctx->dst_queue_cnt < ctx->dpb_count)
                clear_work_bit(ctx);
-       s5p_mfc_clear_int_flags(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
        wake_up_ctx(ctx, reason, err);
        if (test_and_clear_bit(0, &dev->hw_lock) == 0)
                BUG();
        s5p_mfc_clock_off();
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
 }
 
 /* Error handling for interrupt */
@@ -412,7 +428,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx,
 
        dev = ctx->dev;
        mfc_err("Interrupt Error: %08x\n", err);
-       s5p_mfc_clear_int_flags(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
        wake_up_dev(dev, reason, err);
 
        /* Error recovery is dependent on the state of context */
@@ -441,9 +457,11 @@ static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx,
                ctx->state = MFCINST_ERROR;
                /* Mark all dst buffers as having an error */
                spin_lock_irqsave(&dev->irqlock, flags);
-               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
+                               &ctx->vq_dst);
                /* Mark all src buffers as having an error */
-               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
+                               &ctx->vq_src);
                spin_unlock_irqrestore(&dev->irqlock, flags);
                if (test_and_clear_bit(0, &dev->hw_lock) == 0)
                        BUG();
@@ -461,7 +479,6 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
                                 unsigned int reason, unsigned int err)
 {
        struct s5p_mfc_dev *dev;
-       unsigned int guard_width, guard_height;
 
        if (ctx == NULL)
                return;
@@ -470,55 +487,44 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
                if (ctx->c_ops->post_seq_start(ctx))
                        mfc_err("post_seq_start() failed\n");
        } else {
-               ctx->img_width = s5p_mfc_get_img_width();
-               ctx->img_height = s5p_mfc_get_img_height();
-
-               ctx->buf_width = ALIGN(ctx->img_width,
-                                               S5P_FIMV_NV12MT_HALIGN);
-               ctx->buf_height = ALIGN(ctx->img_height,
-                                               S5P_FIMV_NV12MT_VALIGN);
-               mfc_debug(2, "SEQ Done: Movie dimensions %dx%d, "
-                       "buffer dimensions: %dx%d\n", ctx->img_width,
-                               ctx->img_height, ctx->buf_width,
-                                               ctx->buf_height);
-               if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
-                       ctx->luma_size = ALIGN(ctx->buf_width *
-                               ctx->buf_height, S5P_FIMV_DEC_BUF_ALIGN);
-                       ctx->chroma_size = ALIGN(ctx->buf_width *
-                                        ALIGN((ctx->img_height >> 1),
-                                              S5P_FIMV_NV12MT_VALIGN),
-                                              S5P_FIMV_DEC_BUF_ALIGN);
-                       ctx->mv_size = ALIGN(ctx->buf_width *
-                                       ALIGN((ctx->buf_height >> 2),
-                                       S5P_FIMV_NV12MT_VALIGN),
-                                       S5P_FIMV_DEC_BUF_ALIGN);
-               } else {
-                       guard_width = ALIGN(ctx->img_width + 24,
-                                       S5P_FIMV_NV12MT_HALIGN);
-                       guard_height = ALIGN(ctx->img_height + 16,
-                                               S5P_FIMV_NV12MT_VALIGN);
-                       ctx->luma_size = ALIGN(guard_width *
-                               guard_height, S5P_FIMV_DEC_BUF_ALIGN);
-                       guard_width = ALIGN(ctx->img_width + 16,
-                                               S5P_FIMV_NV12MT_HALIGN);
-                       guard_height = ALIGN((ctx->img_height >> 1) + 4,
-                                               S5P_FIMV_NV12MT_VALIGN);
-                       ctx->chroma_size = ALIGN(guard_width *
-                               guard_height, S5P_FIMV_DEC_BUF_ALIGN);
-                       ctx->mv_size = 0;
-               }
-               ctx->dpb_count = s5p_mfc_get_dpb_count();
+               ctx->img_width = s5p_mfc_hw_call(dev->mfc_ops, get_img_width,
+                               dev);
+               ctx->img_height = s5p_mfc_hw_call(dev->mfc_ops, get_img_height,
+                               dev);
+
+               s5p_mfc_hw_call(dev->mfc_ops, dec_calc_dpb_size, ctx);
+
+               ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count,
+                               dev);
+               ctx->mv_count = s5p_mfc_hw_call(dev->mfc_ops, get_mv_count,
+                               dev);
                if (ctx->img_width == 0 || ctx->img_height == 0)
                        ctx->state = MFCINST_ERROR;
                else
                        ctx->state = MFCINST_HEAD_PARSED;
+
+               if ((ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+                       ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) &&
+                               !list_empty(&ctx->src_queue)) {
+                       struct s5p_mfc_buf *src_buf;
+                       src_buf = list_entry(ctx->src_queue.next,
+                                       struct s5p_mfc_buf, list);
+                       if (s5p_mfc_hw_call(dev->mfc_ops, get_consumed_stream,
+                                               dev) <
+                                       src_buf->b->v4l2_planes[0].bytesused)
+                               ctx->head_processed = 0;
+                       else
+                               ctx->head_processed = 1;
+               } else {
+                       ctx->head_processed = 1;
+               }
        }
-       s5p_mfc_clear_int_flags(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
        clear_work_bit(ctx);
        if (test_and_clear_bit(0, &dev->hw_lock) == 0)
                BUG();
        s5p_mfc_clock_off();
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
        wake_up_ctx(ctx, reason, err);
 }
 
@@ -533,14 +539,14 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
        if (ctx == NULL)
                return;
        dev = ctx->dev;
-       s5p_mfc_clear_int_flags(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
        ctx->int_type = reason;
        ctx->int_err = err;
        ctx->int_cond = 1;
        clear_work_bit(ctx);
        if (err == 0) {
                ctx->state = MFCINST_RUNNING;
-               if (!ctx->dpb_flush_flag) {
+               if (!ctx->dpb_flush_flag && ctx->head_processed) {
                        spin_lock_irqsave(&dev->irqlock, flags);
                        if (!list_empty(&ctx->src_queue)) {
                                src_buf = list_entry(ctx->src_queue.next,
@@ -560,7 +566,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
                s5p_mfc_clock_off();
 
                wake_up(&ctx->queue);
-               s5p_mfc_try_run(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
        } else {
                if (test_and_clear_bit(0, &dev->hw_lock) == 0)
                        BUG();
@@ -602,7 +608,7 @@ static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx,
 
        s5p_mfc_clock_off();
        wake_up(&ctx->queue);
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
 }
 
 /* Interrupt processing */
@@ -618,81 +624,83 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
        atomic_set(&dev->watchdog_cnt, 0);
        ctx = dev->ctx[dev->curr_ctx];
        /* Get the reason of interrupt and the error code */
-       reason = s5p_mfc_get_int_reason();
-       err = s5p_mfc_get_int_err();
+       reason = s5p_mfc_hw_call(dev->mfc_ops, get_int_reason, dev);
+       err = s5p_mfc_hw_call(dev->mfc_ops, get_int_err, dev);
        mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err);
        switch (reason) {
-       case S5P_FIMV_R2H_CMD_ERR_RET:
+       case S5P_MFC_R2H_CMD_ERR_RET:
                /* An error has occured */
                if (ctx->state == MFCINST_RUNNING &&
-                       s5p_mfc_err_dec(err) >= S5P_FIMV_ERR_WARNINGS_START)
+                       s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >=
+                               dev->warn_start)
                        s5p_mfc_handle_frame(ctx, reason, err);
                else
                        s5p_mfc_handle_error(ctx, reason, err);
                clear_bit(0, &dev->enter_suspend);
                break;
 
-       case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
-       case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
+       case S5P_MFC_R2H_CMD_SLICE_DONE_RET:
+       case S5P_MFC_R2H_CMD_FIELD_DONE_RET:
+       case S5P_MFC_R2H_CMD_FRAME_DONE_RET:
                if (ctx->c_ops->post_frame_start) {
                        if (ctx->c_ops->post_frame_start(ctx))
                                mfc_err("post_frame_start() failed\n");
-                       s5p_mfc_clear_int_flags(dev);
+                       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
                        wake_up_ctx(ctx, reason, err);
                        if (test_and_clear_bit(0, &dev->hw_lock) == 0)
                                BUG();
                        s5p_mfc_clock_off();
-                       s5p_mfc_try_run(dev);
+                       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
                } else {
                        s5p_mfc_handle_frame(ctx, reason, err);
                }
                break;
 
-       case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
+       case S5P_MFC_R2H_CMD_SEQ_DONE_RET:
                s5p_mfc_handle_seq_done(ctx, reason, err);
                break;
 
-       case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
-               ctx->inst_no = s5p_mfc_get_inst_no();
+       case S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET:
+               ctx->inst_no = s5p_mfc_hw_call(dev->mfc_ops, get_inst_no, dev);
                ctx->state = MFCINST_GOT_INST;
                clear_work_bit(ctx);
                wake_up(&ctx->queue);
                goto irq_cleanup_hw;
 
-       case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
+       case S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET:
                clear_work_bit(ctx);
                ctx->state = MFCINST_FREE;
                wake_up(&ctx->queue);
                goto irq_cleanup_hw;
 
-       case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
-       case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
-       case S5P_FIMV_R2H_CMD_SLEEP_RET:
-       case S5P_FIMV_R2H_CMD_WAKEUP_RET:
+       case S5P_MFC_R2H_CMD_SYS_INIT_RET:
+       case S5P_MFC_R2H_CMD_FW_STATUS_RET:
+       case S5P_MFC_R2H_CMD_SLEEP_RET:
+       case S5P_MFC_R2H_CMD_WAKEUP_RET:
                if (ctx)
                        clear_work_bit(ctx);
-               s5p_mfc_clear_int_flags(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
                wake_up_dev(dev, reason, err);
                clear_bit(0, &dev->hw_lock);
                clear_bit(0, &dev->enter_suspend);
                break;
 
-       case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
+       case S5P_MFC_R2H_CMD_INIT_BUFFERS_RET:
                s5p_mfc_handle_init_buffers(ctx, reason, err);
                break;
 
-       case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET:
+       case S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET:
                s5p_mfc_handle_stream_complete(ctx, reason, err);
                break;
 
        default:
                mfc_debug(2, "Unknown int reason\n");
-               s5p_mfc_clear_int_flags(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
        }
        mfc_debug_leave();
        return IRQ_HANDLED;
 irq_cleanup_hw:
-       s5p_mfc_clear_int_flags(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
        ctx->int_type = reason;
        ctx->int_err = err;
        ctx->int_cond = 1;
@@ -701,7 +709,7 @@ irq_cleanup_hw:
 
        s5p_mfc_clock_off();
 
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
        mfc_debug(2, "Exit via irq_cleanup_hw\n");
        return IRQ_HANDLED;
 }
@@ -749,6 +757,7 @@ static int s5p_mfc_open(struct file *file)
        if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) {
                ctx->type = MFCINST_DECODER;
                ctx->c_ops = get_dec_codec_ops();
+               s5p_mfc_dec_init(ctx);
                /* Setup ctrl handler */
                ret = s5p_mfc_dec_ctrls_setup(ctx);
                if (ret) {
@@ -761,6 +770,7 @@ static int s5p_mfc_open(struct file *file)
                /* only for encoder */
                INIT_LIST_HEAD(&ctx->ref_queue);
                ctx->ref_queue_cnt = 0;
+               s5p_mfc_enc_init(ctx);
                /* Setup ctrl handler */
                ret = s5p_mfc_enc_ctrls_setup(ctx);
                if (ret) {
@@ -886,19 +896,20 @@ static int s5p_mfc_release(struct file *file)
                ctx->state = MFCINST_RETURN_INST;
                set_work_bit_irqsave(ctx);
                s5p_mfc_clean_ctx_int_flags(ctx);
-               s5p_mfc_try_run(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
                /* Wait until instance is returned or timeout occured */
                if (s5p_mfc_wait_for_done_ctx
-                   (ctx, S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET, 0)) {
+                   (ctx, S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) {
                        s5p_mfc_clock_off();
                        mfc_err("Err returning instance\n");
                }
                mfc_debug(2, "After free instance\n");
                /* Free resources */
-               s5p_mfc_release_codec_buffers(ctx);
-               s5p_mfc_release_instance_buffer(ctx);
+               s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx);
+               s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx);
                if (ctx->type == MFCINST_DECODER)
-                       s5p_mfc_release_dec_desc_buffer(ctx);
+                       s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer,
+                                       ctx);
 
                ctx->inst_no = MFC_NO_INSTANCE_SET;
        }
@@ -910,6 +921,7 @@ static int s5p_mfc_release(struct file *file)
                mfc_debug(2, "Last instance - release firmware\n");
                /* reset <-> F/W release */
                s5p_mfc_reset(dev);
+               s5p_mfc_deinit_hw(dev);
                s5p_mfc_release_firmware(dev);
                del_timer_sync(&dev->watchdog_timer);
                if (s5p_mfc_power_off() < 0)
@@ -1041,6 +1053,9 @@ static int s5p_mfc_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       dev->variant = (struct s5p_mfc_variant *)
+               platform_get_device_id(pdev)->driver_data;
+
        ret = s5p_mfc_init_pm(dev);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to get mfc clock source\n");
@@ -1076,6 +1091,7 @@ static int s5p_mfc_probe(struct platform_device *pdev)
                ret = -ENODEV;
                goto err_res;
        }
+
        dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, "s5p-mfc-r",
                                           match_child);
        if (!dev->mem_dev_r) {
@@ -1139,6 +1155,7 @@ static int s5p_mfc_probe(struct platform_device *pdev)
        vfd->release    = video_device_release,
        vfd->lock       = &dev->mfc_mutex;
        vfd->v4l2_dev   = &dev->v4l2_dev;
+       vfd->vfl_dir    = VFL_DIR_M2M;
        snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME);
        dev->vfd_enc    = vfd;
        ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
@@ -1160,6 +1177,10 @@ static int s5p_mfc_probe(struct platform_device *pdev)
        dev->watchdog_timer.data = (unsigned long)dev;
        dev->watchdog_timer.function = s5p_mfc_watchdog;
 
+       /* Initialize HW ops and commands based on MFC version */
+       s5p_mfc_init_hw_ops(dev);
+       s5p_mfc_init_hw_cmds(dev);
+
        pr_debug("%s--\n", __func__);
        return 0;
 
@@ -1280,9 +1301,78 @@ static const struct dev_pm_ops s5p_mfc_pm_ops = {
                           NULL)
 };
 
+struct s5p_mfc_buf_size_v5 mfc_buf_size_v5 = {
+       .h264_ctx       = MFC_H264_CTX_BUF_SIZE,
+       .non_h264_ctx   = MFC_CTX_BUF_SIZE,
+       .dsc            = DESC_BUF_SIZE,
+       .shm            = SHARED_BUF_SIZE,
+};
+
+struct s5p_mfc_buf_size buf_size_v5 = {
+       .fw     = MAX_FW_SIZE,
+       .cpb    = MAX_CPB_SIZE,
+       .priv   = &mfc_buf_size_v5,
+};
+
+struct s5p_mfc_buf_align mfc_buf_align_v5 = {
+       .base = MFC_BASE_ALIGN_ORDER,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v5 = {
+       .version        = MFC_VERSION,
+       .port_num       = MFC_NUM_PORTS,
+       .buf_size       = &buf_size_v5,
+       .buf_align      = &mfc_buf_align_v5,
+       .mclk_name      = "sclk_mfc",
+       .fw_name        = "s5p-mfc.fw",
+};
+
+struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = {
+       .dev_ctx        = MFC_CTX_BUF_SIZE_V6,
+       .h264_dec_ctx   = MFC_H264_DEC_CTX_BUF_SIZE_V6,
+       .other_dec_ctx  = MFC_OTHER_DEC_CTX_BUF_SIZE_V6,
+       .h264_enc_ctx   = MFC_H264_ENC_CTX_BUF_SIZE_V6,
+       .other_enc_ctx  = MFC_OTHER_ENC_CTX_BUF_SIZE_V6,
+};
+
+struct s5p_mfc_buf_size buf_size_v6 = {
+       .fw     = MAX_FW_SIZE_V6,
+       .cpb    = MAX_CPB_SIZE_V6,
+       .priv   = &mfc_buf_size_v6,
+};
+
+struct s5p_mfc_buf_align mfc_buf_align_v6 = {
+       .base = 0,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v6 = {
+       .version        = MFC_VERSION_V6,
+       .port_num       = MFC_NUM_PORTS_V6,
+       .buf_size       = &buf_size_v6,
+       .buf_align      = &mfc_buf_align_v6,
+       .mclk_name      = "aclk_333",
+       .fw_name        = "s5p-mfc-v6.fw",
+};
+
+static struct platform_device_id mfc_driver_ids[] = {
+       {
+               .name = "s5p-mfc",
+               .driver_data = (unsigned long)&mfc_drvdata_v5,
+       }, {
+               .name = "s5p-mfc-v5",
+               .driver_data = (unsigned long)&mfc_drvdata_v5,
+       }, {
+               .name = "s5p-mfc-v6",
+               .driver_data = (unsigned long)&mfc_drvdata_v6,
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(platform, mfc_driver_ids);
+
 static struct platform_driver s5p_mfc_driver = {
-       .probe  = s5p_mfc_probe,
-       .remove = __devexit_p(s5p_mfc_remove),
+       .probe          = s5p_mfc_probe,
+       .remove         = __devexit_p(s5p_mfc_remove),
+       .id_table       = mfc_driver_ids,
        .driver = {
                .name   = S5P_MFC_NAME,
                .owner  = THIS_MODULE,
index 91a415573bd2a1a19233ef05429c7d632b7f2942..f0a41c95df84722b89b485e371668e5ba9a40743 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
  *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
  *
  * This program is free software; you can redistribute it and/or modify
  * (at your option) any later version.
  */
 
-#include "regs-mfc.h"
 #include "s5p_mfc_cmd.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
+#include "s5p_mfc_cmd_v5.h"
+#include "s5p_mfc_cmd_v6.h"
 
-/* This function is used to send a command to the MFC */
-static int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
-                                               struct s5p_mfc_cmd_args *args)
-{
-       int cur_cmd;
-       unsigned long timeout;
-
-       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
-       /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
-       do {
-               if (time_after(jiffies, timeout)) {
-                       mfc_err("Timeout while waiting for hardware\n");
-                       return -EIO;
-               }
-               cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
-       } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
-       mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
-       mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
-       mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
-       mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
-       /* Issue the command */
-       mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
-       return 0;
-}
-
-/* Initialize the MFC */
-int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_cmd_args h2r_args;
-
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       h2r_args.arg[0] = dev->fw_size;
-       return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args);
-}
-
-/* Suspend the MFC hardware */
-int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_cmd_args h2r_args;
-
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
-}
+static struct s5p_mfc_hw_cmds *s5p_mfc_cmds;
 
-/* Wake up the MFC hardware */
-int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev)
+void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev)
 {
-       struct s5p_mfc_cmd_args h2r_args;
+       if (IS_MFCV6(dev))
+               s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6();
+       else
+               s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5();
 
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_WAKEUP, &h2r_args);
+       dev->mfc_cmds = s5p_mfc_cmds;
 }
-
-
-int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_cmd_args h2r_args;
-       int ret;
-
-       /* Preparing decoding - getting instance number */
-       mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode);
-       dev->curr_ctx = ctx->num;
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       h2r_args.arg[0] = ctx->codec_mode;
-       h2r_args.arg[1] = 0; /* no crc & no pixelcache */
-       h2r_args.arg[2] = ctx->ctx_ofs;
-       h2r_args.arg[3] = ctx->ctx_size;
-       ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
-                                                               &h2r_args);
-       if (ret) {
-               mfc_err("Failed to create a new instance\n");
-               ctx->state = MFCINST_ERROR;
-       }
-       return ret;
-}
-
-int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_cmd_args h2r_args;
-       int ret;
-
-       if (ctx->state == MFCINST_FREE) {
-               mfc_err("Instance already returned\n");
-               ctx->state = MFCINST_ERROR;
-               return -EINVAL;
-       }
-       /* Closing decoding instance  */
-       mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
-       dev->curr_ctx = ctx->num;
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       h2r_args.arg[0] = ctx->inst_no;
-       ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
-                                                               &h2r_args);
-       if (ret) {
-               mfc_err("Failed to return an instance\n");
-               ctx->state = MFCINST_ERROR;
-               return -EINVAL;
-       }
-       return 0;
-}
-
index 8b090d3723e7d5f8fd2f84a1373c91e4b59379ea..282e6c780702730f1aabb057b779872334dd7efa 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
  *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
  *
  * This program is free software; you can redistribute it and/or modify
@@ -21,10 +21,15 @@ struct s5p_mfc_cmd_args {
        unsigned int    arg[MAX_H2R_ARG];
 };
 
-int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev);
-int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev);
-int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev);
-int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx);
+struct s5p_mfc_hw_cmds {
+       int (*cmd_host2risc)(struct s5p_mfc_dev *dev, int cmd,
+                               struct s5p_mfc_cmd_args *args);
+       int (*sys_init_cmd)(struct s5p_mfc_dev *dev);
+       int (*sleep_cmd)(struct s5p_mfc_dev *dev);
+       int (*wakeup_cmd)(struct s5p_mfc_dev *dev);
+       int (*open_inst_cmd)(struct s5p_mfc_ctx *ctx);
+       int (*close_inst_cmd)(struct s5p_mfc_ctx *ctx);
+};
 
+void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev);
 #endif /* S5P_MFC_CMD_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
new file mode 100644 (file)
index 0000000..1387780
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.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.
+ */
+
+#include "regs-mfc.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_debug.h"
+
+/* This function is used to send a command to the MFC */
+int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd,
+                               struct s5p_mfc_cmd_args *args)
+{
+       int cur_cmd;
+       unsigned long timeout;
+
+       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+       /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
+       do {
+               if (time_after(jiffies, timeout)) {
+                       mfc_err("Timeout while waiting for hardware\n");
+                       return -EIO;
+               }
+               cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
+       } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
+       mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
+       mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
+       mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
+       mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
+       /* Issue the command */
+       mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
+       return 0;
+}
+
+/* Initialize the MFC */
+int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       h2r_args.arg[0] = dev->fw_size;
+       return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SYS_INIT,
+                       &h2r_args);
+}
+
+/* Suspend the MFC hardware */
+int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
+}
+
+/* Wake up the MFC hardware */
+int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_WAKEUP,
+                       &h2r_args);
+}
+
+
+int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_cmd_args h2r_args;
+       int ret;
+
+       /* Preparing decoding - getting instance number */
+       mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode);
+       dev->curr_ctx = ctx->num;
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_H264_DEC;
+               break;
+       case S5P_MFC_CODEC_VC1_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_VC1_DEC;
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_DEC;
+               break;
+       case S5P_MFC_CODEC_MPEG2_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG2_DEC;
+               break;
+       case S5P_MFC_CODEC_H263_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_H263_DEC;
+               break;
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_VC1RCV_DEC;
+               break;
+       case S5P_MFC_CODEC_H264_ENC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_H264_ENC;
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_ENC;
+               break;
+       case S5P_MFC_CODEC_H263_ENC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_H263_ENC;
+               break;
+       default:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_NONE;
+       };
+       h2r_args.arg[1] = 0; /* no crc & no pixelcache */
+       h2r_args.arg[2] = ctx->ctx.ofs;
+       h2r_args.arg[3] = ctx->ctx.size;
+       ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
+                                                               &h2r_args);
+       if (ret) {
+               mfc_err("Failed to create a new instance\n");
+               ctx->state = MFCINST_ERROR;
+       }
+       return ret;
+}
+
+int s5p_mfc_close_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_cmd_args h2r_args;
+       int ret;
+
+       if (ctx->state == MFCINST_FREE) {
+               mfc_err("Instance already returned\n");
+               ctx->state = MFCINST_ERROR;
+               return -EINVAL;
+       }
+       /* Closing decoding instance  */
+       mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
+       dev->curr_ctx = ctx->num;
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       h2r_args.arg[0] = ctx->inst_no;
+       ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
+                                                               &h2r_args);
+       if (ret) {
+               mfc_err("Failed to return an instance\n");
+               ctx->state = MFCINST_ERROR;
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/* Initialize cmd function pointers for MFC v5 */
+static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v5 = {
+       .cmd_host2risc = s5p_mfc_cmd_host2risc_v5,
+       .sys_init_cmd = s5p_mfc_sys_init_cmd_v5,
+       .sleep_cmd = s5p_mfc_sleep_cmd_v5,
+       .wakeup_cmd = s5p_mfc_wakeup_cmd_v5,
+       .open_inst_cmd = s5p_mfc_open_inst_cmd_v5,
+       .close_inst_cmd = s5p_mfc_close_inst_cmd_v5,
+};
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void)
+{
+       return &s5p_mfc_cmds_v5;
+}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
new file mode 100644 (file)
index 0000000..6928a55
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.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.
+ */
+
+#ifndef S5P_MFC_CMD_V5_H_
+#define S5P_MFC_CMD_V5_H_
+
+#include "s5p_mfc_common.h"
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void);
+
+#endif /* S5P_MFC_CMD_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
new file mode 100644 (file)
index 0000000..754bfbc
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.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.
+ */
+
+#include "s5p_mfc_common.h"
+
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_opr.h"
+
+int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd,
+                               struct s5p_mfc_cmd_args *args)
+{
+       mfc_debug(2, "Issue the command: %d\n", cmd);
+
+       /* Reset RISC2HOST command */
+       mfc_write(dev, 0x0, S5P_FIMV_RISC2HOST_CMD_V6);
+
+       /* Issue the command */
+       mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD_V6);
+       mfc_write(dev, 0x1, S5P_FIMV_HOST2RISC_INT_V6);
+
+       return 0;
+}
+
+int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+       struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
+
+       s5p_mfc_hw_call(dev->mfc_ops, alloc_dev_context_buffer, dev);
+       mfc_write(dev, dev->ctx_buf.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
+       mfc_write(dev, buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
+       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SYS_INIT_V6,
+                                       &h2r_args);
+}
+
+int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SLEEP_V6,
+                       &h2r_args);
+}
+
+int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_WAKEUP_V6,
+                                       &h2r_args);
+}
+
+/* Open a new instance and get its number */
+int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_cmd_args h2r_args;
+       int codec_type;
+
+       mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode);
+       dev->curr_ctx = ctx->num;
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+               codec_type = S5P_FIMV_CODEC_H264_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_H264_MVC_DEC:
+               codec_type = S5P_FIMV_CODEC_H264_MVC_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_VC1_DEC:
+               codec_type = S5P_FIMV_CODEC_VC1_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+               codec_type = S5P_FIMV_CODEC_MPEG4_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_MPEG2_DEC:
+               codec_type = S5P_FIMV_CODEC_MPEG2_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_H263_DEC:
+               codec_type = S5P_FIMV_CODEC_H263_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+               codec_type = S5P_FIMV_CODEC_VC1RCV_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_VP8_DEC:
+               codec_type = S5P_FIMV_CODEC_VP8_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_H264_ENC:
+               codec_type = S5P_FIMV_CODEC_H264_ENC_V6;
+               break;
+       case S5P_MFC_CODEC_H264_MVC_ENC:
+               codec_type = S5P_FIMV_CODEC_H264_MVC_ENC_V6;
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+               codec_type = S5P_FIMV_CODEC_MPEG4_ENC_V6;
+               break;
+       case S5P_MFC_CODEC_H263_ENC:
+               codec_type = S5P_FIMV_CODEC_H263_ENC_V6;
+               break;
+       default:
+               codec_type = S5P_FIMV_CODEC_NONE_V6;
+       };
+       mfc_write(dev, codec_type, S5P_FIMV_CODEC_TYPE_V6);
+       mfc_write(dev, ctx->ctx.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
+       mfc_write(dev, ctx->ctx.size, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
+       mfc_write(dev, 0, S5P_FIMV_D_CRC_CTRL_V6); /* no crc */
+
+       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6,
+                                       &h2r_args);
+}
+
+/* Close instance */
+int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_cmd_args h2r_args;
+       int ret = 0;
+
+       dev->curr_ctx = ctx->num;
+       if (ctx->state != MFCINST_FREE) {
+               mfc_write(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+               ret = s5p_mfc_cmd_host2risc_v6(dev,
+                                       S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6,
+                                       &h2r_args);
+       } else {
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+/* Initialize cmd function pointers for MFC v6 */
+static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v6 = {
+       .cmd_host2risc = s5p_mfc_cmd_host2risc_v6,
+       .sys_init_cmd = s5p_mfc_sys_init_cmd_v6,
+       .sleep_cmd = s5p_mfc_sleep_cmd_v6,
+       .wakeup_cmd = s5p_mfc_wakeup_cmd_v6,
+       .open_inst_cmd = s5p_mfc_open_inst_cmd_v6,
+       .close_inst_cmd = s5p_mfc_close_inst_cmd_v6,
+};
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void)
+{
+       return &s5p_mfc_cmds_v6;
+}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
new file mode 100644 (file)
index 0000000..b7a8e57
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.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.
+ */
+
+#ifndef S5P_MFC_CMD_V6_H_
+#define S5P_MFC_CMD_V6_H_
+
+#include "s5p_mfc_common.h"
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void);
+
+#endif /* S5P_MFC_CMD_H_ */
index 519b0d66d8d1263e52e170e387647ba3962b3fbe..f02e0497ca9837aad0269e4851702b72caeab431 100644 (file)
 #ifndef S5P_MFC_COMMON_H_
 #define S5P_MFC_COMMON_H_
 
-#include "regs-mfc.h"
 #include <linux/platform_device.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/videobuf2-core.h>
+#include "regs-mfc.h"
+#include "regs-mfc-v6.h"
 
 /* Definitions related to MFC memory */
 
 *  while mmaping */
 #define DST_QUEUE_OFF_BASE      (TASK_SIZE / 2)
 
-/* Offset used by the hardware to store addresses */
-#define MFC_OFFSET_SHIFT       11
-
-#define FIRMWARE_ALIGN         0x20000         /* 128KB */
-#define MFC_H264_CTX_BUF_SIZE  0x96000         /* 600KB per H264 instance */
-#define MFC_CTX_BUF_SIZE       0x2800          /* 10KB per instance */
-#define DESC_BUF_SIZE          0x20000         /* 128KB for DESC buffer */
-#define SHARED_BUF_SIZE                0x2000          /* 8KB for shared buffer */
-
-#define DEF_CPB_SIZE           0x40000         /* 512KB */
-
 #define MFC_BANK1_ALLOC_CTX    0
 #define MFC_BANK2_ALLOC_CTX    1
 
@@ -74,7 +64,40 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b)
 #define MFC_ENC_CAP_PLANE_COUNT        1
 #define MFC_ENC_OUT_PLANE_COUNT        2
 #define STUFF_BYTE             4
-#define MFC_MAX_CTRLS          64
+#define MFC_MAX_CTRLS          70
+
+#define S5P_MFC_CODEC_NONE             -1
+#define S5P_MFC_CODEC_H264_DEC         0
+#define S5P_MFC_CODEC_H264_MVC_DEC     1
+#define S5P_MFC_CODEC_VC1_DEC          2
+#define S5P_MFC_CODEC_MPEG4_DEC                3
+#define S5P_MFC_CODEC_MPEG2_DEC                4
+#define S5P_MFC_CODEC_H263_DEC         5
+#define S5P_MFC_CODEC_VC1RCV_DEC       6
+#define S5P_MFC_CODEC_VP8_DEC          7
+
+#define S5P_MFC_CODEC_H264_ENC         20
+#define S5P_MFC_CODEC_H264_MVC_ENC     21
+#define S5P_MFC_CODEC_MPEG4_ENC                22
+#define S5P_MFC_CODEC_H263_ENC         23
+
+#define S5P_MFC_R2H_CMD_EMPTY                  0
+#define S5P_MFC_R2H_CMD_SYS_INIT_RET           1
+#define S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET      2
+#define S5P_MFC_R2H_CMD_SEQ_DONE_RET           3
+#define S5P_MFC_R2H_CMD_INIT_BUFFERS_RET       4
+#define S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET     6
+#define S5P_MFC_R2H_CMD_SLEEP_RET              7
+#define S5P_MFC_R2H_CMD_WAKEUP_RET             8
+#define S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET       9
+#define S5P_MFC_R2H_CMD_DPB_FLUSH_RET          10
+#define S5P_MFC_R2H_CMD_NAL_ABORT_RET          11
+#define S5P_MFC_R2H_CMD_FW_STATUS_RET          12
+#define S5P_MFC_R2H_CMD_FRAME_DONE_RET         13
+#define S5P_MFC_R2H_CMD_FIELD_DONE_RET         14
+#define S5P_MFC_R2H_CMD_SLICE_DONE_RET         15
+#define S5P_MFC_R2H_CMD_ENC_BUFFER_FUL_RET     16
+#define S5P_MFC_R2H_CMD_ERR_RET                        32
 
 #define mfc_read(dev, offset)          readl(dev->regs_base + (offset))
 #define mfc_write(dev, data, offset)   writel((data), dev->regs_base + \
@@ -177,6 +200,58 @@ struct s5p_mfc_pm {
        struct device   *device;
 };
 
+struct s5p_mfc_buf_size_v5 {
+       unsigned int h264_ctx;
+       unsigned int non_h264_ctx;
+       unsigned int dsc;
+       unsigned int shm;
+};
+
+struct s5p_mfc_buf_size_v6 {
+       unsigned int dev_ctx;
+       unsigned int h264_dec_ctx;
+       unsigned int other_dec_ctx;
+       unsigned int h264_enc_ctx;
+       unsigned int other_enc_ctx;
+};
+
+struct s5p_mfc_buf_size {
+       unsigned int fw;
+       unsigned int cpb;
+       void *priv;
+};
+
+struct s5p_mfc_buf_align {
+       unsigned int base;
+};
+
+struct s5p_mfc_variant {
+       unsigned int version;
+       unsigned int port_num;
+       struct s5p_mfc_buf_size *buf_size;
+       struct s5p_mfc_buf_align *buf_align;
+       char    *mclk_name;
+       char    *fw_name;
+};
+
+/**
+ * struct s5p_mfc_priv_buf - represents internal used buffer
+ * @alloc:             allocation-specific context for each buffer
+ *                     (videobuf2 allocator)
+ * @ofs:               offset of each buffer, will be used for MFC
+ * @virt:              kernel virtual address, only valid when the
+ *                     buffer accessed by driver
+ * @dma:               DMA address, only valid when kernel DMA API used
+ * @size:              size of the buffer
+ */
+struct s5p_mfc_priv_buf {
+       void            *alloc;
+       unsigned long   ofs;
+       void            *virt;
+       dma_addr_t      dma;
+       size_t          size;
+};
+
 /**
  * struct s5p_mfc_dev - The struct containing driver internal parameters.
  *
@@ -191,6 +266,7 @@ struct s5p_mfc_pm {
  * @dec_ctrl_handler:  control framework handler for decoding
  * @enc_ctrl_handler:  control framework handler for encoding
  * @pm:                        power management control
+ * @variant:           MFC hardware variant information
  * @num_inst:          couter of active MFC instances
  * @irqlock:           lock for operations on videobuf2 queues
  * @condlock:          lock for changing/checking if a context is ready to be
@@ -212,6 +288,10 @@ struct s5p_mfc_pm {
  * @watchdog_work:     worker for the watchdog
  * @alloc_ctx:         videobuf2 allocator contexts for two memory banks
  * @enter_suspend:     flag set when entering suspend
+ * @ctx_buf:           common context memory (MFCv6)
+ * @warn_start:                hardware error code from which warnings start
+ * @mfc_ops:           ops structure holding HW operation function pointers
+ * @mfc_cmds:          cmd structure holding HW commands function pointers
  *
  */
 struct s5p_mfc_dev {
@@ -226,6 +306,7 @@ struct s5p_mfc_dev {
        struct v4l2_ctrl_handler dec_ctrl_handler;
        struct v4l2_ctrl_handler enc_ctrl_handler;
        struct s5p_mfc_pm       pm;
+       struct s5p_mfc_variant  *variant;
        int num_inst;
        spinlock_t irqlock;     /* lock when operating on videobuf2 queues */
        spinlock_t condlock;    /* lock when changing/checking if a context is
@@ -248,6 +329,11 @@ struct s5p_mfc_dev {
        struct work_struct watchdog_work;
        void *alloc_ctx[2];
        unsigned long enter_suspend;
+
+       struct s5p_mfc_priv_buf ctx_buf;
+       int warn_start;
+       struct s5p_mfc_hw_ops *mfc_ops;
+       struct s5p_mfc_hw_cmds *mfc_cmds;
 };
 
 /**
@@ -262,7 +348,6 @@ struct s5p_mfc_h264_enc_params {
        u8 max_ref_pic;
        u8 num_ref_pic_4p;
        int _8x8_transform;
-       int rc_mb;
        int rc_mb_dark;
        int rc_mb_smooth;
        int rc_mb_static;
@@ -281,6 +366,23 @@ struct s5p_mfc_h264_enc_params {
        enum v4l2_mpeg_video_h264_level level_v4l2;
        int level;
        u16 cpb_size;
+       int interlace;
+       u8 hier_qp;
+       u8 hier_qp_type;
+       u8 hier_qp_layer;
+       u8 hier_qp_layer_qp[7];
+       u8 sei_frame_packing;
+       u8 sei_fp_curr_frame_0;
+       u8 sei_fp_arrangement_type;
+
+       u8 fmo;
+       u8 fmo_map_type;
+       u8 fmo_slice_grp;
+       u8 fmo_chg_dir;
+       u32 fmo_chg_rate;
+       u32 fmo_run_len[4];
+       u8 aso;
+       u32 aso_slice_order[8];
 };
 
 /**
@@ -319,9 +421,11 @@ struct s5p_mfc_enc_params {
        u8 pad_cb;
        u8 pad_cr;
        int rc_frame;
+       int rc_mb;
        u32 rc_bitrate;
        u16 rc_reaction_coeff;
        u16 vbv_size;
+       u32 vbv_delay;
 
        enum v4l2_mpeg_video_header_mode seq_hdr_mode;
        enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
@@ -330,7 +434,6 @@ struct s5p_mfc_enc_params {
        u8 num_b_frame;
        u32 rc_framerate_num;
        u32 rc_framerate_denom;
-       int interlace;
 
        union {
                struct s5p_mfc_h264_enc_params h264;
@@ -388,6 +491,8 @@ struct s5p_mfc_codec_ops {
  *                     decoding buffer
  * @dpb_flush_flag:    flag used to indicate that a DPB buffers are being
  *                     flushed
+ * @head_processed:    flag mentioning whether the header data is processed
+ *                     completely or not
  * @bank1_buf:         handle to memory allocated for temporary buffers from
  *                     memory bank 1
  * @bank1_phys:                address of the temporary buffers from memory bank 1
@@ -412,19 +517,20 @@ struct s5p_mfc_codec_ops {
  * @display_delay_enable:      display delay for H264 enable flag
  * @after_packed_pb:   flag used to track buffer when stream is in
  *                     Packed PB format
+ * @sei_fp_parse:      enable/disable parsing of frame packing SEI information
  * @dpb_count:         count of the DPB buffers required by MFC hw
  * @total_dpb_count:   count of DPB buffers with additional buffers
  *                     requested by the application
- * @ctx_buf:           handle to the memory associated with this context
- * @ctx_phys:          address of the memory associated with this context
- * @ctx_size:          size of the memory associated with this context
- * @desc_buf:          description buffer for decoding handle
- * @desc_phys:         description buffer for decoding address
- * @shm_alloc:         handle for the shared memory buffer
- * @shm:               virtual address for the shared memory buffer
- * @shm_ofs:           address offset for shared memory
+ * @ctx:               context buffer information
+ * @dsc:               descriptor buffer information
+ * @shm:               shared memory buffer information
+ * @mv_count:          number of MV buffers allocated for decoding
  * @enc_params:                encoding parameters for MFC
  * @enc_dst_buf_size:  size of the buffers for encoder output
+ * @luma_dpb_size:     dpb buffer size for luma
+ * @chroma_dpb_size:   dpb buffer size for chroma
+ * @me_buffer_size:    size of the motion estimation buffer
+ * @tmv_buffer_size:   size of temporal predictor motion vector buffer
  * @frame_type:                used to force the type of the next encoded frame
  * @ref_queue:         list of the reference buffers for encoding
  * @ref_queue_cnt:     number of the buffers in the reference list
@@ -473,6 +579,7 @@ struct s5p_mfc_ctx {
        unsigned long consumed_stream;
 
        unsigned int dpb_flush_flag;
+       unsigned int head_processed;
 
        /* Buffers */
        void *bank1_buf;
@@ -502,37 +609,41 @@ struct s5p_mfc_ctx {
        int display_delay;
        int display_delay_enable;
        int after_packed_pb;
+       int sei_fp_parse;
 
        int dpb_count;
        int total_dpb_count;
-
+       int mv_count;
        /* Buffers */
-       void *ctx_buf;
-       size_t ctx_phys;
-       size_t ctx_ofs;
-       size_t ctx_size;
-
-       void *desc_buf;
-       size_t desc_phys;
-
-
-       void *shm_alloc;
-       void *shm;
-       size_t shm_ofs;
+       struct s5p_mfc_priv_buf ctx;
+       struct s5p_mfc_priv_buf dsc;
+       struct s5p_mfc_priv_buf shm;
 
        struct s5p_mfc_enc_params enc_params;
 
        size_t enc_dst_buf_size;
+       size_t luma_dpb_size;
+       size_t chroma_dpb_size;
+       size_t me_buffer_size;
+       size_t tmv_buffer_size;
 
        enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type;
 
        struct list_head ref_queue;
        unsigned int ref_queue_cnt;
 
+       enum v4l2_mpeg_video_multi_slice_mode slice_mode;
+       union {
+               unsigned int mb;
+               unsigned int bits;
+       } slice_size;
+
        struct s5p_mfc_codec_ops *c_ops;
 
        struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS];
        struct v4l2_ctrl_handler ctrl_handler;
+       unsigned int frame_tag;
+       size_t scratch_buf_size;
 };
 
 /*
@@ -565,6 +676,9 @@ struct mfc_control {
        __u8                    is_volatile;
 };
 
+/* Macro for making hardware specific calls */
+#define s5p_mfc_hw_call(f, op, args...) \
+       ((f && f->op) ? f->op(args) : -ENODEV)
 
 #define fh_to_ctx(__fh) container_of(__fh, struct s5p_mfc_ctx, fh)
 #define ctrl_to_ctx(__ctrl) \
@@ -575,4 +689,9 @@ void set_work_bit(struct s5p_mfc_ctx *ctx);
 void clear_work_bit_irqsave(struct s5p_mfc_ctx *ctx);
 void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx);
 
+#define HAS_PORTNUM(dev)       (dev ? (dev->variant ? \
+                               (dev->variant->port_num ? 1 : 0) : 0) : 0)
+#define IS_TWOPORT(dev)                (dev->variant->port_num == 2 ? 1 : 0)
+#define IS_MFCV6(dev)          (dev->variant->version >= 0x60 ? 1 : 0)
+
 #endif /* S5P_MFC_COMMON_H_ */
index 0deba6bc687c7a357ba37ff40de904afb1bebb94..585b7b0ed8ec6a4cd4422246e22c0170f29ac10d 100644 (file)
 #include <linux/firmware.h>
 #include <linux/jiffies.h>
 #include <linux/sched.h>
-#include "regs-mfc.h"
 #include "s5p_mfc_cmd.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_intr.h"
+#include "s5p_mfc_opr.h"
 #include "s5p_mfc_pm.h"
 
 static void *s5p_mfc_bitproc_buf;
@@ -37,13 +37,19 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
        /* Firmare has to be present as a separate file or compiled
         * into kernel. */
        mfc_debug_enter();
+
        err = request_firmware((const struct firmware **)&fw_blob,
-                                    "s5p-mfc.fw", dev->v4l2_dev.dev);
+                                    dev->variant->fw_name, dev->v4l2_dev.dev);
        if (err != 0) {
                mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
                return -EINVAL;
        }
-       dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
+       dev->fw_size = dev->variant->buf_size->fw;
+       if (fw_blob->size > dev->fw_size) {
+               mfc_err("MFC firmware is too big to be loaded\n");
+               release_firmware(fw_blob);
+               return -ENOMEM;
+       }
        if (s5p_mfc_bitproc_buf) {
                mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
                release_firmware(fw_blob);
@@ -77,32 +83,37 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
                return -EIO;
        }
        dev->bank1 = s5p_mfc_bitproc_phys;
-       b_base = vb2_dma_contig_memops.alloc(
-               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BASE_ALIGN_ORDER);
-       if (IS_ERR(b_base)) {
-               vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
-               s5p_mfc_bitproc_phys = 0;
-               s5p_mfc_bitproc_buf = NULL;
-               mfc_err("Allocating bank2 base failed\n");
-       release_firmware(fw_blob);
-               return -ENOMEM;
-       }
-       bank2_base_phys = s5p_mfc_mem_cookie(
-               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
-       vb2_dma_contig_memops.put(b_base);
-       if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
-               mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
-               vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
-               s5p_mfc_bitproc_phys = 0;
-               s5p_mfc_bitproc_buf = NULL;
-               release_firmware(fw_blob);
-               return -EIO;
+       if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) {
+               b_base = vb2_dma_contig_memops.alloc(
+                       dev->alloc_ctx[MFC_BANK2_ALLOC_CTX],
+                       1 << MFC_BASE_ALIGN_ORDER);
+               if (IS_ERR(b_base)) {
+                       vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
+                       s5p_mfc_bitproc_phys = 0;
+                       s5p_mfc_bitproc_buf = NULL;
+                       mfc_err("Allocating bank2 base failed\n");
+                       release_firmware(fw_blob);
+                       return -ENOMEM;
+               }
+               bank2_base_phys = s5p_mfc_mem_cookie(
+                       dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
+               vb2_dma_contig_memops.put(b_base);
+               if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
+                       mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
+                       vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
+                       s5p_mfc_bitproc_phys = 0;
+                       s5p_mfc_bitproc_buf = NULL;
+                       release_firmware(fw_blob);
+                       return -EIO;
+               }
+               /* Valid buffers passed to MFC encoder with LAST_FRAME command
+                * should not have address of bank2 - MFC will treat it as a null frame.
+                * To avoid such situation we set bank2 address below the pool address.
+                */
+               dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER);
+       } else {
+               dev->bank2 = dev->bank1;
        }
-       /* Valid buffers passed to MFC encoder with LAST_FRAME command
-        * should not have address of bank2 - MFC will treat it as a null frame.
-        * To avoid such situation we set bank2 address below the pool address.
-        */
-       dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER);
        memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
        wmb();
        release_firmware(fw_blob);
@@ -119,8 +130,9 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
        /* Firmare has to be present as a separate file or compiled
         * into kernel. */
        mfc_debug_enter();
+
        err = request_firmware((const struct firmware **)&fw_blob,
-                                    "s5p-mfc.fw", dev->v4l2_dev.dev);
+                                    dev->variant->fw_name, dev->v4l2_dev.dev);
        if (err != 0) {
                mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
                return -EINVAL;
@@ -161,46 +173,81 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev)
 {
        unsigned int mc_status;
        unsigned long timeout;
+       int i;
 
        mfc_debug_enter();
-       /* Stop procedure */
-       /*  reset RISC */
-       mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
-       /*  All reset except for MC */
-       mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
-       mdelay(10);
-
-       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
-       /* Check MC status */
-       do {
-               if (time_after(jiffies, timeout)) {
-                       mfc_err("Timeout while resetting MFC\n");
-                       return -EIO;
-               }
 
-               mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
+       if (IS_MFCV6(dev)) {
+               /* Reset IP */
+               /*  except RISC, reset */
+               mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET_V6);
+               /*  reset release */
+               mfc_write(dev, 0x0, S5P_FIMV_MFC_RESET_V6);
+
+               /* Zero Initialization of MFC registers */
+               mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
+               mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD_V6);
+               mfc_write(dev, 0, S5P_FIMV_FW_VERSION_V6);
+
+               for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT_V6; i++)
+                       mfc_write(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN_V6 + (i*4));
 
-       } while (mc_status & 0x3);
+               /* Reset */
+               mfc_write(dev, 0, S5P_FIMV_RISC_ON_V6);
+               mfc_write(dev, 0x1FFF, S5P_FIMV_MFC_RESET_V6);
+               mfc_write(dev, 0, S5P_FIMV_MFC_RESET_V6);
+       } else {
+               /* Stop procedure */
+               /*  reset RISC */
+               mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
+               /*  All reset except for MC */
+               mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
+               mdelay(10);
+
+               timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+               /* Check MC status */
+               do {
+                       if (time_after(jiffies, timeout)) {
+                               mfc_err("Timeout while resetting MFC\n");
+                               return -EIO;
+                       }
+
+                       mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
+
+               } while (mc_status & 0x3);
+
+               mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
+               mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
+       }
 
-       mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
-       mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
        mfc_debug_leave();
        return 0;
 }
 
 static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
 {
-       mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
-       mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
-       mfc_debug(2, "Bank1: %08x, Bank2: %08x\n", dev->bank1, dev->bank2);
+       if (IS_MFCV6(dev)) {
+               mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS_V6);
+               mfc_debug(2, "Base Address : %08x\n", dev->bank1);
+       } else {
+               mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
+               mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
+               mfc_debug(2, "Bank1: %08x, Bank2: %08x\n",
+                               dev->bank1, dev->bank2);
+       }
 }
 
 static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
 {
-       mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
-       mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
-       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
-       mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
+       if (IS_MFCV6(dev)) {
+               /* Zero initialization should be done before RESET.
+                * Nothing to do here. */
+       } else {
+               mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
+               mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
+               mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
+               mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
+       }
 }
 
 /* Initialize hardware */
@@ -228,9 +275,12 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
        s5p_mfc_clear_cmds(dev);
        /* 3. Release reset signal to the RISC */
        s5p_mfc_clean_dev_int_flags(dev);
-       mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
+       if (IS_MFCV6(dev))
+               mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
+       else
+               mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
        mfc_debug(2, "Will now wait for completion of firmware transfer\n");
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
                mfc_err("Failed to load firmware\n");
                s5p_mfc_reset(dev);
                s5p_mfc_clock_off();
@@ -238,7 +288,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
        }
        s5p_mfc_clean_dev_int_flags(dev);
        /* 4. Initialize firmware */
-       ret = s5p_mfc_sys_init_cmd(dev);
+       ret = s5p_mfc_hw_call(dev->mfc_cmds, sys_init_cmd, dev);
        if (ret) {
                mfc_err("Failed to send command to MFC - timeout\n");
                s5p_mfc_reset(dev);
@@ -246,7 +296,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
                return ret;
        }
        mfc_debug(2, "Ok, now will write a command to init the system\n");
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) {
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SYS_INIT_RET)) {
                mfc_err("Failed to load firmware\n");
                s5p_mfc_reset(dev);
                s5p_mfc_clock_off();
@@ -254,7 +304,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
        }
        dev->int_cond = 0;
        if (dev->int_err != 0 || dev->int_type !=
-                                       S5P_FIMV_R2H_CMD_SYS_INIT_RET) {
+                                       S5P_MFC_R2H_CMD_SYS_INIT_RET) {
                /* Failure. */
                mfc_err("Failed to init firmware - error: %d int: %d\n",
                                                dev->int_err, dev->int_type);
@@ -262,7 +312,11 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
                s5p_mfc_clock_off();
                return -EIO;
        }
-       ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
+       if (IS_MFCV6(dev))
+               ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6);
+       else
+               ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
+
        mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
                (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
        s5p_mfc_clock_off();
@@ -271,6 +325,17 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
 }
 
 
+/* Deinitialize hardware */
+void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev)
+{
+       s5p_mfc_clock_on();
+
+       s5p_mfc_reset(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, release_dev_context_buffer, dev);
+
+       s5p_mfc_clock_off();
+}
+
 int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
 {
        int ret;
@@ -278,19 +343,19 @@ int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
        mfc_debug_enter();
        s5p_mfc_clock_on();
        s5p_mfc_clean_dev_int_flags(dev);
-       ret = s5p_mfc_sleep_cmd(dev);
+       ret = s5p_mfc_hw_call(dev->mfc_cmds, sleep_cmd, dev);
        if (ret) {
                mfc_err("Failed to send command to MFC - timeout\n");
                return ret;
        }
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SLEEP_RET)) {
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SLEEP_RET)) {
                mfc_err("Failed to sleep\n");
                return -EIO;
        }
        s5p_mfc_clock_off();
        dev->int_cond = 0;
        if (dev->int_err != 0 || dev->int_type !=
-                                               S5P_FIMV_R2H_CMD_SLEEP_RET) {
+                                               S5P_MFC_R2H_CMD_SLEEP_RET) {
                /* Failure. */
                mfc_err("Failed to sleep - error: %d int: %d\n", dev->int_err,
                                                                dev->int_type);
@@ -320,22 +385,25 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
        s5p_mfc_clear_cmds(dev);
        s5p_mfc_clean_dev_int_flags(dev);
        /* 3. Initialize firmware */
-       ret = s5p_mfc_wakeup_cmd(dev);
+       ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
        if (ret) {
                mfc_err("Failed to send command to MFC - timeout\n");
                return ret;
        }
        /* 4. Release reset signal to the RISC */
-       mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
+       if (IS_MFCV6(dev))
+               mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
+       else
+               mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
        mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) {
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
                mfc_err("Failed to load firmware\n");
                return -EIO;
        }
        s5p_mfc_clock_off();
        dev->int_cond = 0;
        if (dev->int_err != 0 || dev->int_type !=
-                                               S5P_FIMV_R2H_CMD_WAKEUP_RET) {
+                                               S5P_MFC_R2H_CMD_WAKEUP_RET) {
                /* Failure. */
                mfc_err("Failed to wakeup - error: %d int: %d\n", dev->int_err,
                                                                dev->int_type);
index e1e0c544b6a2ccb675c6f445ba6ff758dbd54898..90aa9b9886d56f1e3c30e204ad2ee61793d1b8d1 100644 (file)
@@ -20,6 +20,7 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev);
 int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev);
 
 int s5p_mfc_init_hw(struct s5p_mfc_dev *dev);
+void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev);
 
 int s5p_mfc_sleep(struct s5p_mfc_dev *dev);
 int s5p_mfc_wakeup(struct s5p_mfc_dev *dev);
index 6ee21bb713980ac840b1c87d175f898b380d46db..eb6a70b0f8213285a888ee867e3346d8ca9c5770 100644 (file)
 #include <linux/workqueue.h>
 #include <media/v4l2-ctrls.h>
 #include <media/videobuf2-core.h>
-#include "regs-mfc.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_dec.h"
 #include "s5p_mfc_intr.h"
 #include "s5p_mfc_opr.h"
 #include "s5p_mfc_pm.h"
-#include "s5p_mfc_shm.h"
+
+#define DEF_SRC_FMT_DEC        V4L2_PIX_FMT_H264
+#define DEF_DST_FMT_DEC        V4L2_PIX_FMT_NV12MT_16X16
 
 static struct s5p_mfc_fmt formats[] = {
+       {
+               .name           = "4:2:0 2 Planes 16x16 Tiles",
+               .fourcc         = V4L2_PIX_FMT_NV12MT_16X16,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+       },
        {
                .name           = "4:2:0 2 Planes 64x32 Tiles",
                .fourcc         = V4L2_PIX_FMT_NV12MT,
-               .codec_mode     = S5P_FIMV_CODEC_NONE,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
                .type           = MFC_FMT_RAW,
                .num_planes     = 2,
-        },
+       },
        {
-               .name = "4:2:0 2 Planes",
-               .fourcc = V4L2_PIX_FMT_NV12M,
-               .codec_mode = S5P_FIMV_CODEC_NONE,
-               .type = MFC_FMT_RAW,
-               .num_planes = 2,
+               .name           = "4:2:0 2 Planes Y/CbCr",
+               .fourcc         = V4L2_PIX_FMT_NV12M,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+       },
+       {
+               .name           = "4:2:0 2 Planes Y/CrCb",
+               .fourcc         = V4L2_PIX_FMT_NV21M,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
        },
        {
-               .name = "H264 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_H264,
-               .codec_mode = S5P_FIMV_CODEC_H264_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "H264 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_H264,
+               .codec_mode     = S5P_MFC_CODEC_H264_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
        {
-               .name = "H263 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_H263,
-               .codec_mode = S5P_FIMV_CODEC_H263_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "H264/MVC Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_H264_MVC,
+               .codec_mode     = S5P_MFC_CODEC_H264_MVC_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
        {
-               .name = "MPEG1 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_MPEG1,
-               .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "H263 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_H263,
+               .codec_mode     = S5P_MFC_CODEC_H263_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
        {
-               .name = "MPEG2 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_MPEG2,
-               .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "MPEG1 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_MPEG1,
+               .codec_mode     = S5P_MFC_CODEC_MPEG2_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
        {
-               .name = "MPEG4 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_MPEG4,
-               .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "MPEG2 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_MPEG2,
+               .codec_mode     = S5P_MFC_CODEC_MPEG2_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
        {
-               .name = "XviD Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_XVID,
-               .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "MPEG4 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_MPEG4,
+               .codec_mode     = S5P_MFC_CODEC_MPEG4_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
        {
-               .name = "VC1 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
-               .codec_mode = S5P_FIMV_CODEC_VC1_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "XviD Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_XVID,
+               .codec_mode     = S5P_MFC_CODEC_MPEG4_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
        {
-               .name = "VC1 RCV Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
-               .codec_mode = S5P_FIMV_CODEC_VC1RCV_DEC,
-               .type = MFC_FMT_DEC,
-               .num_planes = 1,
+               .name           = "VC1 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_VC1_ANNEX_G,
+               .codec_mode     = S5P_MFC_CODEC_VC1_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+       },
+       {
+               .name           = "VC1 RCV Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_VC1_ANNEX_L,
+               .codec_mode     = S5P_MFC_CODEC_VC1RCV_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+       },
+       {
+               .name           = "VP8 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_VP8,
+               .codec_mode     = S5P_MFC_CODEC_VP8_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
        },
 };
 
@@ -297,7 +326,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
                /* If the MFC is parsing the header,
                 * so wait until it is finished */
                s5p_mfc_clean_ctx_int_flags(ctx);
-               s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_SEQ_DONE_RET,
+               s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET,
                                                                        0);
        }
        if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
@@ -342,21 +371,36 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
 /* Try format */
 static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
 {
+       struct s5p_mfc_dev *dev = video_drvdata(file);
        struct s5p_mfc_fmt *fmt;
 
-       if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_err("This node supports decoding only\n");
-               return -EINVAL;
-       }
-       fmt = find_format(f, MFC_FMT_DEC);
-       if (!fmt) {
-               mfc_err("Unsupported format\n");
-               return -EINVAL;
-       }
-       if (fmt->type != MFC_FMT_DEC) {
-               mfc_err("\n");
-               return -EINVAL;
+       mfc_debug(2, "Type is %d\n", f->type);
+       if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               fmt = find_format(f, MFC_FMT_DEC);
+               if (!fmt) {
+                       mfc_err("Unsupported format for source.\n");
+                       return -EINVAL;
+               }
+               if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
+                       mfc_err("Not supported format.\n");
+                       return -EINVAL;
+               }
+       } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               fmt = find_format(f, MFC_FMT_RAW);
+               if (!fmt) {
+                       mfc_err("Unsupported format for destination.\n");
+                       return -EINVAL;
+               }
+               if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
+                       mfc_err("Not supported format.\n");
+                       return -EINVAL;
+               } else if (!IS_MFCV6(dev) &&
+                               (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) {
+                       mfc_err("Not supported format.\n");
+                       return -EINVAL;
+               }
        }
+
        return 0;
 }
 
@@ -379,8 +423,29 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
                ret = -EBUSY;
                goto out;
        }
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               fmt = find_format(f, MFC_FMT_RAW);
+               if (!fmt) {
+                       mfc_err("Unsupported format for source.\n");
+                       return -EINVAL;
+               }
+               if (!IS_MFCV6(dev) && (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) {
+                       mfc_err("Not supported format.\n");
+                       return -EINVAL;
+               } else if (IS_MFCV6(dev) &&
+                               (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
+                       mfc_err("Not supported format.\n");
+                       return -EINVAL;
+               }
+               ctx->dst_fmt = fmt;
+               mfc_debug_leave();
+               return ret;
+       } else if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_err("Wrong type error for S_FMT : %d", f->type);
+               return -EINVAL;
+       }
        fmt = find_format(f, MFC_FMT_DEC);
-       if (!fmt || fmt->codec_mode == S5P_FIMV_CODEC_NONE) {
+       if (!fmt || fmt->codec_mode == S5P_MFC_CODEC_NONE) {
                mfc_err("Unknown codec\n");
                ret = -EINVAL;
                goto out;
@@ -391,6 +456,10 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
                ret = -EINVAL;
                goto out;
        }
+       if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
+               mfc_err("Not supported format.\n");
+               return -EINVAL;
+       }
        ctx->src_fmt = fmt;
        ctx->codec_mode = fmt->codec_mode;
        mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
@@ -476,7 +545,7 @@ static int vidioc_reqbufs(struct file *file, void *priv,
                        return -ENOMEM;
                }
                ctx->total_dpb_count = reqbufs->count;
-               ret = s5p_mfc_alloc_codec_buffers(ctx);
+               ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx);
                if (ret) {
                        mfc_err("Failed to allocate decoding buffers\n");
                        reqbufs->count = 0;
@@ -492,15 +561,16 @@ static int vidioc_reqbufs(struct file *file, void *priv,
                        reqbufs->count = 0;
                        s5p_mfc_clock_on();
                        ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-                       s5p_mfc_release_codec_buffers(ctx);
+                       s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers,
+                                       ctx);
                        s5p_mfc_clock_off();
                        return -ENOMEM;
                }
                if (s5p_mfc_ctx_ready(ctx))
                        set_work_bit_irqsave(ctx);
-               s5p_mfc_try_run(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
                s5p_mfc_wait_for_done_ctx(ctx,
-                                        S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0);
+                                       S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0);
        }
        return ret;
 }
@@ -582,18 +652,22 @@ static int vidioc_streamon(struct file *file, void *priv,
                        ctx->src_bufs_cnt = 0;
                        ctx->capture_state = QUEUE_FREE;
                        ctx->output_state = QUEUE_FREE;
-                       s5p_mfc_alloc_instance_buffer(ctx);
-                       s5p_mfc_alloc_dec_temp_buffers(ctx);
+                       s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer,
+                                       ctx);
+                       s5p_mfc_hw_call(dev->mfc_ops, alloc_dec_temp_buffers,
+                                       ctx);
                        set_work_bit_irqsave(ctx);
                        s5p_mfc_clean_ctx_int_flags(ctx);
-                       s5p_mfc_try_run(dev);
+                       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
 
                        if (s5p_mfc_wait_for_done_ctx(ctx,
-                               S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
+                               S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
                                /* Error or timeout */
                                mfc_err("Error getting instance from hardware\n");
-                               s5p_mfc_release_instance_buffer(ctx);
-                               s5p_mfc_release_dec_desc_buffer(ctx);
+                               s5p_mfc_hw_call(dev->mfc_ops,
+                                               release_instance_buffer, ctx);
+                               s5p_mfc_hw_call(dev->mfc_ops,
+                                               release_dec_desc_buffer, ctx);
                                return -EIO;
                        }
                        mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
@@ -662,7 +736,7 @@ static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl)
                /* Should wait for the header to be parsed */
                s5p_mfc_clean_ctx_int_flags(ctx);
                s5p_mfc_wait_for_done_ctx(ctx,
-                               S5P_FIMV_R2H_CMD_SEQ_DONE_RET, 0);
+                               S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
                if (ctx->state >= MFCINST_HEAD_PARSED &&
                    ctx->state < MFCINST_ABORT) {
                        ctrl->val = ctx->dpb_count;
@@ -686,6 +760,7 @@ static int vidioc_g_crop(struct file *file, void *priv,
                struct v4l2_crop *cr)
 {
        struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
        u32 left, right, top, bottom;
 
        if (ctx->state != MFCINST_HEAD_PARSED &&
@@ -695,10 +770,10 @@ static int vidioc_g_crop(struct file *file, void *priv,
                        return -EINVAL;
                }
        if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) {
-               left = s5p_mfc_read_shm(ctx, CROP_INFO_H);
+               left = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_h, ctx);
                right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT;
                left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK;
-               top = s5p_mfc_read_shm(ctx, CROP_INFO_V);
+               top = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_v, ctx);
                bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT;
                top = top & S5P_FIMV_SHARED_CROP_TOP_MASK;
                cr->c.left = left;
@@ -749,6 +824,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
                        void *allocators[])
 {
        struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
 
        /* Video output for decoding (source)
         * this can be set after getting an instance */
@@ -784,7 +860,13 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
            vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
                psize[0] = ctx->luma_size;
                psize[1] = ctx->chroma_size;
-               allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+
+               if (IS_MFCV6(dev))
+                       allocators[0] =
+                               ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+               else
+                       allocators[0] =
+                               ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
                allocators[1] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
        } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
                   ctx->state == MFCINST_INIT) {
@@ -876,7 +958,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
        /* If context is ready then dev = work->data;schedule it to run */
        if (s5p_mfc_ctx_ready(ctx))
                set_work_bit_irqsave(ctx);
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
        return 0;
 }
 
@@ -892,19 +974,21 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
                dev->curr_ctx == ctx->num && dev->hw_lock) {
                ctx->state = MFCINST_ABORT;
                s5p_mfc_wait_for_done_ctx(ctx,
-                                       S5P_FIMV_R2H_CMD_FRAME_DONE_RET, 0);
+                                       S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0);
                aborted = 1;
        }
        spin_lock_irqsave(&dev->irqlock, flags);
        if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
+                               &ctx->vq_dst);
                INIT_LIST_HEAD(&ctx->dst_queue);
                ctx->dst_queue_cnt = 0;
                ctx->dpb_flush_flag = 1;
                ctx->dec_dst_flag = 0;
        }
        if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
+                               &ctx->vq_src);
                INIT_LIST_HEAD(&ctx->src_queue);
                ctx->src_queue_cnt = 0;
        }
@@ -944,7 +1028,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
        }
        if (s5p_mfc_ctx_ready(ctx))
                set_work_bit_irqsave(ctx);
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
 }
 
 static struct vb2_ops s5p_mfc_dec_qops = {
@@ -1028,3 +1112,13 @@ void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx)
                ctx->ctrls[i] = NULL;
 }
 
+void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx)
+{
+       struct v4l2_format f;
+       f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_DEC;
+       ctx->src_fmt = find_format(&f, MFC_FMT_DEC);
+       f.fmt.pix_mp.pixelformat = DEF_DST_FMT_DEC;
+       ctx->dst_fmt = find_format(&f, MFC_FMT_RAW);
+       mfc_debug(2, "Default src_fmt is %x, dest_fmt is %x\n",
+                       (unsigned int)ctx->src_fmt, (unsigned int)ctx->dst_fmt);
+}
index fdf1d99a9d15df53decc6bb427ede6dfd0903ece..d06a7cab5eb1bc32f86cb7edfbac1062fd141b14 100644 (file)
@@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void);
 struct s5p_mfc_fmt *get_dec_def_fmt(bool src);
 int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx);
 void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx);
 
 #endif /* S5P_MFC_DEC_H_ */
index 179e4db60b15614a4cac63e04be9bc98667232b4..2af6d522f4acf3b94b142281c22edd2ce7c53c44 100644 (file)
 #include <linux/workqueue.h>
 #include <media/v4l2-ctrls.h>
 #include <media/videobuf2-core.h>
-#include "regs-mfc.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_enc.h"
 #include "s5p_mfc_intr.h"
 #include "s5p_mfc_opr.h"
 
+#define DEF_SRC_FMT_ENC        V4L2_PIX_FMT_NV12MT
+#define DEF_DST_FMT_ENC        V4L2_PIX_FMT_H264
+
 static struct s5p_mfc_fmt formats[] = {
        {
-               .name = "4:2:0 2 Planes 64x32 Tiles",
-               .fourcc = V4L2_PIX_FMT_NV12MT,
-               .codec_mode = S5P_FIMV_CODEC_NONE,
-               .type = MFC_FMT_RAW,
-               .num_planes = 2,
+               .name           = "4:2:0 2 Planes 16x16 Tiles",
+               .fourcc         = V4L2_PIX_FMT_NV12MT_16X16,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+       },
+       {
+               .name           = "4:2:0 2 Planes 64x32 Tiles",
+               .fourcc         = V4L2_PIX_FMT_NV12MT,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+       },
+       {
+               .name           = "4:2:0 2 Planes Y/CbCr",
+               .fourcc         = V4L2_PIX_FMT_NV12M,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
        },
        {
-               .name = "4:2:0 2 Planes",
-               .fourcc = V4L2_PIX_FMT_NV12M,
-               .codec_mode = S5P_FIMV_CODEC_NONE,
-               .type = MFC_FMT_RAW,
-               .num_planes = 2,
+               .name           = "4:2:0 2 Planes Y/CrCb",
+               .fourcc         = V4L2_PIX_FMT_NV21M,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
        },
        {
-               .name = "H264 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_H264,
-               .codec_mode = S5P_FIMV_CODEC_H264_ENC,
-               .type = MFC_FMT_ENC,
-               .num_planes = 1,
+               .name           = "H264 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_H264,
+               .codec_mode     = S5P_MFC_CODEC_H264_ENC,
+               .type           = MFC_FMT_ENC,
+               .num_planes     = 1,
        },
        {
-               .name = "MPEG4 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_MPEG4,
-               .codec_mode = S5P_FIMV_CODEC_MPEG4_ENC,
-               .type = MFC_FMT_ENC,
-               .num_planes = 1,
+               .name           = "MPEG4 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_MPEG4,
+               .codec_mode     = S5P_MFC_CODEC_MPEG4_ENC,
+               .type           = MFC_FMT_ENC,
+               .num_planes     = 1,
        },
        {
-               .name = "H263 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_H263,
-               .codec_mode = S5P_FIMV_CODEC_H263_ENC,
-               .type = MFC_FMT_ENC,
-               .num_planes = 1,
+               .name           = "H263 Encoded Stream",
+               .fourcc         = V4L2_PIX_FMT_H263,
+               .codec_mode     = S5P_MFC_CODEC_H263_ENC,
+               .type           = MFC_FMT_ENC,
+               .num_planes     = 1,
        },
 };
 
@@ -574,7 +590,8 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
        if (ctx->state == MFCINST_GOT_INST && ctx->dst_queue_cnt >= 1)
                return 1;
        /* context is ready to encode a frame */
-       if (ctx->state == MFCINST_RUNNING &&
+       if ((ctx->state == MFCINST_RUNNING ||
+               ctx->state == MFCINST_HEAD_PARSED) &&
                ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
                return 1;
        /* context is ready to encode remaining frames */
@@ -619,7 +636,8 @@ static int enc_pre_seq_start(struct s5p_mfc_ctx *ctx)
        dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
        dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
        dst_size = vb2_plane_size(dst_mb->b, 0);
-       s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
+       s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
+                       dst_size);
        spin_unlock_irqrestore(&dev->irqlock, flags);
        return 0;
 }
@@ -638,14 +656,23 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
                list_del(&dst_mb->list);
                ctx->dst_queue_cnt--;
                vb2_set_plane_payload(dst_mb->b, 0,
-                                               s5p_mfc_get_enc_strm_size());
+                       s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev));
                vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE);
                spin_unlock_irqrestore(&dev->irqlock, flags);
        }
-       ctx->state = MFCINST_RUNNING;
-       if (s5p_mfc_ctx_ready(ctx))
-               set_work_bit_irqsave(ctx);
-       s5p_mfc_try_run(dev);
+       if (IS_MFCV6(dev)) {
+               ctx->state = MFCINST_HEAD_PARSED; /* for INIT_BUFFER cmd */
+       } else {
+               ctx->state = MFCINST_RUNNING;
+               if (s5p_mfc_ctx_ready(ctx))
+                       set_work_bit_irqsave(ctx);
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+       }
+
+       if (IS_MFCV6(dev))
+               ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops,
+                               get_enc_dpb_count, dev);
+
        return 0;
 }
 
@@ -662,14 +689,16 @@ static int enc_pre_frame_start(struct s5p_mfc_ctx *ctx)
        src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
        src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
        src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
-       s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
+       s5p_mfc_hw_call(dev->mfc_ops, set_enc_frame_buffer, ctx, src_y_addr,
+                       src_c_addr);
        spin_unlock_irqrestore(&dev->irqlock, flags);
 
        spin_lock_irqsave(&dev->irqlock, flags);
        dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
        dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
        dst_size = vb2_plane_size(dst_mb->b, 0);
-       s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
+       s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
+                       dst_size);
        spin_unlock_irqrestore(&dev->irqlock, flags);
 
        return 0;
@@ -685,15 +714,16 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
        unsigned int strm_size;
        unsigned long flags;
 
-       slice_type = s5p_mfc_get_enc_slice_type();
-       strm_size = s5p_mfc_get_enc_strm_size();
+       slice_type = s5p_mfc_hw_call(dev->mfc_ops, get_enc_slice_type, dev);
+       strm_size = s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev);
        mfc_debug(2, "Encoded slice type: %d", slice_type);
        mfc_debug(2, "Encoded stream size: %d", strm_size);
        mfc_debug(2, "Display order: %d",
                  mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT));
        spin_lock_irqsave(&dev->irqlock, flags);
        if (slice_type >= 0) {
-               s5p_mfc_get_enc_frame_buffer(ctx, &enc_y_addr, &enc_c_addr);
+               s5p_mfc_hw_call(dev->mfc_ops, get_enc_frame_buffer, ctx,
+                               &enc_y_addr, &enc_c_addr);
                list_for_each_entry(mb_entry, &ctx->src_queue, list) {
                        mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 0);
                        mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 1);
@@ -939,15 +969,16 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
                pix_fmt_mp->plane_fmt[0].bytesperline = 0;
                ctx->dst_bufs_cnt = 0;
                ctx->capture_state = QUEUE_FREE;
-               s5p_mfc_alloc_instance_buffer(ctx);
+               s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx);
                set_work_bit_irqsave(ctx);
                s5p_mfc_clean_ctx_int_flags(ctx);
-               s5p_mfc_try_run(dev);
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
                if (s5p_mfc_wait_for_done_ctx(ctx, \
-                               S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 1)) {
+                               S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 1)) {
                                /* Error or timeout */
                        mfc_err("Error getting instance from hardware\n");
-                       s5p_mfc_release_instance_buffer(ctx);
+                       s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer,
+                                       ctx);
                        ret = -EIO;
                        goto out;
                }
@@ -958,6 +989,17 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
                        mfc_err("failed to set output format\n");
                        return -EINVAL;
                }
+
+               if (!IS_MFCV6(dev) &&
+                               (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)) {
+                       mfc_err("Not supported format.\n");
+                       return -EINVAL;
+               } else if (IS_MFCV6(dev) &&
+                               (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
+                       mfc_err("Not supported format.\n");
+                       return -EINVAL;
+               }
+
                if (fmt->num_planes != pix_fmt_mp->num_planes) {
                        mfc_err("failed to set output format\n");
                        ret = -EINVAL;
@@ -970,45 +1012,13 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
                mfc_debug(2, "fmt - w: %d, h: %d, ctx - w: %d, h: %d\n",
                        pix_fmt_mp->width, pix_fmt_mp->height,
                        ctx->img_width, ctx->img_height);
-               if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
-                       ctx->buf_width = ALIGN(ctx->img_width,
-                                                       S5P_FIMV_NV12M_HALIGN);
-                       ctx->luma_size = ALIGN(ctx->img_width,
-                               S5P_FIMV_NV12M_HALIGN) * ALIGN(ctx->img_height,
-                               S5P_FIMV_NV12M_LVALIGN);
-                       ctx->chroma_size = ALIGN(ctx->img_width,
-                               S5P_FIMV_NV12M_HALIGN) * ALIGN((ctx->img_height
-                               >> 1), S5P_FIMV_NV12M_CVALIGN);
-
-                       ctx->luma_size = ALIGN(ctx->luma_size,
-                                                       S5P_FIMV_NV12M_SALIGN);
-                       ctx->chroma_size = ALIGN(ctx->chroma_size,
-                                                       S5P_FIMV_NV12M_SALIGN);
-
-                       pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
-                       pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
-                       pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
-                       pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
-
-               } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
-                       ctx->buf_width = ALIGN(ctx->img_width,
-                                                       S5P_FIMV_NV12MT_HALIGN);
-                       ctx->luma_size = ALIGN(ctx->img_width,
-                               S5P_FIMV_NV12MT_HALIGN) * ALIGN(ctx->img_height,
-                               S5P_FIMV_NV12MT_VALIGN);
-                       ctx->chroma_size = ALIGN(ctx->img_width,
-                               S5P_FIMV_NV12MT_HALIGN) * ALIGN((ctx->img_height
-                               >> 1), S5P_FIMV_NV12MT_VALIGN);
-                       ctx->luma_size = ALIGN(ctx->luma_size,
-                                                       S5P_FIMV_NV12MT_SALIGN);
-                       ctx->chroma_size = ALIGN(ctx->chroma_size,
-                                                       S5P_FIMV_NV12MT_SALIGN);
-
-                       pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
-                       pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
-                       pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
-                       pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
-               }
+
+               s5p_mfc_hw_call(dev->mfc_ops, enc_calc_src_size, ctx);
+               pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
+               pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
+               pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
+               pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
+
                ctx->src_bufs_cnt = 0;
                ctx->output_state = QUEUE_FREE;
        } else {
@@ -1023,6 +1033,7 @@ out:
 static int vidioc_reqbufs(struct file *file, void *priv,
                                          struct v4l2_requestbuffers *reqbufs)
 {
+       struct s5p_mfc_dev *dev = video_drvdata(file);
        struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
        int ret = 0;
 
@@ -1042,12 +1053,16 @@ static int vidioc_reqbufs(struct file *file, void *priv,
                        return ret;
                }
                ctx->capture_state = QUEUE_BUFS_REQUESTED;
-               ret = s5p_mfc_alloc_codec_buffers(ctx);
-               if (ret) {
-                       mfc_err("Failed to allocate encoding buffers\n");
-                       reqbufs->count = 0;
-                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-                       return -ENOMEM;
+
+               if (!IS_MFCV6(dev)) {
+                       ret = s5p_mfc_hw_call(ctx->dev->mfc_ops,
+                                       alloc_codec_buffers, ctx);
+                       if (ret) {
+                               mfc_err("Failed to allocate encoding buffers\n");
+                               reqbufs->count = 0;
+                               ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+                               return -ENOMEM;
+                       }
                }
        } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
                if (ctx->output_state != QUEUE_FREE) {
@@ -1310,6 +1325,13 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
                        p->codec.h264.profile =
                                S5P_FIMV_ENC_PROFILE_H264_BASELINE;
                        break;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
+                       if (IS_MFCV6(dev))
+                               p->codec.h264.profile =
+                               S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE;
+                       else
+                               ret = -EINVAL;
+                       break;
                default:
                        ret = -EINVAL;
                }
@@ -1349,7 +1371,7 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
                p->codec.h264._8x8_transform = ctrl->val;
                break;
        case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
-               p->codec.h264.rc_mb = ctrl->val;
+               p->rc_mb = ctrl->val;
                break;
        case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
                p->codec.h264.rc_frame_qp = ctrl->val;
@@ -1500,7 +1522,7 @@ int vidioc_encoder_cmd(struct file *file, void *priv,
                        mfc_debug(2, "EOS: empty src queue, entering finishing state");
                        ctx->state = MFCINST_FINISHING;
                        spin_unlock_irqrestore(&dev->irqlock, flags);
-                       s5p_mfc_try_run(dev);
+                       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
                } else {
                        mfc_debug(2, "EOS: marking last buffer of stream");
                        buf = list_entry(ctx->src_queue.prev,
@@ -1583,6 +1605,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
                        unsigned int psize[], void *allocators[])
 {
        struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
 
        if (ctx->state != MFCINST_GOT_INST) {
                mfc_err("inavlid state: %d\n", ctx->state);
@@ -1611,8 +1634,17 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
                        *buf_count = MFC_MAX_BUFFERS;
                psize[0] = ctx->luma_size;
                psize[1] = ctx->chroma_size;
-               allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
-               allocators[1] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+               if (IS_MFCV6(dev)) {
+                       allocators[0] =
+                               ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+                       allocators[1] =
+                               ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+               } else {
+                       allocators[0] =
+                               ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+                       allocators[1] =
+                               ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+               }
        } else {
                mfc_err("inavlid queue type: %d\n", vq->type);
                return -EINVAL;
@@ -1715,7 +1747,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
        /* If context is ready then dev = work->data;schedule it to run */
        if (s5p_mfc_ctx_ready(ctx))
                set_work_bit_irqsave(ctx);
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
        return 0;
 }
 
@@ -1729,19 +1761,21 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
                ctx->state == MFCINST_RUNNING) &&
                dev->curr_ctx == ctx->num && dev->hw_lock) {
                ctx->state = MFCINST_ABORT;
-               s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_FRAME_DONE_RET,
+               s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_FRAME_DONE_RET,
                                          0);
        }
        ctx->state = MFCINST_FINISHED;
        spin_lock_irqsave(&dev->irqlock, flags);
        if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
+                               &ctx->vq_dst);
                INIT_LIST_HEAD(&ctx->dst_queue);
                ctx->dst_queue_cnt = 0;
        }
        if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
                cleanup_ref_queue(ctx);
-               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
+                               &ctx->vq_src);
                INIT_LIST_HEAD(&ctx->src_queue);
                ctx->src_queue_cnt = 0;
        }
@@ -1782,7 +1816,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
        }
        if (s5p_mfc_ctx_ready(ctx))
                set_work_bit_irqsave(ctx);
-       s5p_mfc_try_run(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
 }
 
 static struct vb2_ops s5p_mfc_enc_qops = {
@@ -1880,3 +1914,13 @@ void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx)
        for (i = 0; i < NUM_CTRLS; i++)
                ctx->ctrls[i] = NULL;
 }
+
+void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx)
+{
+       struct v4l2_format f;
+       f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_ENC;
+       ctx->src_fmt = find_format(&f, MFC_FMT_RAW);
+       f.fmt.pix_mp.pixelformat = DEF_DST_FMT_ENC;
+       ctx->dst_fmt = find_format(&f, MFC_FMT_ENC);
+}
+
index ca9fd66bd310a287ff015ee3e041e3b3ccae5518..5118d46b3a9ea767acd6290a6b5a3d550aabc905 100644 (file)
@@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void);
 struct s5p_mfc_fmt *get_enc_def_fmt(bool src);
 int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx);
 void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx);
 
 #endif /* S5P_MFC_ENC_H_  */
index 37860e299021dddfd16f28f967e7412fb88d6ba5..5b8f0e085e6d0fe9e8460569bf095ec79f903d1d 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/io.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
-#include "regs-mfc.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_intr.h"
@@ -28,7 +27,7 @@ int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
 
        ret = wait_event_interruptible_timeout(dev->queue,
                (dev->int_cond && (dev->int_type == command
-               || dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
+               || dev->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
                msecs_to_jiffies(MFC_INT_TIMEOUT));
        if (ret == 0) {
                mfc_err("Interrupt (dev->int_type:%d, command:%d) timed out\n",
@@ -40,7 +39,7 @@ int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
        }
        mfc_debug(1, "Finished waiting (dev->int_type:%d, command: %d)\n",
                                                        dev->int_type, command);
-       if (dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET)
+       if (dev->int_type == S5P_MFC_R2H_CMD_ERR_RET)
                return 1;
        return 0;
 }
@@ -60,12 +59,12 @@ int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
        if (interrupt) {
                ret = wait_event_interruptible_timeout(ctx->queue,
                                (ctx->int_cond && (ctx->int_type == command
-                       || ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
+                       || ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
                                        msecs_to_jiffies(MFC_INT_TIMEOUT));
        } else {
                ret = wait_event_timeout(ctx->queue,
                                (ctx->int_cond && (ctx->int_type == command
-                       || ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
+                       || ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
                                        msecs_to_jiffies(MFC_INT_TIMEOUT));
        }
        if (ret == 0) {
@@ -78,7 +77,7 @@ int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
        }
        mfc_debug(1, "Finished waiting (ctx->int_type:%d, command: %d)\n",
                                                        ctx->int_type, command);
-       if (ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)
+       if (ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)
                return 1;
        return 0;
 }
index 767a51271dc248f8f7663545ae4e101acee9ea39..6932e90d4065470c00cccb8b5f31987152a32df1 100644 (file)
@@ -1,10 +1,10 @@
 /*
- * drivers/media/platform/samsung/mfc5/s5p_mfc_opr.c
+ * drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
  *
  * Samsung MFC (Multi Function Codec - FIMV) driver
  * This file contains hw related functions.
  *
- * Kamil Debski, Copyright (c) 2011 Samsung Electronics
+ * Kamil Debski, Copyright (c) 2012 Samsung Electronics Co., Ltd.
  * http://www.samsung.com/
  *
  * This program is free software; you can redistribute it and/or modify
  * published by the Free Software Foundation.
  */
 
-#include "regs-mfc.h"
-#include "s5p_mfc_cmd.h"
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_ctrl.h"
-#include "s5p_mfc_debug.h"
-#include "s5p_mfc_intr.h"
 #include "s5p_mfc_opr.h"
-#include "s5p_mfc_pm.h"
-#include "s5p_mfc_shm.h"
-#include <asm/cacheflush.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/firmware.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
+#include "s5p_mfc_opr_v5.h"
+#include "s5p_mfc_opr_v6.h"
 
-#define OFFSETA(x)             (((x) - dev->bank1) >> MFC_OFFSET_SHIFT)
-#define OFFSETB(x)             (((x) - dev->bank2) >> MFC_OFFSET_SHIFT)
+static struct s5p_mfc_hw_ops *s5p_mfc_ops;
 
-/* Allocate temporary buffers for decoding */
-int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx)
+void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev)
 {
-       void *desc_virt;
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       ctx->desc_buf = vb2_dma_contig_memops.alloc(
-                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE);
-       if (IS_ERR_VALUE((int)ctx->desc_buf)) {
-               ctx->desc_buf = NULL;
-               mfc_err("Allocating DESC buffer failed\n");
-               return -ENOMEM;
-       }
-       ctx->desc_phys = s5p_mfc_mem_cookie(
-                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf);
-       BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
-       desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
-       if (desc_virt == NULL) {
-               vb2_dma_contig_memops.put(ctx->desc_buf);
-               ctx->desc_phys = 0;
-               ctx->desc_buf = NULL;
-               mfc_err("Remapping DESC buffer failed\n");
-               return -ENOMEM;
-       }
-       memset(desc_virt, 0, DESC_BUF_SIZE);
-       wmb();
-       return 0;
-}
-
-/* Release temporary buffers for decoding */
-void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
-{
-       if (ctx->desc_phys) {
-               vb2_dma_contig_memops.put(ctx->desc_buf);
-               ctx->desc_phys = 0;
-               ctx->desc_buf = NULL;
-       }
-}
-
-/* Allocate codec buffers */
-int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int enc_ref_y_size = 0;
-       unsigned int enc_ref_c_size = 0;
-       unsigned int guard_width, guard_height;
-
-       if (ctx->type == MFCINST_DECODER) {
-               mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
-                         ctx->luma_size, ctx->chroma_size, ctx->mv_size);
-               mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
-       } else if (ctx->type == MFCINST_ENCODER) {
-               enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
-                       * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
-               enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
-
-               if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) {
-                       enc_ref_c_size = ALIGN(ctx->img_width,
-                                               S5P_FIMV_NV12MT_HALIGN)
-                                               * ALIGN(ctx->img_height >> 1,
-                                               S5P_FIMV_NV12MT_VALIGN);
-                       enc_ref_c_size = ALIGN(enc_ref_c_size,
-                                                       S5P_FIMV_NV12MT_SALIGN);
-               } else {
-                       guard_width = ALIGN(ctx->img_width + 16,
-                                                       S5P_FIMV_NV12MT_HALIGN);
-                       guard_height = ALIGN((ctx->img_height >> 1) + 4,
-                                                       S5P_FIMV_NV12MT_VALIGN);
-                       enc_ref_c_size = ALIGN(guard_width * guard_height,
-                                              S5P_FIMV_NV12MT_SALIGN);
-               }
-               mfc_debug(2, "recon luma size: %d chroma size: %d\n",
-                         enc_ref_y_size, enc_ref_c_size);
+       if (IS_MFCV6(dev)) {
+               s5p_mfc_ops = s5p_mfc_init_hw_ops_v6();
+               dev->warn_start = S5P_FIMV_ERR_WARNINGS_START_V6;
        } else {
-               return -EINVAL;
-       }
-       /* Codecs have different memory requirements */
-       switch (ctx->codec_mode) {
-       case S5P_FIMV_CODEC_H264_DEC:
-               ctx->bank1_size =
-                   ALIGN(S5P_FIMV_DEC_NB_IP_SIZE +
-                                       S5P_FIMV_DEC_VERT_NB_MV_SIZE,
-                                       S5P_FIMV_DEC_BUF_ALIGN);
-               ctx->bank2_size = ctx->total_dpb_count * ctx->mv_size;
-               break;
-       case S5P_FIMV_CODEC_MPEG4_DEC:
-               ctx->bank1_size =
-                   ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE +
-                                    S5P_FIMV_DEC_UPNB_MV_SIZE +
-                                    S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
-                                    S5P_FIMV_DEC_STX_PARSER_SIZE +
-                                    S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE,
-                                    S5P_FIMV_DEC_BUF_ALIGN);
-               ctx->bank2_size = 0;
-               break;
-       case S5P_FIMV_CODEC_VC1RCV_DEC:
-       case S5P_FIMV_CODEC_VC1_DEC:
-               ctx->bank1_size =
-                   ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
-                            S5P_FIMV_DEC_UPNB_MV_SIZE +
-                            S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
-                            S5P_FIMV_DEC_NB_DCAC_SIZE +
-                            3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE,
-                            S5P_FIMV_DEC_BUF_ALIGN);
-               ctx->bank2_size = 0;
-               break;
-       case S5P_FIMV_CODEC_MPEG2_DEC:
-               ctx->bank1_size = 0;
-               ctx->bank2_size = 0;
-               break;
-       case S5P_FIMV_CODEC_H263_DEC:
-               ctx->bank1_size =
-                   ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
-                            S5P_FIMV_DEC_UPNB_MV_SIZE +
-                            S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
-                            S5P_FIMV_DEC_NB_DCAC_SIZE,
-                            S5P_FIMV_DEC_BUF_ALIGN);
-               ctx->bank2_size = 0;
-               break;
-       case S5P_FIMV_CODEC_H264_ENC:
-               ctx->bank1_size = (enc_ref_y_size * 2) +
-                                  S5P_FIMV_ENC_UPMV_SIZE +
-                                  S5P_FIMV_ENC_COLFLG_SIZE +
-                                  S5P_FIMV_ENC_INTRAMD_SIZE +
-                                  S5P_FIMV_ENC_NBORINFO_SIZE;
-               ctx->bank2_size = (enc_ref_y_size * 2) +
-                                  (enc_ref_c_size * 4) +
-                                  S5P_FIMV_ENC_INTRAPRED_SIZE;
-               break;
-       case S5P_FIMV_CODEC_MPEG4_ENC:
-               ctx->bank1_size = (enc_ref_y_size * 2) +
-                                  S5P_FIMV_ENC_UPMV_SIZE +
-                                  S5P_FIMV_ENC_COLFLG_SIZE +
-                                  S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               ctx->bank2_size = (enc_ref_y_size * 2) +
-                                  (enc_ref_c_size * 4);
-               break;
-       case S5P_FIMV_CODEC_H263_ENC:
-               ctx->bank1_size = (enc_ref_y_size * 2) +
-                                  S5P_FIMV_ENC_UPMV_SIZE +
-                                  S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               ctx->bank2_size = (enc_ref_y_size * 2) +
-                                  (enc_ref_c_size * 4);
-               break;
-       default:
-               break;
-       }
-       /* Allocate only if memory from bank 1 is necessary */
-       if (ctx->bank1_size > 0) {
-               ctx->bank1_buf = vb2_dma_contig_memops.alloc(
-               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
-               if (IS_ERR(ctx->bank1_buf)) {
-                       ctx->bank1_buf = NULL;
-                       printk(KERN_ERR
-                              "Buf alloc for decoding failed (port A)\n");
-                       return -ENOMEM;
-               }
-               ctx->bank1_phys = s5p_mfc_mem_cookie(
-               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
-               BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
-       }
-       /* Allocate only if memory from bank 2 is necessary */
-       if (ctx->bank2_size > 0) {
-               ctx->bank2_buf = vb2_dma_contig_memops.alloc(
-               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_size);
-               if (IS_ERR(ctx->bank2_buf)) {
-                       ctx->bank2_buf = NULL;
-                       mfc_err("Buf alloc for decoding failed (port B)\n");
-                       return -ENOMEM;
-               }
-               ctx->bank2_phys = s5p_mfc_mem_cookie(
-               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_buf);
-               BUG_ON(ctx->bank2_phys & ((1 << MFC_BANK2_ALIGN_ORDER) - 1));
-       }
-       return 0;
-}
-
-/* Release buffers allocated for codec */
-void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx)
-{
-       if (ctx->bank1_buf) {
-               vb2_dma_contig_memops.put(ctx->bank1_buf);
-               ctx->bank1_buf = NULL;
-               ctx->bank1_phys = 0;
-               ctx->bank1_size = 0;
-       }
-       if (ctx->bank2_buf) {
-               vb2_dma_contig_memops.put(ctx->bank2_buf);
-               ctx->bank2_buf = NULL;
-               ctx->bank2_phys = 0;
-               ctx->bank2_size = 0;
+               s5p_mfc_ops = s5p_mfc_init_hw_ops_v5();
+               dev->warn_start = S5P_FIMV_ERR_WARNINGS_START;
        }
+       dev->mfc_ops = s5p_mfc_ops;
 }
-
-/* Allocate memory for instance data buffer */
-int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx)
-{
-       void *context_virt;
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
-               ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
-               ctx->ctx_size = MFC_H264_CTX_BUF_SIZE;
-       else
-               ctx->ctx_size = MFC_CTX_BUF_SIZE;
-       ctx->ctx_buf = vb2_dma_contig_memops.alloc(
-               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
-       if (IS_ERR(ctx->ctx_buf)) {
-               mfc_err("Allocating context buffer failed\n");
-               ctx->ctx_phys = 0;
-               ctx->ctx_buf = NULL;
-               return -ENOMEM;
-       }
-       ctx->ctx_phys = s5p_mfc_mem_cookie(
-               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_buf);
-       BUG_ON(ctx->ctx_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
-       ctx->ctx_ofs = OFFSETA(ctx->ctx_phys);
-       context_virt = vb2_dma_contig_memops.vaddr(ctx->ctx_buf);
-       if (context_virt == NULL) {
-               mfc_err("Remapping instance buffer failed\n");
-               vb2_dma_contig_memops.put(ctx->ctx_buf);
-               ctx->ctx_phys = 0;
-               ctx->ctx_buf = NULL;
-               return -ENOMEM;
-       }
-       /* Zero content of the allocated memory */
-       memset(context_virt, 0, ctx->ctx_size);
-       wmb();
-       if (s5p_mfc_init_shm(ctx) < 0) {
-               vb2_dma_contig_memops.put(ctx->ctx_buf);
-               ctx->ctx_phys = 0;
-               ctx->ctx_buf = NULL;
-               return -ENOMEM;
-       }
-       return 0;
-}
-
-/* Release instance buffer */
-void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx)
-{
-       if (ctx->ctx_buf) {
-               vb2_dma_contig_memops.put(ctx->ctx_buf);
-               ctx->ctx_phys = 0;
-               ctx->ctx_buf = NULL;
-       }
-       if (ctx->shm_alloc) {
-               vb2_dma_contig_memops.put(ctx->shm_alloc);
-               ctx->shm_alloc = NULL;
-               ctx->shm = NULL;
-       }
-}
-
-/* Set registers for decoding temporary buffers */
-void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_write(dev, OFFSETA(ctx->desc_phys), S5P_FIMV_SI_CH0_DESC_ADR);
-       mfc_write(dev, DESC_BUF_SIZE, S5P_FIMV_SI_CH0_DESC_SIZE);
-}
-
-/* Set registers for shared buffer */
-static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       mfc_write(dev, ctx->shm_ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
-}
-
-/* Set registers for decoding stream buffer */
-int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
-                 unsigned int start_num_byte, unsigned int buf_size)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
-       mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
-       mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
-       s5p_mfc_write_shm(ctx, start_num_byte, START_BYTE_NUM);
-       return 0;
-}
-
-/* Set decoding frame buffer */
-int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx)
-{
-       unsigned int frame_size, i;
-       unsigned int frame_size_ch, frame_size_mv;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int dpb;
-       size_t buf_addr1, buf_addr2;
-       int buf_size1, buf_size2;
-
-       buf_addr1 = ctx->bank1_phys;
-       buf_size1 = ctx->bank1_size;
-       buf_addr2 = ctx->bank2_phys;
-       buf_size2 = ctx->bank2_size;
-       dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
-                                               ~S5P_FIMV_DPB_COUNT_MASK;
-       mfc_write(dev, ctx->total_dpb_count | dpb,
-                                               S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
-       s5p_mfc_set_shared_buffer(ctx);
-       switch (ctx->codec_mode) {
-       case S5P_FIMV_CODEC_H264_DEC:
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                               S5P_FIMV_H264_VERT_NB_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR);
-               buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE;
-               break;
-       case S5P_FIMV_CODEC_MPEG4_DEC:
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_NB_DCAC_ADR);
-               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_NB_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR);
-               buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_OT_LINE_ADR);
-               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               break;
-       case S5P_FIMV_CODEC_H263_DEC:
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR);
-               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_NB_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR);
-               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
-               break;
-       case S5P_FIMV_CODEC_VC1_DEC:
-       case S5P_FIMV_CODEC_VC1RCV_DEC:
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR);
-               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR);
-               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE3_ADR);
-               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE2_ADR);
-               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE1_ADR);
-               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               break;
-       case S5P_FIMV_CODEC_MPEG2_DEC:
-               break;
-       default:
-               mfc_err("Unknown codec for decoding (%x)\n",
-                       ctx->codec_mode);
-               return -EINVAL;
-               break;
-       }
-       frame_size = ctx->luma_size;
-       frame_size_ch = ctx->chroma_size;
-       frame_size_mv = ctx->mv_size;
-       mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size, frame_size_ch,
-                                                               frame_size_mv);
-       for (i = 0; i < ctx->total_dpb_count; i++) {
-               /* Bank2 */
-               mfc_debug(2, "Luma %d: %x\n", i,
-                                       ctx->dst_bufs[i].cookie.raw.luma);
-               mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma),
-                                               S5P_FIMV_DEC_LUMA_ADR + i * 4);
-               mfc_debug(2, "\tChroma %d: %x\n", i,
-                                       ctx->dst_bufs[i].cookie.raw.chroma);
-               mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma),
-                                              S5P_FIMV_DEC_CHROMA_ADR + i * 4);
-               if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
-                       mfc_debug(2, "\tBuf2: %x, size: %d\n",
-                                                       buf_addr2, buf_size2);
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                                               S5P_FIMV_H264_MV_ADR + i * 4);
-                       buf_addr2 += frame_size_mv;
-                       buf_size2 -= frame_size_mv;
-               }
-       }
-       mfc_debug(2, "Buf1: %u, buf_size1: %d\n", buf_addr1, buf_size1);
-       mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n",
-                       buf_size1,  buf_size2, ctx->total_dpb_count);
-       if (buf_size1 < 0 || buf_size2 < 0) {
-               mfc_debug(2, "Not enough memory has been allocated\n");
-               return -ENOMEM;
-       }
-       s5p_mfc_write_shm(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
-       s5p_mfc_write_shm(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
-       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC)
-               s5p_mfc_write_shm(ctx, frame_size_mv, ALLOC_MV_SIZE);
-       mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
-                                       << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
-                                               S5P_FIMV_SI_CH0_INST_ID);
-       return 0;
-}
-
-/* Set registers for encoding stream buffer */
-int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
-               unsigned long addr, unsigned int size)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR);
-       mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE);
-       return 0;
-}
-
-void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
-               unsigned long y_addr, unsigned long c_addr)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR);
-       mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR);
-}
-
-void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
-               unsigned long *y_addr, unsigned long *c_addr)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       *y_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR)
-                                                       << MFC_OFFSET_SHIFT);
-       *c_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR)
-                                                       << MFC_OFFSET_SHIFT);
-}
-
-/* Set encoding ref & codec buffer */
-int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       size_t buf_addr1, buf_addr2;
-       size_t buf_size1, buf_size2;
-       unsigned int enc_ref_y_size, enc_ref_c_size;
-       unsigned int guard_width, guard_height;
-       int i;
-
-       buf_addr1 = ctx->bank1_phys;
-       buf_size1 = ctx->bank1_size;
-       buf_addr2 = ctx->bank2_phys;
-       buf_size2 = ctx->bank2_size;
-       enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
-               * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
-       enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
-       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) {
-               enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
-                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
-               enc_ref_c_size = ALIGN(enc_ref_c_size, S5P_FIMV_NV12MT_SALIGN);
-       } else {
-               guard_width = ALIGN(ctx->img_width + 16,
-                                               S5P_FIMV_NV12MT_HALIGN);
-               guard_height = ALIGN((ctx->img_height >> 1) + 4,
-                                               S5P_FIMV_NV12MT_VALIGN);
-               enc_ref_c_size = ALIGN(guard_width * guard_height,
-                                      S5P_FIMV_NV12MT_SALIGN);
-       }
-       mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", buf_size1, buf_size2);
-       switch (ctx->codec_mode) {
-       case S5P_FIMV_CODEC_H264_ENC:
-               for (i = 0; i < 2; i++) {
-                       mfc_write(dev, OFFSETA(buf_addr1),
-                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
-                       buf_addr1 += enc_ref_y_size;
-                       buf_size1 -= enc_ref_y_size;
-
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_y_size;
-                       buf_size2 -= enc_ref_y_size;
-               }
-               for (i = 0; i < 4; i++) {
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_c_size;
-                       buf_size2 -= enc_ref_c_size;
-               }
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR);
-               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                       S5P_FIMV_H264_COZERO_FLAG_ADR);
-               buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                       S5P_FIMV_H264_UP_INTRA_MD_ADR);
-               buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE;
-               mfc_write(dev, OFFSETB(buf_addr2),
-                                       S5P_FIMV_H264_UP_INTRA_PRED_ADR);
-               buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE;
-               buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                       S5P_FIMV_H264_NBOR_INFO_ADR);
-               buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE;
-               mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
-                       buf_size1, buf_size2);
-               break;
-       case S5P_FIMV_CODEC_MPEG4_ENC:
-               for (i = 0; i < 2; i++) {
-                       mfc_write(dev, OFFSETA(buf_addr1),
-                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
-                       buf_addr1 += enc_ref_y_size;
-                       buf_size1 -= enc_ref_y_size;
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_y_size;
-                       buf_size2 -= enc_ref_y_size;
-               }
-               for (i = 0; i < 4; i++) {
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_c_size;
-                       buf_size2 -= enc_ref_c_size;
-               }
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR);
-               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                               S5P_FIMV_MPEG4_COZERO_FLAG_ADR);
-               buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                               S5P_FIMV_MPEG4_ACDC_COEF_ADR);
-               buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
-                       buf_size1, buf_size2);
-               break;
-       case S5P_FIMV_CODEC_H263_ENC:
-               for (i = 0; i < 2; i++) {
-                       mfc_write(dev, OFFSETA(buf_addr1),
-                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
-                       buf_addr1 += enc_ref_y_size;
-                       buf_size1 -= enc_ref_y_size;
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_y_size;
-                       buf_size2 -= enc_ref_y_size;
-               }
-               for (i = 0; i < 4; i++) {
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_c_size;
-                       buf_size2 -= enc_ref_c_size;
-               }
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR);
-               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_ACDC_COEF_ADR);
-               buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
-                       buf_size1, buf_size2);
-               break;
-       default:
-               mfc_err("Unknown codec set for encoding: %d\n",
-                       ctx->codec_mode);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       unsigned int reg;
-       unsigned int shm;
-
-       /* width */
-       mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX);
-       /* height */
-       mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX);
-       /* pictype : enable, IDR period */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       reg |= (1 << 18);
-       reg &= ~(0xFFFF);
-       reg |= p->gop_size;
-       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON);
-       /* multi-slice control */
-       /* multi-slice MB number or bit size */
-       mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL);
-       if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
-               mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB);
-       } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
-               mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT);
-       } else {
-               mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB);
-               mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT);
-       }
-       /* cyclic intra refresh */
-       mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL);
-       /* memory structure cur. frame */
-       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
-               mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
-       else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
-               mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
-       /* padding control & value */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL);
-       if (p->pad) {
-               /** enable */
-               reg |= (1 << 31);
-               /** cr value */
-               reg &= ~(0xFF << 16);
-               reg |= (p->pad_cr << 16);
-               /** cb value */
-               reg &= ~(0xFF << 8);
-               reg |= (p->pad_cb << 8);
-               /** y value */
-               reg &= ~(0xFF);
-               reg |= (p->pad_luma);
-       } else {
-               /** disable & all value clear */
-               reg = 0;
-       }
-       mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL);
-       /* rate control config. */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
-       /** frame-level rate control */
-       reg &= ~(0x1 << 9);
-       reg |= (p->rc_frame << 9);
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
-       /* bit rate */
-       if (p->rc_frame)
-               mfc_write(dev, p->rc_bitrate,
-                       S5P_FIMV_ENC_RC_BIT_RATE);
-       else
-               mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE);
-       /* reaction coefficient */
-       if (p->rc_frame)
-               mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
-       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
-       /* seq header ctrl */
-       shm &= ~(0x1 << 3);
-       shm |= (p->seq_hdr_mode << 3);
-       /* frame skip mode */
-       shm &= ~(0x3 << 1);
-       shm |= (p->frame_skip_mode << 1);
-       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
-       /* fixed target bit */
-       s5p_mfc_write_shm(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
-       unsigned int reg;
-       unsigned int shm;
-
-       s5p_mfc_set_enc_params(ctx);
-       /* pictype : number of B */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       /* num_b_frame - 0 ~ 2 */
-       reg &= ~(0x3 << 16);
-       reg |= (p->num_b_frame << 16);
-       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       /* profile & level */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
-       /* level */
-       reg &= ~(0xFF << 8);
-       reg |= (p_264->level << 8);
-       /* profile - 0 ~ 2 */
-       reg &= ~(0x3F);
-       reg |= p_264->profile;
-       mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
-       /* interlace  */
-       mfc_write(dev, p->interlace, S5P_FIMV_ENC_PIC_STRUCT);
-       /* height */
-       if (p->interlace)
-               mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
-       /* loopfilter ctrl */
-       mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
-       /* loopfilter alpha offset */
-       if (p_264->loop_filter_alpha < 0) {
-               reg = 0x10;
-               reg |= (0xFF - p_264->loop_filter_alpha) + 1;
-       } else {
-               reg = 0x00;
-               reg |= (p_264->loop_filter_alpha & 0xF);
-       }
-       mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF);
-       /* loopfilter beta offset */
-       if (p_264->loop_filter_beta < 0) {
-               reg = 0x10;
-               reg |= (0xFF - p_264->loop_filter_beta) + 1;
-       } else {
-               reg = 0x00;
-               reg |= (p_264->loop_filter_beta & 0xF);
-       }
-       mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF);
-       /* entropy coding mode */
-       if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)
-               mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE);
-       else
-               mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE);
-       /* number of ref. picture */
-       reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF);
-       /* num of ref. pictures of P */
-       reg &= ~(0x3 << 5);
-       reg |= (p_264->num_ref_pic_4p << 5);
-       /* max number of ref. pictures */
-       reg &= ~(0x1F);
-       reg |= p_264->max_ref_pic;
-       mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF);
-       /* 8x8 transform enable */
-       mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG);
-       /* rate control config. */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
-       /* macroblock level rate control */
-       reg &= ~(0x1 << 8);
-       reg |= (p_264->rc_mb << 8);
-       /* frame QP */
-       reg &= ~(0x3F);
-       reg |= p_264->rc_frame_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
-       /* frame rate */
-       if (p->rc_frame && p->rc_framerate_denom)
-               mfc_write(dev, p->rc_framerate_num * 1000
-                       / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
-       else
-               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
-       /* max & min value of QP */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
-       /* max QP */
-       reg &= ~(0x3F << 8);
-       reg |= (p_264->rc_max_qp << 8);
-       /* min QP */
-       reg &= ~(0x3F);
-       reg |= p_264->rc_min_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
-       /* macroblock adaptive scaling features */
-       if (p_264->rc_mb) {
-               reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
-               /* dark region */
-               reg &= ~(0x1 << 3);
-               reg |= (p_264->rc_mb_dark << 3);
-               /* smooth region */
-               reg &= ~(0x1 << 2);
-               reg |= (p_264->rc_mb_smooth << 2);
-               /* static region */
-               reg &= ~(0x1 << 1);
-               reg |= (p_264->rc_mb_static << 1);
-               /* high activity region */
-               reg &= ~(0x1);
-               reg |= p_264->rc_mb_activity;
-               mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
-       }
-       if (!p->rc_frame &&
-           !p_264->rc_mb) {
-               shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
-               shm &= ~(0xFFF);
-               shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
-               shm |= (p_264->rc_p_frame_qp & 0x3F);
-               s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
-       }
-       /* extended encoder ctrl */
-       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
-       /* AR VUI control */
-       shm &= ~(0x1 << 15);
-       shm |= (p_264->vui_sar << 1);
-       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
-       if (p_264->vui_sar) {
-               /* aspect ration IDC */
-               shm = s5p_mfc_read_shm(ctx, SAMPLE_ASPECT_RATIO_IDC);
-               shm &= ~(0xFF);
-               shm |= p_264->vui_sar_idc;
-               s5p_mfc_write_shm(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
-               if (p_264->vui_sar_idc == 0xFF) {
-                       /* sample  AR info */
-                       shm = s5p_mfc_read_shm(ctx, EXTENDED_SAR);
-                       shm &= ~(0xFFFFFFFF);
-                       shm |= p_264->vui_ext_sar_width << 16;
-                       shm |= p_264->vui_ext_sar_height;
-                       s5p_mfc_write_shm(ctx, shm, EXTENDED_SAR);
-               }
-       }
-       /* intra picture period for H.264 */
-       shm = s5p_mfc_read_shm(ctx, H264_I_PERIOD);
-       /* control */
-       shm &= ~(0x1 << 16);
-       shm |= (p_264->open_gop << 16);
-       /* value */
-       if (p_264->open_gop) {
-               shm &= ~(0xFFFF);
-               shm |= p_264->open_gop_size;
-       }
-       s5p_mfc_write_shm(ctx, shm, H264_I_PERIOD);
-       /* extended encoder ctrl */
-       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
-       /* vbv buffer size */
-       if (p->frame_skip_mode ==
-                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
-               shm &= ~(0xFFFF << 16);
-               shm |= (p_264->cpb_size << 16);
-       }
-       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
-       unsigned int reg;
-       unsigned int shm;
-       unsigned int framerate;
-
-       s5p_mfc_set_enc_params(ctx);
-       /* pictype : number of B */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       /* num_b_frame - 0 ~ 2 */
-       reg &= ~(0x3 << 16);
-       reg |= (p->num_b_frame << 16);
-       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       /* profile & level */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
-       /* level */
-       reg &= ~(0xFF << 8);
-       reg |= (p_mpeg4->level << 8);
-       /* profile - 0 ~ 2 */
-       reg &= ~(0x3F);
-       reg |= p_mpeg4->profile;
-       mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
-       /* quarter_pixel */
-       mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
-       /* qp */
-       if (!p->rc_frame) {
-               shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
-               shm &= ~(0xFFF);
-               shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
-               shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
-               s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
-       }
-       /* frame rate */
-       if (p->rc_frame) {
-               if (p->rc_framerate_denom > 0) {
-                       framerate = p->rc_framerate_num * 1000 /
-                                               p->rc_framerate_denom;
-                       mfc_write(dev, framerate,
-                               S5P_FIMV_ENC_RC_FRAME_RATE);
-                       shm = s5p_mfc_read_shm(ctx, RC_VOP_TIMING);
-                       shm &= ~(0xFFFFFFFF);
-                       shm |= (1 << 31);
-                       shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
-                       shm |= (p->rc_framerate_denom & 0xFFFF);
-                       s5p_mfc_write_shm(ctx, shm, RC_VOP_TIMING);
-               }
-       } else {
-               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
-       }
-       /* rate control config. */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
-       /* frame QP */
-       reg &= ~(0x3F);
-       reg |= p_mpeg4->rc_frame_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
-       /* max & min value of QP */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
-       /* max QP */
-       reg &= ~(0x3F << 8);
-       reg |= (p_mpeg4->rc_max_qp << 8);
-       /* min QP */
-       reg &= ~(0x3F);
-       reg |= p_mpeg4->rc_min_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
-       /* extended encoder ctrl */
-       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
-       /* vbv buffer size */
-       if (p->frame_skip_mode ==
-                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
-               shm &= ~(0xFFFF << 16);
-               shm |= (p->vbv_size << 16);
-       }
-       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
-       unsigned int reg;
-       unsigned int shm;
-
-       s5p_mfc_set_enc_params(ctx);
-       /* qp */
-       if (!p->rc_frame) {
-               shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
-               shm &= ~(0xFFF);
-               shm |= (p_h263->rc_p_frame_qp & 0x3F);
-               s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
-       }
-       /* frame rate */
-       if (p->rc_frame && p->rc_framerate_denom)
-               mfc_write(dev, p->rc_framerate_num * 1000
-                       / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
-       else
-               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
-       /* rate control config. */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
-       /* frame QP */
-       reg &= ~(0x3F);
-       reg |= p_h263->rc_frame_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
-       /* max & min value of QP */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
-       /* max QP */
-       reg &= ~(0x3F << 8);
-       reg |= (p_h263->rc_max_qp << 8);
-       /* min QP */
-       reg &= ~(0x3F);
-       reg |= p_h263->rc_min_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
-       /* extended encoder ctrl */
-       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
-       /* vbv buffer size */
-       if (p->frame_skip_mode ==
-                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
-               shm &= ~(0xFFFF << 16);
-               shm |= (p->vbv_size << 16);
-       }
-       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
-       return 0;
-}
-
-/* Initialize decoding */
-int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       s5p_mfc_set_shared_buffer(ctx);
-       /* Setup loop filter, for decoding this is only valid for MPEG4 */
-       if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_DEC)
-               mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL);
-       else
-               mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL);
-       mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) <<
-               S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable <<
-               S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay &
-               S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT),
-               S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
-       mfc_write(dev,
-       ((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
-                               | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
-       return 0;
-}
-
-static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int dpb;
-
-       if (flush)
-               dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (
-                       S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
-       else
-               dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
-                       ~(S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
-       mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
-}
-
-/* Decode a single frame */
-int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx,
-                                       enum s5p_mfc_decode_arg last_frame)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF);
-       s5p_mfc_set_shared_buffer(ctx);
-       s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
-       /* Issue different commands to instance basing on whether it
-        * is the last frame or not. */
-       switch (last_frame) {
-       case MFC_DEC_FRAME:
-               mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK) <<
-               S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
-               break;
-       case MFC_DEC_LAST_FRAME:
-               mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) <<
-               S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
-               break;
-       case MFC_DEC_RES_CHANGE:
-               mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC &
-               S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
-               S5P_FIMV_SI_CH0_INST_ID);
-               break;
-       }
-       mfc_debug(2, "Decoding a usual frame\n");
-       return 0;
-}
-
-int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
-               s5p_mfc_set_enc_params_h264(ctx);
-       else if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_ENC)
-               s5p_mfc_set_enc_params_mpeg4(ctx);
-       else if (ctx->codec_mode == S5P_FIMV_CODEC_H263_ENC)
-               s5p_mfc_set_enc_params_h263(ctx);
-       else {
-               mfc_err("Unknown codec for encoding (%x)\n",
-                       ctx->codec_mode);
-               return -EINVAL;
-       }
-       s5p_mfc_set_shared_buffer(ctx);
-       mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) |
-               (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
-       return 0;
-}
-
-/* Encode a single frame */
-int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       int cmd;
-       /* memory structure cur. frame */
-       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
-               mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
-       else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
-               mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
-       s5p_mfc_set_shared_buffer(ctx);
-
-       if (ctx->state == MFCINST_FINISHING)
-               cmd = S5P_FIMV_CH_LAST_FRAME;
-       else
-               cmd = S5P_FIMV_CH_FRAME_START;
-       mfc_write(dev, ((cmd & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
-                               | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
-
-       return 0;
-}
-
-static int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
-{
-       unsigned long flags;
-       int new_ctx;
-       int cnt;
-
-       spin_lock_irqsave(&dev->condlock, flags);
-       new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
-       cnt = 0;
-       while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
-               new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
-               if (++cnt > MFC_NUM_CONTEXTS) {
-                       /* No contexts to run */
-                       spin_unlock_irqrestore(&dev->condlock, flags);
-                       return -EAGAIN;
-               }
-       }
-       spin_unlock_irqrestore(&dev->condlock, flags);
-       return new_ctx;
-}
-
-static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       s5p_mfc_set_dec_stream_buffer(ctx, 0, 0, 0);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       s5p_mfc_decode_one_frame(ctx, MFC_DEC_RES_CHANGE);
-}
-
-static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *temp_vb;
-       unsigned long flags;
-       unsigned int index;
-
-       spin_lock_irqsave(&dev->irqlock, flags);
-       /* Frames are being decoded */
-       if (list_empty(&ctx->src_queue)) {
-               mfc_debug(2, "No src buffers\n");
-               spin_unlock_irqrestore(&dev->irqlock, flags);
-               return -EAGAIN;
-       }
-       /* Get the next source buffer */
-       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       temp_vb->flags |= MFC_BUF_FLAG_USED;
-       s5p_mfc_set_dec_stream_buffer(ctx,
-               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), ctx->consumed_stream,
-                                       temp_vb->b->v4l2_planes[0].bytesused);
-       spin_unlock_irqrestore(&dev->irqlock, flags);
-       index = temp_vb->b->v4l2_buf.index;
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
-               last_frame = MFC_DEC_LAST_FRAME;
-               mfc_debug(2, "Setting ctx->state to FINISHING\n");
-               ctx->state = MFCINST_FINISHING;
-       }
-       s5p_mfc_decode_one_frame(ctx, last_frame);
-       return 0;
-}
-
-static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
-       struct s5p_mfc_buf *dst_mb;
-       struct s5p_mfc_buf *src_mb;
-       unsigned long src_y_addr, src_c_addr, dst_addr;
-       unsigned int dst_size;
-
-       spin_lock_irqsave(&dev->irqlock, flags);
-       if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) {
-               mfc_debug(2, "no src buffers\n");
-               spin_unlock_irqrestore(&dev->irqlock, flags);
-               return -EAGAIN;
-       }
-       if (list_empty(&ctx->dst_queue)) {
-               mfc_debug(2, "no dst buffers\n");
-               spin_unlock_irqrestore(&dev->irqlock, flags);
-               return -EAGAIN;
-       }
-       if (list_empty(&ctx->src_queue)) {
-               /* send null frame */
-               s5p_mfc_set_enc_frame_buffer(ctx, dev->bank2, dev->bank2);
-               src_mb = NULL;
-       } else {
-               src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
-                                                                       list);
-               src_mb->flags |= MFC_BUF_FLAG_USED;
-               if (src_mb->b->v4l2_planes[0].bytesused == 0) {
-                       /* send null frame */
-                       s5p_mfc_set_enc_frame_buffer(ctx, dev->bank2,
-                                                               dev->bank2);
-                       ctx->state = MFCINST_FINISHING;
-               } else {
-                       src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
-                                                                       0);
-                       src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
-                                                                       1);
-                       s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr,
-                                                               src_c_addr);
-                       if (src_mb->flags & MFC_BUF_FLAG_EOS)
-                               ctx->state = MFCINST_FINISHING;
-               }
-       }
-       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
-       dst_mb->flags |= MFC_BUF_FLAG_USED;
-       dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
-       dst_size = vb2_plane_size(dst_mb->b, 0);
-       s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
-       spin_unlock_irqrestore(&dev->irqlock, flags);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       mfc_debug(2, "encoding buffer with index=%d state=%d",
-                       src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state);
-       s5p_mfc_encode_one_frame(ctx);
-       return 0;
-}
-
-static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
-       struct s5p_mfc_buf *temp_vb;
-
-       /* Initializing decoding - parsing header */
-       spin_lock_irqsave(&dev->irqlock, flags);
-       mfc_debug(2, "Preparing to init decoding\n");
-       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       s5p_mfc_set_dec_desc_buffer(ctx);
-       mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
-       s5p_mfc_set_dec_stream_buffer(ctx,
-                               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
-                               0, temp_vb->b->v4l2_planes[0].bytesused);
-       spin_unlock_irqrestore(&dev->irqlock, flags);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       s5p_mfc_init_decode(ctx);
-}
-
-static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
-       struct s5p_mfc_buf *dst_mb;
-       unsigned long dst_addr;
-       unsigned int dst_size;
-
-       s5p_mfc_set_enc_ref_buffer(ctx);
-       spin_lock_irqsave(&dev->irqlock, flags);
-       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
-       dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
-       dst_size = vb2_plane_size(dst_mb->b, 0);
-       s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
-       spin_unlock_irqrestore(&dev->irqlock, flags);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       s5p_mfc_init_encode(ctx);
-}
-
-static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
-       struct s5p_mfc_buf *temp_vb;
-       int ret;
-
-       /*
-        * Header was parsed now starting processing
-        * First set the output frame buffers
-        */
-       if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
-               mfc_err("It seems that not all destionation buffers were "
-                       "mmaped\nMFC requires that all destination are mmaped "
-                       "before starting processing\n");
-               return -EAGAIN;
-       }
-       spin_lock_irqsave(&dev->irqlock, flags);
-       if (list_empty(&ctx->src_queue)) {
-               mfc_err("Header has been deallocated in the middle of"
-                       " initialization\n");
-               spin_unlock_irqrestore(&dev->irqlock, flags);
-               return -EIO;
-       }
-       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
-       s5p_mfc_set_dec_stream_buffer(ctx,
-                               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
-                               0, temp_vb->b->v4l2_planes[0].bytesused);
-       spin_unlock_irqrestore(&dev->irqlock, flags);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       ret = s5p_mfc_set_dec_frame_buffer(ctx);
-       if (ret) {
-               mfc_err("Failed to alloc frame mem\n");
-               ctx->state = MFCINST_ERROR;
-       }
-       return ret;
-}
-
-/* Try running an operation on hardware */
-void s5p_mfc_try_run(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_ctx *ctx;
-       int new_ctx;
-       unsigned int ret = 0;
-
-       if (test_bit(0, &dev->enter_suspend)) {
-               mfc_debug(1, "Entering suspend so do not schedule any jobs\n");
-               return;
-       }
-       /* Check whether hardware is not running */
-       if (test_and_set_bit(0, &dev->hw_lock) != 0) {
-               /* This is perfectly ok, the scheduled ctx should wait */
-               mfc_debug(1, "Couldn't lock HW\n");
-               return;
-       }
-       /* Choose the context to run */
-       new_ctx = s5p_mfc_get_new_ctx(dev);
-       if (new_ctx < 0) {
-               /* No contexts to run */
-               if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
-                       mfc_err("Failed to unlock hardware\n");
-                       return;
-               }
-               mfc_debug(1, "No ctx is scheduled to be run\n");
-               return;
-       }
-       ctx = dev->ctx[new_ctx];
-       /* Got context to run in ctx */
-       /*
-        * Last frame has already been sent to MFC.
-        * Now obtaining frames from MFC buffer
-        */
-       s5p_mfc_clock_on();
-       if (ctx->type == MFCINST_DECODER) {
-               s5p_mfc_set_dec_desc_buffer(ctx);
-               switch (ctx->state) {
-               case MFCINST_FINISHING:
-                       s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME);
-                       break;
-               case MFCINST_RUNNING:
-                       ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
-                       break;
-               case MFCINST_INIT:
-                       s5p_mfc_clean_ctx_int_flags(ctx);
-                       ret = s5p_mfc_open_inst_cmd(ctx);
-                       break;
-               case MFCINST_RETURN_INST:
-                       s5p_mfc_clean_ctx_int_flags(ctx);
-                       ret = s5p_mfc_close_inst_cmd(ctx);
-                       break;
-               case MFCINST_GOT_INST:
-                       s5p_mfc_run_init_dec(ctx);
-                       break;
-               case MFCINST_HEAD_PARSED:
-                       ret = s5p_mfc_run_init_dec_buffers(ctx);
-                       mfc_debug(1, "head parsed\n");
-                       break;
-               case MFCINST_RES_CHANGE_INIT:
-                       s5p_mfc_run_res_change(ctx);
-                       break;
-               case MFCINST_RES_CHANGE_FLUSH:
-                       s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
-                       break;
-               case MFCINST_RES_CHANGE_END:
-                       mfc_debug(2, "Finished remaining frames after resolution change\n");
-                       ctx->capture_state = QUEUE_FREE;
-                       mfc_debug(2, "Will re-init the codec\n");
-                       s5p_mfc_run_init_dec(ctx);
-                       break;
-               default:
-                       ret = -EAGAIN;
-               }
-       } else if (ctx->type == MFCINST_ENCODER) {
-               switch (ctx->state) {
-               case MFCINST_FINISHING:
-               case MFCINST_RUNNING:
-                       ret = s5p_mfc_run_enc_frame(ctx);
-                       break;
-               case MFCINST_INIT:
-                       s5p_mfc_clean_ctx_int_flags(ctx);
-                       ret = s5p_mfc_open_inst_cmd(ctx);
-                       break;
-               case MFCINST_RETURN_INST:
-                       s5p_mfc_clean_ctx_int_flags(ctx);
-                       ret = s5p_mfc_close_inst_cmd(ctx);
-                       break;
-               case MFCINST_GOT_INST:
-                       s5p_mfc_run_init_enc(ctx);
-                       break;
-               default:
-                       ret = -EAGAIN;
-               }
-       } else {
-               mfc_err("Invalid context type: %d\n", ctx->type);
-               ret = -EAGAIN;
-       }
-
-       if (ret) {
-               /* Free hardware lock */
-               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
-                       mfc_err("Failed to unlock hardware\n");
-
-               /* This is in deed imporant, as no operation has been
-                * scheduled, reduce the clock count as no one will
-                * ever do this, because no interrupt related to this try_run
-                * will ever come from hardware. */
-               s5p_mfc_clock_off();
-       }
-}
-
-
-void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq)
-{
-       struct s5p_mfc_buf *b;
-       int i;
-
-       while (!list_empty(lh)) {
-               b = list_entry(lh->next, struct s5p_mfc_buf, list);
-               for (i = 0; i < b->b->num_planes; i++)
-                       vb2_set_plane_payload(b->b, i, 0);
-               vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
-               list_del(&b->list);
-       }
-}
-
index 2ad3def052f8836d844e27ef6bad80ec0d77d8dc..420abecafec0e625e1a5745cfbf5c7bf7fe05bb9 100644 (file)
@@ -1,10 +1,10 @@
 /*
- * drivers/media/platform/samsung/mfc5/s5p_mfc_opr.h
+ * drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
  *
  * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
  * Contains declarations of hw related functions.
  *
- * Kamil Debski, Copyright (C) 2011 Samsung Electronics
+ * Kamil Debski, Copyright (C) 2012 Samsung Electronics Co., Ltd.
  * http://www.samsung.com/
  *
  * This program is free software; you can redistribute it and/or modify
 
 #include "s5p_mfc_common.h"
 
-int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_init_encode(struct s5p_mfc_ctx *mfc_ctx);
+struct s5p_mfc_hw_ops {
+       int (*alloc_dec_temp_buffers)(struct s5p_mfc_ctx *ctx);
+       void (*release_dec_desc_buffer)(struct s5p_mfc_ctx *ctx);
+       int (*alloc_codec_buffers)(struct s5p_mfc_ctx *ctx);
+       void (*release_codec_buffers)(struct s5p_mfc_ctx *ctx);
+       int (*alloc_instance_buffer)(struct s5p_mfc_ctx *ctx);
+       void (*release_instance_buffer)(struct s5p_mfc_ctx *ctx);
+       int (*alloc_dev_context_buffer)(struct s5p_mfc_dev *dev);
+       void (*release_dev_context_buffer)(struct s5p_mfc_dev *dev);
+       void (*dec_calc_dpb_size)(struct s5p_mfc_ctx *ctx);
+       void (*enc_calc_src_size)(struct s5p_mfc_ctx *ctx);
+       int (*set_dec_stream_buffer)(struct s5p_mfc_ctx *ctx,
+                       int buf_addr, unsigned int start_num_byte,
+                       unsigned int buf_size);
+       int (*set_dec_frame_buffer)(struct s5p_mfc_ctx *ctx);
+       int (*set_enc_stream_buffer)(struct s5p_mfc_ctx *ctx,
+                       unsigned long addr, unsigned int size);
+       void (*set_enc_frame_buffer)(struct s5p_mfc_ctx *ctx,
+                       unsigned long y_addr, unsigned long c_addr);
+       void (*get_enc_frame_buffer)(struct s5p_mfc_ctx *ctx,
+                       unsigned long *y_addr, unsigned long *c_addr);
+       int (*set_enc_ref_buffer)(struct s5p_mfc_ctx *ctx);
+       int (*init_decode)(struct s5p_mfc_ctx *ctx);
+       int (*init_encode)(struct s5p_mfc_ctx *ctx);
+       int (*encode_one_frame)(struct s5p_mfc_ctx *ctx);
+       void (*try_run)(struct s5p_mfc_dev *dev);
+       void (*cleanup_queue)(struct list_head *lh,
+                       struct vb2_queue *vq);
+       void (*clear_int_flags)(struct s5p_mfc_dev *dev);
+       void (*write_info)(struct s5p_mfc_ctx *ctx, unsigned int data,
+                       unsigned int ofs);
+       unsigned int (*read_info)(struct s5p_mfc_ctx *ctx,
+                       unsigned int ofs);
+       int (*get_dspl_y_adr)(struct s5p_mfc_dev *dev);
+       int (*get_dec_y_adr)(struct s5p_mfc_dev *dev);
+       int (*get_dspl_status)(struct s5p_mfc_dev *dev);
+       int (*get_dec_status)(struct s5p_mfc_dev *dev);
+       int (*get_dec_frame_type)(struct s5p_mfc_dev *dev);
+       int (*get_disp_frame_type)(struct s5p_mfc_ctx *ctx);
+       int (*get_consumed_stream)(struct s5p_mfc_dev *dev);
+       int (*get_int_reason)(struct s5p_mfc_dev *dev);
+       int (*get_int_err)(struct s5p_mfc_dev *dev);
+       int (*err_dec)(unsigned int err);
+       int (*err_dspl)(unsigned int err);
+       int (*get_img_width)(struct s5p_mfc_dev *dev);
+       int (*get_img_height)(struct s5p_mfc_dev *dev);
+       int (*get_dpb_count)(struct s5p_mfc_dev *dev);
+       int (*get_mv_count)(struct s5p_mfc_dev *dev);
+       int (*get_inst_no)(struct s5p_mfc_dev *dev);
+       int (*get_enc_strm_size)(struct s5p_mfc_dev *dev);
+       int (*get_enc_slice_type)(struct s5p_mfc_dev *dev);
+       int (*get_enc_dpb_count)(struct s5p_mfc_dev *dev);
+       int (*get_enc_pic_count)(struct s5p_mfc_dev *dev);
+       int (*get_sei_avail_status)(struct s5p_mfc_ctx *ctx);
+       int (*get_mvc_num_views)(struct s5p_mfc_dev *dev);
+       int (*get_mvc_view_id)(struct s5p_mfc_dev *dev);
+       unsigned int (*get_pic_type_top)(struct s5p_mfc_ctx *ctx);
+       unsigned int (*get_pic_type_bot)(struct s5p_mfc_ctx *ctx);
+       unsigned int (*get_crop_info_h)(struct s5p_mfc_ctx *ctx);
+       unsigned int (*get_crop_info_v)(struct s5p_mfc_ctx *ctx);
+};
 
-/* Decoding functions */
-int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
-                                                 unsigned int start_num_byte,
-                                                 unsigned int buf_size);
-
-/* Encoding functions */
-void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
-               unsigned long y_addr, unsigned long c_addr);
-int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
-               unsigned long addr, unsigned int size);
-void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
-               unsigned long *y_addr, unsigned long *c_addr);
-int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *mfc_ctx);
-
-int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx,
-                                       enum s5p_mfc_decode_arg last_frame);
-int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *mfc_ctx);
-
-/* Memory allocation */
-int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
-
-int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx);
-
-int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx);
-
-void s5p_mfc_try_run(struct s5p_mfc_dev *dev);
-void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
-
-#define s5p_mfc_get_dspl_y_adr()       (readl(dev->regs_base + \
-                                       S5P_FIMV_SI_DISPLAY_Y_ADR) << \
-                                       MFC_OFFSET_SHIFT)
-#define s5p_mfc_get_dec_y_adr()                (readl(dev->regs_base + \
-                                       S5P_FIMV_SI_DECODE_Y_ADR) << \
-                                       MFC_OFFSET_SHIFT)
-#define s5p_mfc_get_dspl_status()      readl(dev->regs_base + \
-                                               S5P_FIMV_SI_DISPLAY_STATUS)
-#define s5p_mfc_get_dec_status()       readl(dev->regs_base + \
-                                               S5P_FIMV_SI_DECODE_STATUS)
-#define s5p_mfc_get_frame_type()       (readl(dev->regs_base + \
-                                               S5P_FIMV_DECODE_FRAME_TYPE) \
-                                       & S5P_FIMV_DECODE_FRAME_MASK)
-#define s5p_mfc_get_consumed_stream()  readl(dev->regs_base + \
-                                               S5P_FIMV_SI_CONSUMED_BYTES)
-#define s5p_mfc_get_int_reason()       (readl(dev->regs_base + \
-                                       S5P_FIMV_RISC2HOST_CMD) & \
-                                       S5P_FIMV_RISC2HOST_CMD_MASK)
-#define s5p_mfc_get_int_err()          readl(dev->regs_base + \
-                                               S5P_FIMV_RISC2HOST_ARG2)
-#define s5p_mfc_err_dec(x)             (((x) & S5P_FIMV_ERR_DEC_MASK) >> \
-                                                       S5P_FIMV_ERR_DEC_SHIFT)
-#define s5p_mfc_err_dspl(x)            (((x) & S5P_FIMV_ERR_DSPL_MASK) >> \
-                                                       S5P_FIMV_ERR_DSPL_SHIFT)
-#define s5p_mfc_get_img_width()                readl(dev->regs_base + \
-                                               S5P_FIMV_SI_HRESOL)
-#define s5p_mfc_get_img_height()       readl(dev->regs_base + \
-                                               S5P_FIMV_SI_VRESOL)
-#define s5p_mfc_get_dpb_count()                readl(dev->regs_base + \
-                                               S5P_FIMV_SI_BUF_NUMBER)
-#define s5p_mfc_get_inst_no()          readl(dev->regs_base + \
-                                               S5P_FIMV_RISC2HOST_ARG1)
-#define s5p_mfc_get_enc_strm_size()    readl(dev->regs_base + \
-                                               S5P_FIMV_ENC_SI_STRM_SIZE)
-#define s5p_mfc_get_enc_slice_type()   readl(dev->regs_base + \
-                                               S5P_FIMV_ENC_SI_SLICE_TYPE)
+void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev);
 
 #endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
new file mode 100644 (file)
index 0000000..bf7d010
--- /dev/null
@@ -0,0 +1,1794 @@
+/*
+ * drivers/media/platform/samsung/mfc5/s5p_mfc_opr_v5.c
+ *
+ * Samsung MFC (Multi Function Codec - FIMV) driver
+ * This file contains hw related functions.
+ *
+ * Kamil Debski, Copyright (c) 2011 Samsung Electronics
+ * http://www.samsung.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.
+ */
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_ctrl.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_pm.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_opr_v5.h"
+#include <asm/cacheflush.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#define OFFSETA(x)             (((x) - dev->bank1) >> MFC_OFFSET_SHIFT)
+#define OFFSETB(x)             (((x) - dev->bank2) >> MFC_OFFSET_SHIFT)
+
+/* Allocate temporary buffers for decoding */
+int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
+
+       ctx->dsc.alloc = vb2_dma_contig_memops.alloc(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
+                       buf_size->dsc);
+       if (IS_ERR_VALUE((int)ctx->dsc.alloc)) {
+               ctx->dsc.alloc = NULL;
+               mfc_err("Allocating DESC buffer failed\n");
+               return -ENOMEM;
+       }
+       ctx->dsc.dma = s5p_mfc_mem_cookie(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->dsc.alloc);
+       BUG_ON(ctx->dsc.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+       ctx->dsc.virt = vb2_dma_contig_memops.vaddr(ctx->dsc.alloc);
+       if (ctx->dsc.virt == NULL) {
+               vb2_dma_contig_memops.put(ctx->dsc.alloc);
+               ctx->dsc.dma = 0;
+               ctx->dsc.alloc = NULL;
+               mfc_err("Remapping DESC buffer failed\n");
+               return -ENOMEM;
+       }
+       memset(ctx->dsc.virt, 0, buf_size->dsc);
+       wmb();
+       return 0;
+}
+
+/* Release temporary buffers for decoding */
+void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->dsc.dma) {
+               vb2_dma_contig_memops.put(ctx->dsc.alloc);
+               ctx->dsc.alloc = NULL;
+               ctx->dsc.dma = 0;
+       }
+}
+
+/* Allocate codec buffers */
+int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int enc_ref_y_size = 0;
+       unsigned int enc_ref_c_size = 0;
+       unsigned int guard_width, guard_height;
+
+       if (ctx->type == MFCINST_DECODER) {
+               mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
+                         ctx->luma_size, ctx->chroma_size, ctx->mv_size);
+               mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
+       } else if (ctx->type == MFCINST_ENCODER) {
+               enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+                       * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+               enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
+
+               if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {
+                       enc_ref_c_size = ALIGN(ctx->img_width,
+                                               S5P_FIMV_NV12MT_HALIGN)
+                                               * ALIGN(ctx->img_height >> 1,
+                                               S5P_FIMV_NV12MT_VALIGN);
+                       enc_ref_c_size = ALIGN(enc_ref_c_size,
+                                                       S5P_FIMV_NV12MT_SALIGN);
+               } else {
+                       guard_width = ALIGN(ctx->img_width + 16,
+                                                       S5P_FIMV_NV12MT_HALIGN);
+                       guard_height = ALIGN((ctx->img_height >> 1) + 4,
+                                                       S5P_FIMV_NV12MT_VALIGN);
+                       enc_ref_c_size = ALIGN(guard_width * guard_height,
+                                              S5P_FIMV_NV12MT_SALIGN);
+               }
+               mfc_debug(2, "recon luma size: %d chroma size: %d\n",
+                         enc_ref_y_size, enc_ref_c_size);
+       } else {
+               return -EINVAL;
+       }
+       /* Codecs have different memory requirements */
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+               ctx->bank1_size =
+                   ALIGN(S5P_FIMV_DEC_NB_IP_SIZE +
+                                       S5P_FIMV_DEC_VERT_NB_MV_SIZE,
+                                       S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2_size = ctx->total_dpb_count * ctx->mv_size;
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+               ctx->bank1_size =
+                   ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE +
+                                    S5P_FIMV_DEC_UPNB_MV_SIZE +
+                                    S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
+                                    S5P_FIMV_DEC_STX_PARSER_SIZE +
+                                    S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE,
+                                    S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2_size = 0;
+               break;
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+       case S5P_MFC_CODEC_VC1_DEC:
+               ctx->bank1_size =
+                   ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
+                            S5P_FIMV_DEC_UPNB_MV_SIZE +
+                            S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
+                            S5P_FIMV_DEC_NB_DCAC_SIZE +
+                            3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE,
+                            S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2_size = 0;
+               break;
+       case S5P_MFC_CODEC_MPEG2_DEC:
+               ctx->bank1_size = 0;
+               ctx->bank2_size = 0;
+               break;
+       case S5P_MFC_CODEC_H263_DEC:
+               ctx->bank1_size =
+                   ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
+                            S5P_FIMV_DEC_UPNB_MV_SIZE +
+                            S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
+                            S5P_FIMV_DEC_NB_DCAC_SIZE,
+                            S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2_size = 0;
+               break;
+       case S5P_MFC_CODEC_H264_ENC:
+               ctx->bank1_size = (enc_ref_y_size * 2) +
+                                  S5P_FIMV_ENC_UPMV_SIZE +
+                                  S5P_FIMV_ENC_COLFLG_SIZE +
+                                  S5P_FIMV_ENC_INTRAMD_SIZE +
+                                  S5P_FIMV_ENC_NBORINFO_SIZE;
+               ctx->bank2_size = (enc_ref_y_size * 2) +
+                                  (enc_ref_c_size * 4) +
+                                  S5P_FIMV_ENC_INTRAPRED_SIZE;
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+               ctx->bank1_size = (enc_ref_y_size * 2) +
+                                  S5P_FIMV_ENC_UPMV_SIZE +
+                                  S5P_FIMV_ENC_COLFLG_SIZE +
+                                  S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               ctx->bank2_size = (enc_ref_y_size * 2) +
+                                  (enc_ref_c_size * 4);
+               break;
+       case S5P_MFC_CODEC_H263_ENC:
+               ctx->bank1_size = (enc_ref_y_size * 2) +
+                                  S5P_FIMV_ENC_UPMV_SIZE +
+                                  S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               ctx->bank2_size = (enc_ref_y_size * 2) +
+                                  (enc_ref_c_size * 4);
+               break;
+       default:
+               break;
+       }
+       /* Allocate only if memory from bank 1 is necessary */
+       if (ctx->bank1_size > 0) {
+               ctx->bank1_buf = vb2_dma_contig_memops.alloc(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
+               if (IS_ERR(ctx->bank1_buf)) {
+                       ctx->bank1_buf = NULL;
+                       printk(KERN_ERR
+                              "Buf alloc for decoding failed (port A)\n");
+                       return -ENOMEM;
+               }
+               ctx->bank1_phys = s5p_mfc_mem_cookie(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
+               BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+       }
+       /* Allocate only if memory from bank 2 is necessary */
+       if (ctx->bank2_size > 0) {
+               ctx->bank2_buf = vb2_dma_contig_memops.alloc(
+               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_size);
+               if (IS_ERR(ctx->bank2_buf)) {
+                       ctx->bank2_buf = NULL;
+                       mfc_err("Buf alloc for decoding failed (port B)\n");
+                       return -ENOMEM;
+               }
+               ctx->bank2_phys = s5p_mfc_mem_cookie(
+               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_buf);
+               BUG_ON(ctx->bank2_phys & ((1 << MFC_BANK2_ALIGN_ORDER) - 1));
+       }
+       return 0;
+}
+
+/* Release buffers allocated for codec */
+void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->bank1_buf) {
+               vb2_dma_contig_memops.put(ctx->bank1_buf);
+               ctx->bank1_buf = NULL;
+               ctx->bank1_phys = 0;
+               ctx->bank1_size = 0;
+       }
+       if (ctx->bank2_buf) {
+               vb2_dma_contig_memops.put(ctx->bank2_buf);
+               ctx->bank2_buf = NULL;
+               ctx->bank2_phys = 0;
+               ctx->bank2_size = 0;
+       }
+}
+
+/* Allocate memory for instance data buffer */
+int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+               ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+               ctx->ctx.size = buf_size->h264_ctx;
+       else
+               ctx->ctx.size = buf_size->non_h264_ctx;
+       ctx->ctx.alloc = vb2_dma_contig_memops.alloc(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.size);
+       if (IS_ERR(ctx->ctx.alloc)) {
+               mfc_err("Allocating context buffer failed\n");
+               ctx->ctx.alloc = NULL;
+               return -ENOMEM;
+       }
+       ctx->ctx.dma = s5p_mfc_mem_cookie(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc);
+       BUG_ON(ctx->ctx.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+       ctx->ctx.ofs = OFFSETA(ctx->ctx.dma);
+       ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc);
+       if (!ctx->ctx.virt) {
+               mfc_err("Remapping instance buffer failed\n");
+               vb2_dma_contig_memops.put(ctx->ctx.alloc);
+               ctx->ctx.alloc = NULL;
+               ctx->ctx.ofs = 0;
+               ctx->ctx.dma = 0;
+               return -ENOMEM;
+       }
+       /* Zero content of the allocated memory */
+       memset(ctx->ctx.virt, 0, ctx->ctx.size);
+       wmb();
+
+       /* Initialize shared memory */
+       ctx->shm.alloc = vb2_dma_contig_memops.alloc(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], buf_size->shm);
+       if (IS_ERR(ctx->shm.alloc)) {
+               mfc_err("failed to allocate shared memory\n");
+               return PTR_ERR(ctx->shm.alloc);
+       }
+       /* shared memory offset only keeps the offset from base (port a) */
+       ctx->shm.ofs = s5p_mfc_mem_cookie(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->shm.alloc)
+                                                               - dev->bank1;
+       BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+
+       ctx->shm.virt = vb2_dma_contig_memops.vaddr(ctx->shm.alloc);
+       if (!ctx->shm.virt) {
+               vb2_dma_contig_memops.put(ctx->shm.alloc);
+               ctx->shm.alloc = NULL;
+               ctx->shm.ofs = 0;
+               mfc_err("failed to virt addr of shared memory\n");
+               return -ENOMEM;
+       }
+       memset((void *)ctx->shm.virt, 0, buf_size->shm);
+       wmb();
+       return 0;
+}
+
+/* Release instance buffer */
+void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->ctx.alloc) {
+               vb2_dma_contig_memops.put(ctx->ctx.alloc);
+               ctx->ctx.alloc = NULL;
+               ctx->ctx.ofs = 0;
+               ctx->ctx.virt = NULL;
+               ctx->ctx.dma = 0;
+       }
+       if (ctx->shm.alloc) {
+               vb2_dma_contig_memops.put(ctx->shm.alloc);
+               ctx->shm.alloc = NULL;
+               ctx->shm.ofs = 0;
+               ctx->shm.virt = NULL;
+       }
+}
+
+int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
+{
+       /* NOP */
+
+       return 0;
+}
+
+void s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
+{
+       /* NOP */
+}
+
+static void s5p_mfc_write_info_v5(struct s5p_mfc_ctx *ctx, unsigned int data,
+                       unsigned int ofs)
+{
+       writel(data, (ctx->shm.virt + ofs));
+       wmb();
+}
+
+static unsigned int s5p_mfc_read_info_v5(struct s5p_mfc_ctx *ctx,
+                               unsigned int ofs)
+{
+       rmb();
+       return readl(ctx->shm.virt + ofs);
+}
+
+void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx)
+{
+       unsigned int guard_width, guard_height;
+
+       ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
+       ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+       mfc_debug(2,
+               "SEQ Done: Movie dimensions %dx%d, buffer dimensions: %dx%d\n",
+               ctx->img_width, ctx->img_height, ctx->buf_width,
+               ctx->buf_height);
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {
+               ctx->luma_size = ALIGN(ctx->buf_width * ctx->buf_height,
+                               S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->chroma_size = ALIGN(ctx->buf_width *
+                               ALIGN((ctx->img_height >> 1),
+                                       S5P_FIMV_NV12MT_VALIGN),
+                               S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->mv_size = ALIGN(ctx->buf_width *
+                               ALIGN((ctx->buf_height >> 2),
+                                       S5P_FIMV_NV12MT_VALIGN),
+                               S5P_FIMV_DEC_BUF_ALIGN);
+       } else {
+               guard_width =
+                       ALIGN(ctx->img_width + 24, S5P_FIMV_NV12MT_HALIGN);
+               guard_height =
+                       ALIGN(ctx->img_height + 16, S5P_FIMV_NV12MT_VALIGN);
+               ctx->luma_size = ALIGN(guard_width * guard_height,
+                               S5P_FIMV_DEC_BUF_ALIGN);
+
+               guard_width =
+                       ALIGN(ctx->img_width + 16, S5P_FIMV_NV12MT_HALIGN);
+               guard_height =
+                       ALIGN((ctx->img_height >> 1) + 4,
+                                       S5P_FIMV_NV12MT_VALIGN);
+               ctx->chroma_size = ALIGN(guard_width * guard_height,
+                               S5P_FIMV_DEC_BUF_ALIGN);
+
+               ctx->mv_size = 0;
+       }
+}
+
+void s5p_mfc_enc_calc_src_size_v5(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
+               ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);
+
+               ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
+                       * ALIGN(ctx->img_height, S5P_FIMV_NV12M_LVALIGN);
+               ctx->chroma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
+                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12M_CVALIGN);
+
+               ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12M_SALIGN);
+               ctx->chroma_size =
+                       ALIGN(ctx->chroma_size, S5P_FIMV_NV12M_SALIGN);
+       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
+               ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
+
+               ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+                       * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+               ctx->chroma_size =
+                       ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
+
+               ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12MT_SALIGN);
+               ctx->chroma_size =
+                       ALIGN(ctx->chroma_size, S5P_FIMV_NV12MT_SALIGN);
+       }
+}
+
+/* Set registers for decoding temporary buffers */
+static void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
+
+       mfc_write(dev, OFFSETA(ctx->dsc.dma), S5P_FIMV_SI_CH0_DESC_ADR);
+       mfc_write(dev, buf_size->dsc, S5P_FIMV_SI_CH0_DESC_SIZE);
+}
+
+/* Set registers for shared buffer */
+static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       mfc_write(dev, ctx->shm.ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
+}
+
+/* Set registers for decoding stream buffer */
+int s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx *ctx, int buf_addr,
+                 unsigned int start_num_byte, unsigned int buf_size)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
+       mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
+       mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
+       s5p_mfc_write_info_v5(ctx, start_num_byte, START_BYTE_NUM);
+       return 0;
+}
+
+/* Set decoding frame buffer */
+int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+       unsigned int frame_size, i;
+       unsigned int frame_size_ch, frame_size_mv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int dpb;
+       size_t buf_addr1, buf_addr2;
+       int buf_size1, buf_size2;
+
+       buf_addr1 = ctx->bank1_phys;
+       buf_size1 = ctx->bank1_size;
+       buf_addr2 = ctx->bank2_phys;
+       buf_size2 = ctx->bank2_size;
+       dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
+                                               ~S5P_FIMV_DPB_COUNT_MASK;
+       mfc_write(dev, ctx->total_dpb_count | dpb,
+                                               S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+       s5p_mfc_set_shared_buffer(ctx);
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                               S5P_FIMV_H264_VERT_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE;
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_NB_DCAC_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR);
+               buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_OT_LINE_ADR);
+               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               break;
+       case S5P_MFC_CODEC_H263_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR);
+               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
+               break;
+       case S5P_MFC_CODEC_VC1_DEC:
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR);
+               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE3_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE2_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE1_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               break;
+       case S5P_MFC_CODEC_MPEG2_DEC:
+               break;
+       default:
+               mfc_err("Unknown codec for decoding (%x)\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+               break;
+       }
+       frame_size = ctx->luma_size;
+       frame_size_ch = ctx->chroma_size;
+       frame_size_mv = ctx->mv_size;
+       mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size, frame_size_ch,
+                                                               frame_size_mv);
+       for (i = 0; i < ctx->total_dpb_count; i++) {
+               /* Bank2 */
+               mfc_debug(2, "Luma %d: %x\n", i,
+                                       ctx->dst_bufs[i].cookie.raw.luma);
+               mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma),
+                                               S5P_FIMV_DEC_LUMA_ADR + i * 4);
+               mfc_debug(2, "\tChroma %d: %x\n", i,
+                                       ctx->dst_bufs[i].cookie.raw.chroma);
+               mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma),
+                                              S5P_FIMV_DEC_CHROMA_ADR + i * 4);
+               if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {
+                       mfc_debug(2, "\tBuf2: %x, size: %d\n",
+                                                       buf_addr2, buf_size2);
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                                               S5P_FIMV_H264_MV_ADR + i * 4);
+                       buf_addr2 += frame_size_mv;
+                       buf_size2 -= frame_size_mv;
+               }
+       }
+       mfc_debug(2, "Buf1: %u, buf_size1: %d\n", buf_addr1, buf_size1);
+       mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n",
+                       buf_size1,  buf_size2, ctx->total_dpb_count);
+       if (buf_size1 < 0 || buf_size2 < 0) {
+               mfc_debug(2, "Not enough memory has been allocated\n");
+               return -ENOMEM;
+       }
+       s5p_mfc_write_info_v5(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
+       s5p_mfc_write_info_v5(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC)
+               s5p_mfc_write_info_v5(ctx, frame_size_mv, ALLOC_MV_SIZE);
+       mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
+                                       << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
+                                               S5P_FIMV_SI_CH0_INST_ID);
+       return 0;
+}
+
+/* Set registers for encoding stream buffer */
+int s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx *ctx,
+               unsigned long addr, unsigned int size)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR);
+       mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE);
+       return 0;
+}
+
+void s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
+               unsigned long y_addr, unsigned long c_addr)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR);
+       mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR);
+}
+
+void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
+               unsigned long *y_addr, unsigned long *c_addr)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       *y_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR)
+                                                       << MFC_OFFSET_SHIFT);
+       *c_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR)
+                                                       << MFC_OFFSET_SHIFT);
+}
+
+/* Set encoding ref & codec buffer */
+int s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       size_t buf_addr1, buf_addr2;
+       size_t buf_size1, buf_size2;
+       unsigned int enc_ref_y_size, enc_ref_c_size;
+       unsigned int guard_width, guard_height;
+       int i;
+
+       buf_addr1 = ctx->bank1_phys;
+       buf_size1 = ctx->bank1_size;
+       buf_addr2 = ctx->bank2_phys;
+       buf_size2 = ctx->bank2_size;
+       enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+               * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+       enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {
+               enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
+               enc_ref_c_size = ALIGN(enc_ref_c_size, S5P_FIMV_NV12MT_SALIGN);
+       } else {
+               guard_width = ALIGN(ctx->img_width + 16,
+                                               S5P_FIMV_NV12MT_HALIGN);
+               guard_height = ALIGN((ctx->img_height >> 1) + 4,
+                                               S5P_FIMV_NV12MT_VALIGN);
+               enc_ref_c_size = ALIGN(guard_width * guard_height,
+                                      S5P_FIMV_NV12MT_SALIGN);
+       }
+       mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", buf_size1, buf_size2);
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_ENC:
+               for (i = 0; i < 2; i++) {
+                       mfc_write(dev, OFFSETA(buf_addr1),
+                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
+                       buf_addr1 += enc_ref_y_size;
+                       buf_size1 -= enc_ref_y_size;
+
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_y_size;
+                       buf_size2 -= enc_ref_y_size;
+               }
+               for (i = 0; i < 4; i++) {
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_c_size;
+                       buf_size2 -= enc_ref_c_size;
+               }
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR);
+               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                       S5P_FIMV_H264_COZERO_FLAG_ADR);
+               buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                       S5P_FIMV_H264_UP_INTRA_MD_ADR);
+               buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE;
+               mfc_write(dev, OFFSETB(buf_addr2),
+                                       S5P_FIMV_H264_UP_INTRA_PRED_ADR);
+               buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE;
+               buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                       S5P_FIMV_H264_NBOR_INFO_ADR);
+               buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE;
+               mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
+                       buf_size1, buf_size2);
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+               for (i = 0; i < 2; i++) {
+                       mfc_write(dev, OFFSETA(buf_addr1),
+                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
+                       buf_addr1 += enc_ref_y_size;
+                       buf_size1 -= enc_ref_y_size;
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_y_size;
+                       buf_size2 -= enc_ref_y_size;
+               }
+               for (i = 0; i < 4; i++) {
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_c_size;
+                       buf_size2 -= enc_ref_c_size;
+               }
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR);
+               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                               S5P_FIMV_MPEG4_COZERO_FLAG_ADR);
+               buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                               S5P_FIMV_MPEG4_ACDC_COEF_ADR);
+               buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
+                       buf_size1, buf_size2);
+               break;
+       case S5P_MFC_CODEC_H263_ENC:
+               for (i = 0; i < 2; i++) {
+                       mfc_write(dev, OFFSETA(buf_addr1),
+                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
+                       buf_addr1 += enc_ref_y_size;
+                       buf_size1 -= enc_ref_y_size;
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_y_size;
+                       buf_size2 -= enc_ref_y_size;
+               }
+               for (i = 0; i < 4; i++) {
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_c_size;
+                       buf_size2 -= enc_ref_c_size;
+               }
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR);
+               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_ACDC_COEF_ADR);
+               buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               mfc_debug(2, "buf_size1: %d, buf_size2: %d\n",
+                       buf_size1, buf_size2);
+               break;
+       default:
+               mfc_err("Unknown codec set for encoding: %d\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       unsigned int reg;
+       unsigned int shm;
+
+       /* width */
+       mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX);
+       /* height */
+       mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX);
+       /* pictype : enable, IDR period */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       reg |= (1 << 18);
+       reg &= ~(0xFFFF);
+       reg |= p->gop_size;
+       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON);
+       /* multi-slice control */
+       /* multi-slice MB number or bit size */
+       mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL);
+       if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+               mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB);
+       } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
+               mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT);
+       } else {
+               mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB);
+               mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT);
+       }
+       /* cyclic intra refresh */
+       mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL);
+       /* memory structure cur. frame */
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
+               mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
+       else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
+               mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
+       /* padding control & value */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL);
+       if (p->pad) {
+               /** enable */
+               reg |= (1 << 31);
+               /** cr value */
+               reg &= ~(0xFF << 16);
+               reg |= (p->pad_cr << 16);
+               /** cb value */
+               reg &= ~(0xFF << 8);
+               reg |= (p->pad_cb << 8);
+               /** y value */
+               reg &= ~(0xFF);
+               reg |= (p->pad_luma);
+       } else {
+               /** disable & all value clear */
+               reg = 0;
+       }
+       mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL);
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /** frame-level rate control */
+       reg &= ~(0x1 << 9);
+       reg |= (p->rc_frame << 9);
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* bit rate */
+       if (p->rc_frame)
+               mfc_write(dev, p->rc_bitrate,
+                       S5P_FIMV_ENC_RC_BIT_RATE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE);
+       /* reaction coefficient */
+       if (p->rc_frame)
+               mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
+       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+       /* seq header ctrl */
+       shm &= ~(0x1 << 3);
+       shm |= (p->seq_hdr_mode << 3);
+       /* frame skip mode */
+       shm &= ~(0x3 << 1);
+       shm |= (p->frame_skip_mode << 1);
+       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+       /* fixed target bit */
+       s5p_mfc_write_info_v5(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
+       unsigned int reg;
+       unsigned int shm;
+
+       s5p_mfc_set_enc_params(ctx);
+       /* pictype : number of B */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* num_b_frame - 0 ~ 2 */
+       reg &= ~(0x3 << 16);
+       reg |= (p->num_b_frame << 16);
+       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* profile & level */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
+       /* level */
+       reg &= ~(0xFF << 8);
+       reg |= (p_264->level << 8);
+       /* profile - 0 ~ 2 */
+       reg &= ~(0x3F);
+       reg |= p_264->profile;
+       mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
+       /* interlace  */
+       mfc_write(dev, p_264->interlace, S5P_FIMV_ENC_PIC_STRUCT);
+       /* height */
+       if (p_264->interlace)
+               mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
+       /* loopfilter ctrl */
+       mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
+       /* loopfilter alpha offset */
+       if (p_264->loop_filter_alpha < 0) {
+               reg = 0x10;
+               reg |= (0xFF - p_264->loop_filter_alpha) + 1;
+       } else {
+               reg = 0x00;
+               reg |= (p_264->loop_filter_alpha & 0xF);
+       }
+       mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF);
+       /* loopfilter beta offset */
+       if (p_264->loop_filter_beta < 0) {
+               reg = 0x10;
+               reg |= (0xFF - p_264->loop_filter_beta) + 1;
+       } else {
+               reg = 0x00;
+               reg |= (p_264->loop_filter_beta & 0xF);
+       }
+       mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF);
+       /* entropy coding mode */
+       if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)
+               mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE);
+       /* number of ref. picture */
+       reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF);
+       /* num of ref. pictures of P */
+       reg &= ~(0x3 << 5);
+       reg |= (p_264->num_ref_pic_4p << 5);
+       /* max number of ref. pictures */
+       reg &= ~(0x1F);
+       reg |= p_264->max_ref_pic;
+       mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF);
+       /* 8x8 transform enable */
+       mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG);
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /* macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= (p->rc_mb << 8);
+       /* frame QP */
+       reg &= ~(0x3F);
+       reg |= p_264->rc_frame_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_denom)
+               mfc_write(dev, p->rc_framerate_num * 1000
+                       / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
+       /* max & min value of QP */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
+       /* max QP */
+       reg &= ~(0x3F << 8);
+       reg |= (p_264->rc_max_qp << 8);
+       /* min QP */
+       reg &= ~(0x3F);
+       reg |= p_264->rc_min_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
+       /* macroblock adaptive scaling features */
+       if (p->rc_mb) {
+               reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
+               /* dark region */
+               reg &= ~(0x1 << 3);
+               reg |= (p_264->rc_mb_dark << 3);
+               /* smooth region */
+               reg &= ~(0x1 << 2);
+               reg |= (p_264->rc_mb_smooth << 2);
+               /* static region */
+               reg &= ~(0x1 << 1);
+               reg |= (p_264->rc_mb_static << 1);
+               /* high activity region */
+               reg &= ~(0x1);
+               reg |= p_264->rc_mb_activity;
+               mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
+       }
+       if (!p->rc_frame && !p->rc_mb) {
+               shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
+               shm &= ~(0xFFF);
+               shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
+               shm |= (p_264->rc_p_frame_qp & 0x3F);
+               s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
+       }
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+       /* AR VUI control */
+       shm &= ~(0x1 << 15);
+       shm |= (p_264->vui_sar << 1);
+       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+       if (p_264->vui_sar) {
+               /* aspect ration IDC */
+               shm = s5p_mfc_read_info_v5(ctx, SAMPLE_ASPECT_RATIO_IDC);
+               shm &= ~(0xFF);
+               shm |= p_264->vui_sar_idc;
+               s5p_mfc_write_info_v5(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
+               if (p_264->vui_sar_idc == 0xFF) {
+                       /* sample  AR info */
+                       shm = s5p_mfc_read_info_v5(ctx, EXTENDED_SAR);
+                       shm &= ~(0xFFFFFFFF);
+                       shm |= p_264->vui_ext_sar_width << 16;
+                       shm |= p_264->vui_ext_sar_height;
+                       s5p_mfc_write_info_v5(ctx, shm, EXTENDED_SAR);
+               }
+       }
+       /* intra picture period for H.264 */
+       shm = s5p_mfc_read_info_v5(ctx, H264_I_PERIOD);
+       /* control */
+       shm &= ~(0x1 << 16);
+       shm |= (p_264->open_gop << 16);
+       /* value */
+       if (p_264->open_gop) {
+               shm &= ~(0xFFFF);
+               shm |= p_264->open_gop_size;
+       }
+       s5p_mfc_write_info_v5(ctx, shm, H264_I_PERIOD);
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               shm &= ~(0xFFFF << 16);
+               shm |= (p_264->cpb_size << 16);
+       }
+       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
+       unsigned int reg;
+       unsigned int shm;
+       unsigned int framerate;
+
+       s5p_mfc_set_enc_params(ctx);
+       /* pictype : number of B */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* num_b_frame - 0 ~ 2 */
+       reg &= ~(0x3 << 16);
+       reg |= (p->num_b_frame << 16);
+       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* profile & level */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
+       /* level */
+       reg &= ~(0xFF << 8);
+       reg |= (p_mpeg4->level << 8);
+       /* profile - 0 ~ 2 */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->profile;
+       mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
+       /* quarter_pixel */
+       mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
+       /* qp */
+       if (!p->rc_frame) {
+               shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
+               shm &= ~(0xFFF);
+               shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
+               shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
+               s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
+       }
+       /* frame rate */
+       if (p->rc_frame) {
+               if (p->rc_framerate_denom > 0) {
+                       framerate = p->rc_framerate_num * 1000 /
+                                               p->rc_framerate_denom;
+                       mfc_write(dev, framerate,
+                               S5P_FIMV_ENC_RC_FRAME_RATE);
+                       shm = s5p_mfc_read_info_v5(ctx, RC_VOP_TIMING);
+                       shm &= ~(0xFFFFFFFF);
+                       shm |= (1 << 31);
+                       shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
+                       shm |= (p->rc_framerate_denom & 0xFFFF);
+                       s5p_mfc_write_info_v5(ctx, shm, RC_VOP_TIMING);
+               }
+       } else {
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
+       }
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /* frame QP */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->rc_frame_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* max & min value of QP */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
+       /* max QP */
+       reg &= ~(0x3F << 8);
+       reg |= (p_mpeg4->rc_max_qp << 8);
+       /* min QP */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->rc_min_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               shm &= ~(0xFFFF << 16);
+               shm |= (p->vbv_size << 16);
+       }
+       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
+       unsigned int reg;
+       unsigned int shm;
+
+       s5p_mfc_set_enc_params(ctx);
+       /* qp */
+       if (!p->rc_frame) {
+               shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
+               shm &= ~(0xFFF);
+               shm |= (p_h263->rc_p_frame_qp & 0x3F);
+               s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
+       }
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_denom)
+               mfc_write(dev, p->rc_framerate_num * 1000
+                       / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /* frame QP */
+       reg &= ~(0x3F);
+       reg |= p_h263->rc_frame_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* max & min value of QP */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
+       /* max QP */
+       reg &= ~(0x3F << 8);
+       reg |= (p_h263->rc_max_qp << 8);
+       /* min QP */
+       reg &= ~(0x3F);
+       reg |= p_h263->rc_min_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               shm &= ~(0xFFFF << 16);
+               shm |= (p->vbv_size << 16);
+       }
+       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+       return 0;
+}
+
+/* Initialize decoding */
+int s5p_mfc_init_decode_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       s5p_mfc_set_shared_buffer(ctx);
+       /* Setup loop filter, for decoding this is only valid for MPEG4 */
+       if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC)
+               mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL);
+       mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) <<
+               S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable <<
+               S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay &
+               S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT),
+               S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+       mfc_write(dev,
+       ((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
+                               | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+       return 0;
+}
+
+static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int dpb;
+
+       if (flush)
+               dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (
+                       S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
+       else
+               dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
+                       ~(S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
+       mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+}
+
+/* Decode a single frame */
+int s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx *ctx,
+                                       enum s5p_mfc_decode_arg last_frame)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF);
+       s5p_mfc_set_shared_buffer(ctx);
+       s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
+       /* Issue different commands to instance basing on whether it
+        * is the last frame or not. */
+       switch (last_frame) {
+       case MFC_DEC_FRAME:
+               mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK) <<
+               S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+               break;
+       case MFC_DEC_LAST_FRAME:
+               mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) <<
+               S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+               break;
+       case MFC_DEC_RES_CHANGE:
+               mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC &
+               S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
+               S5P_FIMV_SI_CH0_INST_ID);
+               break;
+       }
+       mfc_debug(2, "Decoding a usual frame\n");
+       return 0;
+}
+
+int s5p_mfc_init_encode_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+               s5p_mfc_set_enc_params_h264(ctx);
+       else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC)
+               s5p_mfc_set_enc_params_mpeg4(ctx);
+       else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC)
+               s5p_mfc_set_enc_params_h263(ctx);
+       else {
+               mfc_err("Unknown codec for encoding (%x)\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+       }
+       s5p_mfc_set_shared_buffer(ctx);
+       mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) |
+               (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+       return 0;
+}
+
+/* Encode a single frame */
+int s5p_mfc_encode_one_frame_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int cmd;
+       /* memory structure cur. frame */
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
+               mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
+       else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
+               mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
+       s5p_mfc_set_shared_buffer(ctx);
+
+       if (ctx->state == MFCINST_FINISHING)
+               cmd = S5P_FIMV_CH_LAST_FRAME;
+       else
+               cmd = S5P_FIMV_CH_FRAME_START;
+       mfc_write(dev, ((cmd & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
+                               | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+
+       return 0;
+}
+
+static int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
+{
+       unsigned long flags;
+       int new_ctx;
+       int cnt;
+
+       spin_lock_irqsave(&dev->condlock, flags);
+       new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
+       cnt = 0;
+       while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
+               new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
+               if (++cnt > MFC_NUM_CONTEXTS) {
+                       /* No contexts to run */
+                       spin_unlock_irqrestore(&dev->condlock, flags);
+                       return -EAGAIN;
+               }
+       }
+       spin_unlock_irqrestore(&dev->condlock, flags);
+       return new_ctx;
+}
+
+static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_decode_one_frame_v5(ctx, MFC_DEC_RES_CHANGE);
+}
+
+static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *temp_vb;
+       unsigned long flags;
+       unsigned int index;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+       /* Frames are being decoded */
+       if (list_empty(&ctx->src_queue)) {
+               mfc_debug(2, "No src buffers\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EAGAIN;
+       }
+       /* Get the next source buffer */
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       temp_vb->flags |= MFC_BUF_FLAG_USED;
+       s5p_mfc_set_dec_stream_buffer_v5(ctx,
+               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
+               ctx->consumed_stream, temp_vb->b->v4l2_planes[0].bytesused);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       index = temp_vb->b->v4l2_buf.index;
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
+               last_frame = MFC_DEC_LAST_FRAME;
+               mfc_debug(2, "Setting ctx->state to FINISHING\n");
+               ctx->state = MFCINST_FINISHING;
+       }
+       s5p_mfc_decode_one_frame_v5(ctx, last_frame);
+       return 0;
+}
+
+static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *dst_mb;
+       struct s5p_mfc_buf *src_mb;
+       unsigned long src_y_addr, src_c_addr, dst_addr;
+       unsigned int dst_size;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+       if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) {
+               mfc_debug(2, "no src buffers\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EAGAIN;
+       }
+       if (list_empty(&ctx->dst_queue)) {
+               mfc_debug(2, "no dst buffers\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EAGAIN;
+       }
+       if (list_empty(&ctx->src_queue)) {
+               /* send null frame */
+               s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->bank2, dev->bank2);
+               src_mb = NULL;
+       } else {
+               src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
+                                                                       list);
+               src_mb->flags |= MFC_BUF_FLAG_USED;
+               if (src_mb->b->v4l2_planes[0].bytesused == 0) {
+                       /* send null frame */
+                       s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->bank2,
+                                                               dev->bank2);
+                       ctx->state = MFCINST_FINISHING;
+               } else {
+                       src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
+                                                                       0);
+                       src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
+                                                                       1);
+                       s5p_mfc_set_enc_frame_buffer_v5(ctx, src_y_addr,
+                                                               src_c_addr);
+                       if (src_mb->flags & MFC_BUF_FLAG_EOS)
+                               ctx->state = MFCINST_FINISHING;
+               }
+       }
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_mb->flags |= MFC_BUF_FLAG_USED;
+       dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
+       dst_size = vb2_plane_size(dst_mb->b, 0);
+       s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       mfc_debug(2, "encoding buffer with index=%d state=%d",
+                       src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state);
+       s5p_mfc_encode_one_frame_v5(ctx);
+       return 0;
+}
+
+static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *temp_vb;
+
+       /* Initializing decoding - parsing header */
+       spin_lock_irqsave(&dev->irqlock, flags);
+       mfc_debug(2, "Preparing to init decoding\n");
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       s5p_mfc_set_dec_desc_buffer(ctx);
+       mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
+       s5p_mfc_set_dec_stream_buffer_v5(ctx,
+                               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
+                               0, temp_vb->b->v4l2_planes[0].bytesused);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_init_decode_v5(ctx);
+}
+
+static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *dst_mb;
+       unsigned long dst_addr;
+       unsigned int dst_size;
+
+       s5p_mfc_set_enc_ref_buffer_v5(ctx);
+       spin_lock_irqsave(&dev->irqlock, flags);
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
+       dst_size = vb2_plane_size(dst_mb->b, 0);
+       s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_init_encode_v5(ctx);
+}
+
+static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *temp_vb;
+       int ret;
+
+       /*
+        * Header was parsed now starting processing
+        * First set the output frame buffers
+        */
+       if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
+               mfc_err("It seems that not all destionation buffers were "
+                       "mmaped\nMFC requires that all destination are mmaped "
+                       "before starting processing\n");
+               return -EAGAIN;
+       }
+       spin_lock_irqsave(&dev->irqlock, flags);
+       if (list_empty(&ctx->src_queue)) {
+               mfc_err("Header has been deallocated in the middle of"
+                       " initialization\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EIO;
+       }
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
+       s5p_mfc_set_dec_stream_buffer_v5(ctx,
+                               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
+                               0, temp_vb->b->v4l2_planes[0].bytesused);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       ret = s5p_mfc_set_dec_frame_buffer_v5(ctx);
+       if (ret) {
+               mfc_err("Failed to alloc frame mem\n");
+               ctx->state = MFCINST_ERROR;
+       }
+       return ret;
+}
+
+/* Try running an operation on hardware */
+void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_ctx *ctx;
+       int new_ctx;
+       unsigned int ret = 0;
+
+       if (test_bit(0, &dev->enter_suspend)) {
+               mfc_debug(1, "Entering suspend so do not schedule any jobs\n");
+               return;
+       }
+       /* Check whether hardware is not running */
+       if (test_and_set_bit(0, &dev->hw_lock) != 0) {
+               /* This is perfectly ok, the scheduled ctx should wait */
+               mfc_debug(1, "Couldn't lock HW\n");
+               return;
+       }
+       /* Choose the context to run */
+       new_ctx = s5p_mfc_get_new_ctx(dev);
+       if (new_ctx < 0) {
+               /* No contexts to run */
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
+                       mfc_err("Failed to unlock hardware\n");
+                       return;
+               }
+               mfc_debug(1, "No ctx is scheduled to be run\n");
+               return;
+       }
+       ctx = dev->ctx[new_ctx];
+       /* Got context to run in ctx */
+       /*
+        * Last frame has already been sent to MFC.
+        * Now obtaining frames from MFC buffer
+        */
+       s5p_mfc_clock_on();
+       if (ctx->type == MFCINST_DECODER) {
+               s5p_mfc_set_dec_desc_buffer(ctx);
+               switch (ctx->state) {
+               case MFCINST_FINISHING:
+                       s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME);
+                       break;
+               case MFCINST_RUNNING:
+                       ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
+                       break;
+               case MFCINST_INIT:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_RETURN_INST:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_GOT_INST:
+                       s5p_mfc_run_init_dec(ctx);
+                       break;
+               case MFCINST_HEAD_PARSED:
+                       ret = s5p_mfc_run_init_dec_buffers(ctx);
+                       mfc_debug(1, "head parsed\n");
+                       break;
+               case MFCINST_RES_CHANGE_INIT:
+                       s5p_mfc_run_res_change(ctx);
+                       break;
+               case MFCINST_RES_CHANGE_FLUSH:
+                       s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
+                       break;
+               case MFCINST_RES_CHANGE_END:
+                       mfc_debug(2, "Finished remaining frames after resolution change\n");
+                       ctx->capture_state = QUEUE_FREE;
+                       mfc_debug(2, "Will re-init the codec\n");
+                       s5p_mfc_run_init_dec(ctx);
+                       break;
+               default:
+                       ret = -EAGAIN;
+               }
+       } else if (ctx->type == MFCINST_ENCODER) {
+               switch (ctx->state) {
+               case MFCINST_FINISHING:
+               case MFCINST_RUNNING:
+                       ret = s5p_mfc_run_enc_frame(ctx);
+                       break;
+               case MFCINST_INIT:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_RETURN_INST:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_GOT_INST:
+                       s5p_mfc_run_init_enc(ctx);
+                       break;
+               default:
+                       ret = -EAGAIN;
+               }
+       } else {
+               mfc_err("Invalid context type: %d\n", ctx->type);
+               ret = -EAGAIN;
+       }
+
+       if (ret) {
+               /* Free hardware lock */
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+                       mfc_err("Failed to unlock hardware\n");
+
+               /* This is in deed imporant, as no operation has been
+                * scheduled, reduce the clock count as no one will
+                * ever do this, because no interrupt related to this try_run
+                * will ever come from hardware. */
+               s5p_mfc_clock_off();
+       }
+}
+
+
+void s5p_mfc_cleanup_queue_v5(struct list_head *lh, struct vb2_queue *vq)
+{
+       struct s5p_mfc_buf *b;
+       int i;
+
+       while (!list_empty(lh)) {
+               b = list_entry(lh->next, struct s5p_mfc_buf, list);
+               for (i = 0; i < b->b->num_planes; i++)
+                       vb2_set_plane_payload(b->b, i, 0);
+               vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
+               list_del(&b->list);
+       }
+}
+
+void s5p_mfc_clear_int_flags_v5(struct s5p_mfc_dev *dev)
+{
+       mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
+       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
+       mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
+}
+
+int s5p_mfc_get_dspl_y_adr_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_DISPLAY_Y_ADR) << MFC_OFFSET_SHIFT;
+}
+
+int s5p_mfc_get_dec_y_adr_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_DECODE_Y_ADR) << MFC_OFFSET_SHIFT;
+}
+
+int s5p_mfc_get_dspl_status_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_DISPLAY_STATUS);
+}
+
+int s5p_mfc_get_dec_status_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_DECODE_STATUS);
+}
+
+int s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_DECODE_FRAME_TYPE) &
+               S5P_FIMV_DECODE_FRAME_MASK;
+}
+
+int s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx *ctx)
+{
+       return (s5p_mfc_read_info_v5(ctx, DISP_PIC_FRAME_TYPE) >>
+                       S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT) &
+                       S5P_FIMV_DECODE_FRAME_MASK;
+}
+
+int s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_CONSUMED_BYTES);
+}
+
+int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev)
+{
+       int reason;
+       reason = mfc_read(dev, S5P_FIMV_RISC2HOST_CMD) &
+               S5P_FIMV_RISC2HOST_CMD_MASK;
+       switch (reason) {
+       case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
+               reason = S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
+               reason = S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
+               reason = S5P_MFC_R2H_CMD_SEQ_DONE_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
+               reason = S5P_MFC_R2H_CMD_FRAME_DONE_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
+               reason = S5P_MFC_R2H_CMD_SLICE_DONE_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
+               reason = S5P_MFC_R2H_CMD_SYS_INIT_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
+               reason = S5P_MFC_R2H_CMD_FW_STATUS_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_SLEEP_RET:
+               reason = S5P_MFC_R2H_CMD_SLEEP_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_WAKEUP_RET:
+               reason = S5P_MFC_R2H_CMD_WAKEUP_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
+               reason = S5P_MFC_R2H_CMD_INIT_BUFFERS_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET:
+               reason = S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_ERR_RET:
+               reason = S5P_MFC_R2H_CMD_ERR_RET;
+               break;
+       default:
+               reason = S5P_MFC_R2H_CMD_EMPTY;
+       };
+       return reason;
+}
+
+int s5p_mfc_get_int_err_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG2);
+}
+
+int s5p_mfc_err_dec_v5(unsigned int err)
+{
+       return (err & S5P_FIMV_ERR_DEC_MASK) >> S5P_FIMV_ERR_DEC_SHIFT;
+}
+
+int s5p_mfc_err_dspl_v5(unsigned int err)
+{
+       return (err & S5P_FIMV_ERR_DSPL_MASK) >> S5P_FIMV_ERR_DSPL_SHIFT;
+}
+
+int s5p_mfc_get_img_width_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_HRESOL);
+}
+
+int s5p_mfc_get_img_height_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_VRESOL);
+}
+
+int s5p_mfc_get_dpb_count_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_BUF_NUMBER);
+}
+
+int s5p_mfc_get_mv_count_v5(struct s5p_mfc_dev *dev)
+{
+       /* NOP */
+       return -1;
+}
+
+int s5p_mfc_get_inst_no_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG1);
+}
+
+int s5p_mfc_get_enc_strm_size_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_ENC_SI_STRM_SIZE);
+}
+
+int s5p_mfc_get_enc_slice_type_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_ENC_SI_SLICE_TYPE);
+}
+
+int s5p_mfc_get_enc_dpb_count_v5(struct s5p_mfc_dev *dev)
+{
+       return -1;
+}
+
+int s5p_mfc_get_enc_pic_count_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT);
+}
+
+int s5p_mfc_get_sei_avail_status_v5(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v5(ctx, FRAME_PACK_SEI_AVAIL);
+}
+
+int s5p_mfc_get_mvc_num_views_v5(struct s5p_mfc_dev *dev)
+{
+       return -1;
+}
+
+int s5p_mfc_get_mvc_view_id_v5(struct s5p_mfc_dev *dev)
+{
+       return -1;
+}
+
+unsigned int s5p_mfc_get_pic_type_top_v5(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v5(ctx, PIC_TIME_TOP);
+}
+
+unsigned int s5p_mfc_get_pic_type_bot_v5(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v5(ctx, PIC_TIME_BOT);
+}
+
+unsigned int s5p_mfc_get_crop_info_h_v5(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v5(ctx, CROP_INFO_H);
+}
+
+unsigned int s5p_mfc_get_crop_info_v_v5(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v5(ctx, CROP_INFO_V);
+}
+
+/* Initialize opr function pointers for MFC v5 */
+static struct s5p_mfc_hw_ops s5p_mfc_ops_v5 = {
+       .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v5,
+       .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v5,
+       .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v5,
+       .release_codec_buffers = s5p_mfc_release_codec_buffers_v5,
+       .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v5,
+       .release_instance_buffer = s5p_mfc_release_instance_buffer_v5,
+       .alloc_dev_context_buffer = s5p_mfc_alloc_dev_context_buffer_v5,
+       .release_dev_context_buffer = s5p_mfc_release_dev_context_buffer_v5,
+       .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v5,
+       .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v5,
+       .set_dec_stream_buffer = s5p_mfc_set_dec_stream_buffer_v5,
+       .set_dec_frame_buffer = s5p_mfc_set_dec_frame_buffer_v5,
+       .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v5,
+       .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v5,
+       .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v5,
+       .set_enc_ref_buffer = s5p_mfc_set_enc_ref_buffer_v5,
+       .init_decode = s5p_mfc_init_decode_v5,
+       .init_encode = s5p_mfc_init_encode_v5,
+       .encode_one_frame = s5p_mfc_encode_one_frame_v5,
+       .try_run = s5p_mfc_try_run_v5,
+       .cleanup_queue = s5p_mfc_cleanup_queue_v5,
+       .clear_int_flags = s5p_mfc_clear_int_flags_v5,
+       .write_info = s5p_mfc_write_info_v5,
+       .read_info = s5p_mfc_read_info_v5,
+       .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v5,
+       .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v5,
+       .get_dspl_status = s5p_mfc_get_dspl_status_v5,
+       .get_dec_status = s5p_mfc_get_dec_status_v5,
+       .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v5,
+       .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v5,
+       .get_consumed_stream = s5p_mfc_get_consumed_stream_v5,
+       .get_int_reason = s5p_mfc_get_int_reason_v5,
+       .get_int_err = s5p_mfc_get_int_err_v5,
+       .err_dec = s5p_mfc_err_dec_v5,
+       .err_dspl = s5p_mfc_err_dspl_v5,
+       .get_img_width = s5p_mfc_get_img_width_v5,
+       .get_img_height = s5p_mfc_get_img_height_v5,
+       .get_dpb_count = s5p_mfc_get_dpb_count_v5,
+       .get_mv_count = s5p_mfc_get_mv_count_v5,
+       .get_inst_no = s5p_mfc_get_inst_no_v5,
+       .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v5,
+       .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v5,
+       .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v5,
+       .get_enc_pic_count = s5p_mfc_get_enc_pic_count_v5,
+       .get_sei_avail_status = s5p_mfc_get_sei_avail_status_v5,
+       .get_mvc_num_views = s5p_mfc_get_mvc_num_views_v5,
+       .get_mvc_view_id = s5p_mfc_get_mvc_view_id_v5,
+       .get_pic_type_top = s5p_mfc_get_pic_type_top_v5,
+       .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v5,
+       .get_crop_info_h = s5p_mfc_get_crop_info_h_v5,
+       .get_crop_info_v = s5p_mfc_get_crop_info_v_v5,
+};
+
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void)
+{
+       return &s5p_mfc_ops_v5;
+}
similarity index 76%
rename from drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
rename to drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h
index 416ebd7ba35ad3d333d15d2d4f004b31937be366..ffee39a127d52d1dd03b0fdea260dcdc967b4900 100644 (file)
@@ -1,17 +1,22 @@
 /*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
+ * drivers/media/platform/samsung/mfc5/s5p_mfc_opr_v5.h
  *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * Contains declarations of hw related functions.
+ *
+ * Kamil Debski, Copyright (C) 2011 Samsung Electronics
+ * http://www.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.
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
  */
 
-#ifndef S5P_MFC_SHM_H_
-#define S5P_MFC_SHM_H_
+#ifndef S5P_MFC_OPR_V5_H_
+#define S5P_MFC_OPR_V5_H_
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_opr.h"
 
 enum MFC_SHM_OFS {
        EXTENEDED_DECODE_STATUS = 0x00, /* D */
@@ -71,20 +76,10 @@ enum MFC_SHM_OFS {
        DBG_HISTORY_INPUT1      = 0xD4, /* C */
        DBG_HISTORY_OUTPUT      = 0xD8, /* C */
        HIERARCHICAL_P_QP       = 0xE0, /* E, H.264 */
+       FRAME_PACK_SEI_ENABLE   = 0x168, /* C */
+       FRAME_PACK_SEI_AVAIL    = 0x16c, /* D */
+       FRAME_PACK_SEI_INFO     = 0x17c, /* E */
 };
 
-int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx);
-
-#define s5p_mfc_write_shm(ctx, x, ofs)         \
-       do {                                    \
-               writel(x, (ctx->shm + ofs));    \
-               wmb();                          \
-       } while (0)
-
-static inline u32 s5p_mfc_read_shm(struct s5p_mfc_ctx *ctx, unsigned int ofs)
-{
-       rmb();
-       return readl(ctx->shm + ofs);
-}
-
-#endif /* S5P_MFC_SHM_H_ */
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void);
+#endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
new file mode 100644 (file)
index 0000000..50b5bee
--- /dev/null
@@ -0,0 +1,1956 @@
+/*
+ * drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+ *
+ * Samsung MFC (Multi Function Codec - FIMV) driver
+ * This file contains hw related functions.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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.
+ */
+
+#undef DEBUG
+
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/firmware.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/cacheflush.h>
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_pm.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_opr_v6.h"
+
+/* #define S5P_MFC_DEBUG_REGWRITE  */
+#ifdef S5P_MFC_DEBUG_REGWRITE
+#undef writel
+#define writel(v, r)                                                   \
+       do {                                                            \
+               pr_err("MFCWRITE(%p): %08x\n", r, (unsigned int)v);     \
+       __raw_writel(v, r);                                             \
+       } while (0)
+#endif /* S5P_MFC_DEBUG_REGWRITE */
+
+#define READL(offset)          readl(dev->regs_base + (offset))
+#define WRITEL(data, offset)   writel((data), dev->regs_base + (offset))
+#define OFFSETA(x)             (((x) - dev->port_a) >> S5P_FIMV_MEM_OFFSET)
+#define OFFSETB(x)             (((x) - dev->port_b) >> S5P_FIMV_MEM_OFFSET)
+
+/* Allocate temporary buffers for decoding */
+int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx)
+{
+       /* NOP */
+
+       return 0;
+}
+
+/* Release temproary buffers for decoding */
+void s5p_mfc_release_dec_desc_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+       /* NOP */
+}
+
+int s5p_mfc_get_dec_status_v6(struct s5p_mfc_dev *dev)
+{
+       /* NOP */
+       return -1;
+}
+
+/* Allocate codec buffers */
+int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int mb_width, mb_height;
+
+       mb_width = MB_WIDTH(ctx->img_width);
+       mb_height = MB_HEIGHT(ctx->img_height);
+
+       if (ctx->type == MFCINST_DECODER) {
+               mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
+                         ctx->luma_size, ctx->chroma_size, ctx->mv_size);
+               mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
+       } else if (ctx->type == MFCINST_ENCODER) {
+               ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 *
+                       ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width, mb_height),
+                       S5P_FIMV_TMV_BUFFER_ALIGN_V6);
+               ctx->luma_dpb_size = ALIGN((mb_width * mb_height) *
+                               S5P_FIMV_LUMA_MB_TO_PIXEL_V6,
+                               S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6);
+               ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) *
+                               S5P_FIMV_CHROMA_MB_TO_PIXEL_V6,
+                               S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6);
+               ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V6(
+                                       ctx->img_width, ctx->img_height,
+                                       mb_width, mb_height),
+                                       S5P_FIMV_ME_BUFFER_ALIGN_V6);
+
+               mfc_debug(2, "recon luma size: %d chroma size: %d\n",
+                         ctx->luma_dpb_size, ctx->chroma_dpb_size);
+       } else {
+               return -EINVAL;
+       }
+
+       /* Codecs have different memory requirements */
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+       case S5P_MFC_CODEC_H264_MVC_DEC:
+               ctx->scratch_buf_size =
+                       S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(
+                                       mb_width,
+                                       mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1_size =
+                       ctx->scratch_buf_size +
+                       (ctx->mv_count * ctx->mv_size);
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+               ctx->scratch_buf_size =
+                       S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(
+                                       mb_width,
+                                       mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1_size = ctx->scratch_buf_size;
+               break;
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+       case S5P_MFC_CODEC_VC1_DEC:
+               ctx->scratch_buf_size =
+                       S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(
+                                       mb_width,
+                                       mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1_size = ctx->scratch_buf_size;
+               break;
+       case S5P_MFC_CODEC_MPEG2_DEC:
+               ctx->bank1_size = 0;
+               ctx->bank2_size = 0;
+               break;
+       case S5P_MFC_CODEC_H263_DEC:
+               ctx->scratch_buf_size =
+                       S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(
+                                       mb_width,
+                                       mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1_size = ctx->scratch_buf_size;
+               break;
+       case S5P_MFC_CODEC_VP8_DEC:
+               ctx->scratch_buf_size =
+                       S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6(
+                                       mb_width,
+                                       mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1_size = ctx->scratch_buf_size;
+               break;
+       case S5P_MFC_CODEC_H264_ENC:
+               ctx->scratch_buf_size =
+                       S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6(
+                                       mb_width,
+                                       mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1_size =
+                       ctx->scratch_buf_size + ctx->tmv_buffer_size +
+                       (ctx->dpb_count * (ctx->luma_dpb_size +
+                       ctx->chroma_dpb_size + ctx->me_buffer_size));
+               ctx->bank2_size = 0;
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+       case S5P_MFC_CODEC_H263_ENC:
+               ctx->scratch_buf_size =
+                       S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(
+                                       mb_width,
+                                       mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1_size =
+                       ctx->scratch_buf_size + ctx->tmv_buffer_size +
+                       (ctx->dpb_count * (ctx->luma_dpb_size +
+                       ctx->chroma_dpb_size + ctx->me_buffer_size));
+               ctx->bank2_size = 0;
+               break;
+       default:
+               break;
+       }
+
+       /* Allocate only if memory from bank 1 is necessary */
+       if (ctx->bank1_size > 0) {
+               ctx->bank1_buf = vb2_dma_contig_memops.alloc(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
+               if (IS_ERR(ctx->bank1_buf)) {
+                       ctx->bank1_buf = 0;
+                       pr_err("Buf alloc for decoding failed (port A)\n");
+                       return -ENOMEM;
+               }
+               ctx->bank1_phys = s5p_mfc_mem_cookie(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
+               BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+       }
+
+       return 0;
+}
+
+/* Release buffers allocated for codec */
+void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->bank1_buf) {
+               vb2_dma_contig_memops.put(ctx->bank1_buf);
+               ctx->bank1_buf = 0;
+               ctx->bank1_phys = 0;
+               ctx->bank1_size = 0;
+       }
+}
+
+/* Allocate memory for instance data buffer */
+int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
+
+       mfc_debug_enter();
+
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+       case S5P_MFC_CODEC_H264_MVC_DEC:
+               ctx->ctx.size = buf_size->h264_dec_ctx;
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+       case S5P_MFC_CODEC_H263_DEC:
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+       case S5P_MFC_CODEC_VC1_DEC:
+       case S5P_MFC_CODEC_MPEG2_DEC:
+       case S5P_MFC_CODEC_VP8_DEC:
+               ctx->ctx.size = buf_size->other_dec_ctx;
+               break;
+       case S5P_MFC_CODEC_H264_ENC:
+               ctx->ctx.size = buf_size->h264_enc_ctx;
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+       case S5P_MFC_CODEC_H263_ENC:
+               ctx->ctx.size = buf_size->other_enc_ctx;
+               break;
+       default:
+               ctx->ctx.size = 0;
+               mfc_err("Codec type(%d) should be checked!\n", ctx->codec_mode);
+               break;
+       }
+
+       ctx->ctx.alloc = vb2_dma_contig_memops.alloc(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.size);
+       if (IS_ERR(ctx->ctx.alloc)) {
+               mfc_err("Allocating context buffer failed.\n");
+               return PTR_ERR(ctx->ctx.alloc);
+       }
+
+       ctx->ctx.dma = s5p_mfc_mem_cookie(
+               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc);
+
+       ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc);
+       if (!ctx->ctx.virt) {
+               vb2_dma_contig_memops.put(ctx->ctx.alloc);
+               ctx->ctx.alloc = NULL;
+               ctx->ctx.dma = 0;
+               ctx->ctx.virt = NULL;
+
+               mfc_err("Remapping context buffer failed.\n");
+               return -ENOMEM;
+       }
+
+       memset(ctx->ctx.virt, 0, ctx->ctx.size);
+       wmb();
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Release instance buffer */
+void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+       mfc_debug_enter();
+
+       if (ctx->ctx.alloc) {
+               vb2_dma_contig_memops.put(ctx->ctx.alloc);
+               ctx->ctx.alloc = NULL;
+               ctx->ctx.dma = 0;
+               ctx->ctx.virt = NULL;
+       }
+
+       mfc_debug_leave();
+}
+
+/* Allocate context buffers for SYS_INIT */
+int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
+
+       mfc_debug_enter();
+
+       dev->ctx_buf.alloc = vb2_dma_contig_memops.alloc(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], buf_size->dev_ctx);
+       if (IS_ERR(dev->ctx_buf.alloc)) {
+               mfc_err("Allocating DESC buffer failed.\n");
+               return PTR_ERR(dev->ctx_buf.alloc);
+       }
+
+       dev->ctx_buf.dma = s5p_mfc_mem_cookie(
+                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
+                       dev->ctx_buf.alloc);
+
+       dev->ctx_buf.virt = vb2_dma_contig_memops.vaddr(dev->ctx_buf.alloc);
+       if (!dev->ctx_buf.virt) {
+               vb2_dma_contig_memops.put(dev->ctx_buf.alloc);
+               dev->ctx_buf.alloc = NULL;
+               dev->ctx_buf.dma = 0;
+
+               mfc_err("Remapping DESC buffer failed.\n");
+               return -ENOMEM;
+       }
+
+       memset(dev->ctx_buf.virt, 0, buf_size->dev_ctx);
+       wmb();
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Release context buffers for SYS_INIT */
+void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
+{
+       if (dev->ctx_buf.alloc) {
+               vb2_dma_contig_memops.put(dev->ctx_buf.alloc);
+               dev->ctx_buf.alloc = NULL;
+               dev->ctx_buf.dma = 0;
+               dev->ctx_buf.virt = NULL;
+       }
+}
+
+static int calc_plane(int width, int height)
+{
+       int mbX, mbY;
+
+       mbX = DIV_ROUND_UP(width, S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6);
+       mbY = DIV_ROUND_UP(height, S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6);
+
+       if (width * height < S5P_FIMV_MAX_FRAME_SIZE_V6)
+               mbY = (mbY + 1) / 2 * 2;
+
+       return (mbX * S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6) *
+               (mbY * S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6);
+}
+
+void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx)
+{
+       ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN_V6);
+       ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN_V6);
+       mfc_debug(2, "SEQ Done: Movie dimensions %dx%d,\n"
+                       "buffer dimensions: %dx%d\n", ctx->img_width,
+                       ctx->img_height, ctx->buf_width, ctx->buf_height);
+
+       ctx->luma_size = calc_plane(ctx->img_width, ctx->img_height);
+       ctx->chroma_size = calc_plane(ctx->img_width, (ctx->img_height >> 1));
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+                       ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) {
+               ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V6(ctx->img_width,
+                               ctx->img_height);
+               ctx->mv_size = ALIGN(ctx->mv_size, 16);
+       } else {
+               ctx->mv_size = 0;
+       }
+}
+
+void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx)
+{
+       unsigned int mb_width, mb_height;
+
+       mb_width = MB_WIDTH(ctx->img_width);
+       mb_height = MB_HEIGHT(ctx->img_height);
+
+       ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6);
+       ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256);
+       ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256);
+}
+
+/* Set registers for decoding stream buffer */
+int s5p_mfc_set_dec_stream_buffer_v6(struct s5p_mfc_ctx *ctx, int buf_addr,
+                 unsigned int start_num_byte, unsigned int strm_size)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;
+
+       mfc_debug_enter();
+       mfc_debug(2, "inst_no: %d, buf_addr: 0x%08x,\n"
+               "buf_size: 0x%08x (%d)\n",
+               ctx->inst_no, buf_addr, strm_size, strm_size);
+       WRITEL(strm_size, S5P_FIMV_D_STREAM_DATA_SIZE_V6);
+       WRITEL(buf_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V6);
+       WRITEL(buf_size->cpb, S5P_FIMV_D_CPB_BUFFER_SIZE_V6);
+       WRITEL(start_num_byte, S5P_FIMV_D_CPB_BUFFER_OFFSET_V6);
+
+       mfc_debug_leave();
+       return 0;
+}
+
+/* Set decoding frame buffer */
+int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+       unsigned int frame_size, i;
+       unsigned int frame_size_ch, frame_size_mv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       size_t buf_addr1;
+       int buf_size1;
+       int align_gap;
+
+       buf_addr1 = ctx->bank1_phys;
+       buf_size1 = ctx->bank1_size;
+
+       mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
+       mfc_debug(2, "Total DPB COUNT: %d\n", ctx->total_dpb_count);
+       mfc_debug(2, "Setting display delay to %d\n", ctx->display_delay);
+
+       WRITEL(ctx->total_dpb_count, S5P_FIMV_D_NUM_DPB_V6);
+       WRITEL(ctx->luma_size, S5P_FIMV_D_LUMA_DPB_SIZE_V6);
+       WRITEL(ctx->chroma_size, S5P_FIMV_D_CHROMA_DPB_SIZE_V6);
+
+       WRITEL(buf_addr1, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6);
+       WRITEL(ctx->scratch_buf_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6);
+       buf_addr1 += ctx->scratch_buf_size;
+       buf_size1 -= ctx->scratch_buf_size;
+
+       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
+                       ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC){
+               WRITEL(ctx->mv_size, S5P_FIMV_D_MV_BUFFER_SIZE_V6);
+               WRITEL(ctx->mv_count, S5P_FIMV_D_NUM_MV_V6);
+       }
+
+       frame_size = ctx->luma_size;
+       frame_size_ch = ctx->chroma_size;
+       frame_size_mv = ctx->mv_size;
+       mfc_debug(2, "Frame size: %d ch: %d mv: %d\n",
+                       frame_size, frame_size_ch, frame_size_mv);
+
+       for (i = 0; i < ctx->total_dpb_count; i++) {
+               /* Bank2 */
+               mfc_debug(2, "Luma %d: %x\n", i,
+                                       ctx->dst_bufs[i].cookie.raw.luma);
+               WRITEL(ctx->dst_bufs[i].cookie.raw.luma,
+                               S5P_FIMV_D_LUMA_DPB_V6 + i * 4);
+               mfc_debug(2, "\tChroma %d: %x\n", i,
+                                       ctx->dst_bufs[i].cookie.raw.chroma);
+               WRITEL(ctx->dst_bufs[i].cookie.raw.chroma,
+                               S5P_FIMV_D_CHROMA_DPB_V6 + i * 4);
+       }
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+                       ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) {
+               for (i = 0; i < ctx->mv_count; i++) {
+                       /* To test alignment */
+                       align_gap = buf_addr1;
+                       buf_addr1 = ALIGN(buf_addr1, 16);
+                       align_gap = buf_addr1 - align_gap;
+                       buf_size1 -= align_gap;
+
+                       mfc_debug(2, "\tBuf1: %x, size: %d\n",
+                                       buf_addr1, buf_size1);
+                       WRITEL(buf_addr1, S5P_FIMV_D_MV_BUFFER_V6 + i * 4);
+                       buf_addr1 += frame_size_mv;
+                       buf_size1 -= frame_size_mv;
+               }
+       }
+
+       mfc_debug(2, "Buf1: %u, buf_size1: %d (frames %d)\n",
+                       buf_addr1, buf_size1, ctx->total_dpb_count);
+       if (buf_size1 < 0) {
+               mfc_debug(2, "Not enough memory has been allocated.\n");
+               return -ENOMEM;
+       }
+
+       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                       S5P_FIMV_CH_INIT_BUFS_V6, NULL);
+
+       mfc_debug(2, "After setting buffers.\n");
+       return 0;
+}
+
+/* Set registers for encoding stream buffer */
+int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx,
+               unsigned long addr, unsigned int size)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       WRITEL(addr, S5P_FIMV_E_STREAM_BUFFER_ADDR_V6); /* 16B align */
+       WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE_V6);
+
+       mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d",
+               addr, size);
+
+       return 0;
+}
+
+void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
+               unsigned long y_addr, unsigned long c_addr)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); /* 256B align */
+       WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6);
+
+       mfc_debug(2, "enc src y buf addr: 0x%08lx", y_addr);
+       mfc_debug(2, "enc src c buf addr: 0x%08lx", c_addr);
+}
+
+void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
+               unsigned long *y_addr, unsigned long *c_addr)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long enc_recon_y_addr, enc_recon_c_addr;
+
+       *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6);
+       *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6);
+
+       enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6);
+       enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6);
+
+       mfc_debug(2, "recon y addr: 0x%08lx", enc_recon_y_addr);
+       mfc_debug(2, "recon c addr: 0x%08lx", enc_recon_c_addr);
+}
+
+/* Set encoding ref & codec buffer */
+int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       size_t buf_addr1, buf_size1;
+       int i;
+
+       mfc_debug_enter();
+
+       buf_addr1 = ctx->bank1_phys;
+       buf_size1 = ctx->bank1_size;
+
+       mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
+
+       for (i = 0; i < ctx->dpb_count; i++) {
+               WRITEL(buf_addr1, S5P_FIMV_E_LUMA_DPB_V6 + (4 * i));
+               buf_addr1 += ctx->luma_dpb_size;
+               WRITEL(buf_addr1, S5P_FIMV_E_CHROMA_DPB_V6 + (4 * i));
+               buf_addr1 += ctx->chroma_dpb_size;
+               WRITEL(buf_addr1, S5P_FIMV_E_ME_BUFFER_V6 + (4 * i));
+               buf_addr1 += ctx->me_buffer_size;
+               buf_size1 -= (ctx->luma_dpb_size + ctx->chroma_dpb_size +
+                       ctx->me_buffer_size);
+       }
+
+       WRITEL(buf_addr1, S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6);
+       WRITEL(ctx->scratch_buf_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6);
+       buf_addr1 += ctx->scratch_buf_size;
+       buf_size1 -= ctx->scratch_buf_size;
+
+       WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER0_V6);
+       buf_addr1 += ctx->tmv_buffer_size >> 1;
+       WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER1_V6);
+       buf_addr1 += ctx->tmv_buffer_size >> 1;
+       buf_size1 -= ctx->tmv_buffer_size;
+
+       mfc_debug(2, "Buf1: %u, buf_size1: %d (ref frames %d)\n",
+                       buf_addr1, buf_size1, ctx->dpb_count);
+       if (buf_size1 < 0) {
+               mfc_debug(2, "Not enough memory has been allocated.\n");
+               return -ENOMEM;
+       }
+
+       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                       S5P_FIMV_CH_INIT_BUFS_V6, NULL);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       /* multi-slice control */
+       /* multi-slice MB number or bit size */
+       WRITEL(ctx->slice_mode, S5P_FIMV_E_MSLICE_MODE_V6);
+       if (ctx->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+               WRITEL(ctx->slice_size.mb, S5P_FIMV_E_MSLICE_SIZE_MB_V6);
+       } else if (ctx->slice_mode ==
+                       V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
+               WRITEL(ctx->slice_size.bits, S5P_FIMV_E_MSLICE_SIZE_BITS_V6);
+       } else {
+               WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_MB_V6);
+               WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_BITS_V6);
+       }
+
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       unsigned int reg = 0;
+
+       mfc_debug_enter();
+
+       /* width */
+       WRITEL(ctx->img_width, S5P_FIMV_E_FRAME_WIDTH_V6); /* 16 align */
+       /* height */
+       WRITEL(ctx->img_height, S5P_FIMV_E_FRAME_HEIGHT_V6); /* 16 align */
+
+       /* cropped width */
+       WRITEL(ctx->img_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6);
+       /* cropped height */
+       WRITEL(ctx->img_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6);
+       /* cropped offset */
+       WRITEL(0x0, S5P_FIMV_E_FRAME_CROP_OFFSET_V6);
+
+       /* pictype : IDR period */
+       reg = 0;
+       reg |= p->gop_size & 0xFFFF;
+       WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6);
+
+       /* multi-slice control */
+       /* multi-slice MB number or bit size */
+       ctx->slice_mode = p->slice_mode;
+       reg = 0;
+       if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+               reg |= (0x1 << 3);
+               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+               ctx->slice_size.mb = p->slice_mb;
+       } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
+               reg |= (0x1 << 3);
+               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+               ctx->slice_size.bits = p->slice_bit;
+       } else {
+               reg &= ~(0x1 << 3);
+               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+       }
+
+       s5p_mfc_set_slice_mode(ctx);
+
+       /* cyclic intra refresh */
+       WRITEL(p->intra_refresh_mb, S5P_FIMV_E_IR_SIZE_V6);
+       reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+       if (p->intra_refresh_mb == 0)
+               reg &= ~(0x1 << 4);
+       else
+               reg |= (0x1 << 4);
+       WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+
+       /* 'NON_REFERENCE_STORE_ENABLE' for debugging */
+       reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+       reg &= ~(0x1 << 9);
+       WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+
+       /* memory structure cur. frame */
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
+               /* 0: Linear, 1: 2D tiled*/
+               reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+               reg &= ~(0x1 << 7);
+               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+               /* 0: NV12(CbCr), 1: NV21(CrCb) */
+               WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6);
+       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M) {
+               /* 0: Linear, 1: 2D tiled*/
+               reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+               reg &= ~(0x1 << 7);
+               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+               /* 0: NV12(CbCr), 1: NV21(CrCb) */
+               WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT_V6);
+       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) {
+               /* 0: Linear, 1: 2D tiled*/
+               reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+               reg |= (0x1 << 7);
+               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+               /* 0: NV12(CbCr), 1: NV21(CrCb) */
+               WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6);
+       }
+
+       /* memory structure recon. frame */
+       /* 0: Linear, 1: 2D tiled */
+       reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+       reg |= (0x1 << 8);
+       WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+
+       /* padding control & value */
+       WRITEL(0x0, S5P_FIMV_E_PADDING_CTRL_V6);
+       if (p->pad) {
+               reg = 0;
+               /** enable */
+               reg |= (1 << 31);
+               /** cr value */
+               reg |= ((p->pad_cr & 0xFF) << 16);
+               /** cb value */
+               reg |= ((p->pad_cb & 0xFF) << 8);
+               /** y value */
+               reg |= p->pad_luma & 0xFF;
+               WRITEL(reg, S5P_FIMV_E_PADDING_CTRL_V6);
+       }
+
+       /* rate control config. */
+       reg = 0;
+       /* frame-level rate control */
+       reg |= ((p->rc_frame & 0x1) << 9);
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+
+       /* bit rate */
+       if (p->rc_frame)
+               WRITEL(p->rc_bitrate,
+                       S5P_FIMV_E_RC_BIT_RATE_V6);
+       else
+               WRITEL(1, S5P_FIMV_E_RC_BIT_RATE_V6);
+
+       /* reaction coefficient */
+       if (p->rc_frame) {
+               if (p->rc_reaction_coeff < TIGHT_CBR_MAX) /* tight CBR */
+                       WRITEL(1, S5P_FIMV_E_RC_RPARAM_V6);
+               else                                      /* loose CBR */
+                       WRITEL(2, S5P_FIMV_E_RC_RPARAM_V6);
+       }
+
+       /* seq header ctrl */
+       reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6);
+       reg &= ~(0x1 << 2);
+       reg |= ((p->seq_hdr_mode & 0x1) << 2);
+
+       /* frame skip mode */
+       reg &= ~(0x3);
+       reg |= (p->frame_skip_mode & 0x3);
+       WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6);
+
+       /* 'DROP_CONTROL_ENABLE', disable */
+       reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
+       reg &= ~(0x1 << 10);
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+
+       /* setting for MV range [16, 256] */
+       reg = 0;
+       reg &= ~(0x3FFF);
+       reg = 256;
+       WRITEL(reg, S5P_FIMV_E_MV_HOR_RANGE_V6);
+
+       reg = 0;
+       reg &= ~(0x3FFF);
+       reg = 256;
+       WRITEL(reg, S5P_FIMV_E_MV_VER_RANGE_V6);
+
+       WRITEL(0x0, S5P_FIMV_E_FRAME_INSERTION_V6);
+       WRITEL(0x0, S5P_FIMV_E_ROI_BUFFER_ADDR_V6);
+       WRITEL(0x0, S5P_FIMV_E_PARAM_CHANGE_V6);
+       WRITEL(0x0, S5P_FIMV_E_RC_ROI_CTRL_V6);
+       WRITEL(0x0, S5P_FIMV_E_PICTURE_TAG_V6);
+
+       WRITEL(0x0, S5P_FIMV_E_BIT_COUNT_ENABLE_V6);
+       WRITEL(0x0, S5P_FIMV_E_MAX_BIT_COUNT_V6);
+       WRITEL(0x0, S5P_FIMV_E_MIN_BIT_COUNT_V6);
+
+       WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_ADDR_V6);
+       WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_SIZE_V6);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
+       unsigned int reg = 0;
+       int i;
+
+       mfc_debug_enter();
+
+       s5p_mfc_set_enc_params(ctx);
+
+       /* pictype : number of B */
+       reg = READL(S5P_FIMV_E_GOP_CONFIG_V6);
+       reg &= ~(0x3 << 16);
+       reg |= ((p->num_b_frame & 0x3) << 16);
+       WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6);
+
+       /* profile & level */
+       reg = 0;
+       /** level */
+       reg |= ((p_h264->level & 0xFF) << 8);
+       /** profile - 0 ~ 3 */
+       reg |= p_h264->profile & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6);
+
+       /* rate control config. */
+       reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
+       /** macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= ((p->rc_mb & 0x1) << 8);
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+       /** frame QP */
+       reg &= ~(0x3F);
+       reg |= p_h264->rc_frame_qp & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+
+       /* max & min value of QP */
+       reg = 0;
+       /** max QP */
+       reg |= ((p_h264->rc_max_qp & 0x3F) << 8);
+       /** min QP */
+       reg |= p_h264->rc_min_qp & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6);
+
+       /* other QPs */
+       WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+       if (!p->rc_frame && !p->rc_mb) {
+               reg = 0;
+               reg |= ((p_h264->rc_b_frame_qp & 0x3F) << 16);
+               reg |= ((p_h264->rc_p_frame_qp & 0x3F) << 8);
+               reg |= p_h264->rc_frame_qp & 0x3F;
+               WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+       }
+
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+               reg = 0;
+               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+               reg |= p->rc_framerate_denom & 0xFFFF;
+               WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6);
+       }
+
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               WRITEL(p_h264->cpb_size & 0xFFFF,
+                               S5P_FIMV_E_VBV_BUFFER_SIZE_V6);
+
+               if (p->rc_frame)
+                       WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6);
+       }
+
+       /* interlace */
+       reg = 0;
+       reg |= ((p_h264->interlace & 0x1) << 3);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* height */
+       if (p_h264->interlace) {
+               WRITEL(ctx->img_height >> 1,
+                               S5P_FIMV_E_FRAME_HEIGHT_V6); /* 32 align */
+               /* cropped height */
+               WRITEL(ctx->img_height >> 1,
+                               S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6);
+       }
+
+       /* loop filter ctrl */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x3 << 1);
+       reg |= ((p_h264->loop_filter_mode & 0x3) << 1);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* loopfilter alpha offset */
+       if (p_h264->loop_filter_alpha < 0) {
+               reg = 0x10;
+               reg |= (0xFF - p_h264->loop_filter_alpha) + 1;
+       } else {
+               reg = 0x00;
+               reg |= (p_h264->loop_filter_alpha & 0xF);
+       }
+       WRITEL(reg, S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6);
+
+       /* loopfilter beta offset */
+       if (p_h264->loop_filter_beta < 0) {
+               reg = 0x10;
+               reg |= (0xFF - p_h264->loop_filter_beta) + 1;
+       } else {
+               reg = 0x00;
+               reg |= (p_h264->loop_filter_beta & 0xF);
+       }
+       WRITEL(reg, S5P_FIMV_E_H264_LF_BETA_OFFSET_V6);
+
+       /* entropy coding mode */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1);
+       reg |= p_h264->entropy_mode & 0x1;
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* number of ref. picture */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1 << 7);
+       reg |= (((p_h264->num_ref_pic_4p - 1) & 0x1) << 7);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* 8x8 transform enable */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x3 << 12);
+       reg |= ((p_h264->_8x8_transform & 0x3) << 12);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* macroblock adaptive scaling features */
+       WRITEL(0x0, S5P_FIMV_E_MB_RC_CONFIG_V6);
+       if (p->rc_mb) {
+               reg = 0;
+               /** dark region */
+               reg |= ((p_h264->rc_mb_dark & 0x1) << 3);
+               /** smooth region */
+               reg |= ((p_h264->rc_mb_smooth & 0x1) << 2);
+               /** static region */
+               reg |= ((p_h264->rc_mb_static & 0x1) << 1);
+               /** high activity region */
+               reg |= p_h264->rc_mb_activity & 0x1;
+               WRITEL(reg, S5P_FIMV_E_MB_RC_CONFIG_V6);
+       }
+
+       /* aspect ratio VUI */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1 << 5);
+       reg |= ((p_h264->vui_sar & 0x1) << 5);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       WRITEL(0x0, S5P_FIMV_E_ASPECT_RATIO_V6);
+       WRITEL(0x0, S5P_FIMV_E_EXTENDED_SAR_V6);
+       if (p_h264->vui_sar) {
+               /* aspect ration IDC */
+               reg = 0;
+               reg |= p_h264->vui_sar_idc & 0xFF;
+               WRITEL(reg, S5P_FIMV_E_ASPECT_RATIO_V6);
+               if (p_h264->vui_sar_idc == 0xFF) {
+                       /* extended SAR */
+                       reg = 0;
+                       reg |= (p_h264->vui_ext_sar_width & 0xFFFF) << 16;
+                       reg |= p_h264->vui_ext_sar_height & 0xFFFF;
+                       WRITEL(reg, S5P_FIMV_E_EXTENDED_SAR_V6);
+               }
+       }
+
+       /* intra picture period for H.264 open GOP */
+       /* control */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1 << 4);
+       reg |= ((p_h264->open_gop & 0x1) << 4);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+       /* value */
+       WRITEL(0x0, S5P_FIMV_E_H264_I_PERIOD_V6);
+       if (p_h264->open_gop) {
+               reg = 0;
+               reg |= p_h264->open_gop_size & 0xFFFF;
+               WRITEL(reg, S5P_FIMV_E_H264_I_PERIOD_V6);
+       }
+
+       /* 'WEIGHTED_BI_PREDICTION' for B is disable */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x3 << 9);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1 << 14);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* ASO */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1 << 6);
+       reg |= ((p_h264->aso & 0x1) << 6);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+
+       /* hier qp enable */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1 << 8);
+       reg |= ((p_h264->open_gop & 0x1) << 8);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+       reg = 0;
+       if (p_h264->hier_qp && p_h264->hier_qp_layer) {
+               reg |= (p_h264->hier_qp_type & 0x1) << 0x3;
+               reg |= p_h264->hier_qp_layer & 0x7;
+               WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER_V6);
+               /* QP value for each layer */
+               for (i = 0; i < (p_h264->hier_qp_layer & 0x7); i++)
+                       WRITEL(p_h264->hier_qp_layer_qp[i],
+                               S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6 +
+                               i * 4);
+       }
+       /* number of coding layer should be zero when hierarchical is disable */
+       WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER_V6);
+
+       /* frame packing SEI generation */
+       reg = READL(S5P_FIMV_E_H264_OPTIONS_V6);
+       reg &= ~(0x1 << 25);
+       reg |= ((p_h264->sei_frame_packing & 0x1) << 25);
+       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6);
+       if (p_h264->sei_frame_packing) {
+               reg = 0;
+               /** current frame0 flag */
+               reg |= ((p_h264->sei_fp_curr_frame_0 & 0x1) << 2);
+               /** arrangement type */
+               reg |= p_h264->sei_fp_arrangement_type & 0x3;
+               WRITEL(reg, S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6);
+       }
+
+       if (p_h264->fmo) {
+               switch (p_h264->fmo_map_type) {
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES:
+                       if (p_h264->fmo_slice_grp > 4)
+                               p_h264->fmo_slice_grp = 4;
+                       for (i = 0; i < (p_h264->fmo_slice_grp & 0xF); i++)
+                               WRITEL(p_h264->fmo_run_len[i] - 1,
+                               S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6 +
+                               i * 4);
+                       break;
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES:
+                       if (p_h264->fmo_slice_grp > 4)
+                               p_h264->fmo_slice_grp = 4;
+                       break;
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN:
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN:
+                       if (p_h264->fmo_slice_grp > 2)
+                               p_h264->fmo_slice_grp = 2;
+                       WRITEL(p_h264->fmo_chg_dir & 0x1,
+                               S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6);
+                       /* the valid range is 0 ~ number of macroblocks -1 */
+                       WRITEL(p_h264->fmo_chg_rate,
+                               S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6);
+                       break;
+               default:
+                       mfc_err("Unsupported map type for FMO: %d\n",
+                                       p_h264->fmo_map_type);
+                       p_h264->fmo_map_type = 0;
+                       p_h264->fmo_slice_grp = 1;
+                       break;
+               }
+
+               WRITEL(p_h264->fmo_map_type,
+                               S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6);
+               WRITEL(p_h264->fmo_slice_grp - 1,
+                               S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6);
+       } else {
+               WRITEL(0, S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6);
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
+       unsigned int reg = 0;
+
+       mfc_debug_enter();
+
+       s5p_mfc_set_enc_params(ctx);
+
+       /* pictype : number of B */
+       reg = READL(S5P_FIMV_E_GOP_CONFIG_V6);
+       reg &= ~(0x3 << 16);
+       reg |= ((p->num_b_frame & 0x3) << 16);
+       WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6);
+
+       /* profile & level */
+       reg = 0;
+       /** level */
+       reg |= ((p_mpeg4->level & 0xFF) << 8);
+       /** profile - 0 ~ 1 */
+       reg |= p_mpeg4->profile & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6);
+
+       /* rate control config. */
+       reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
+       /** macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= ((p->rc_mb & 0x1) << 8);
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+       /** frame QP */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->rc_frame_qp & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+
+       /* max & min value of QP */
+       reg = 0;
+       /** max QP */
+       reg |= ((p_mpeg4->rc_max_qp & 0x3F) << 8);
+       /** min QP */
+       reg |= p_mpeg4->rc_min_qp & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6);
+
+       /* other QPs */
+       WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+       if (!p->rc_frame && !p->rc_mb) {
+               reg = 0;
+               reg |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 16);
+               reg |= ((p_mpeg4->rc_p_frame_qp & 0x3F) << 8);
+               reg |= p_mpeg4->rc_frame_qp & 0x3F;
+               WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+       }
+
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+               reg = 0;
+               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+               reg |= p->rc_framerate_denom & 0xFFFF;
+               WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6);
+       }
+
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE_V6);
+
+               if (p->rc_frame)
+                       WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6);
+       }
+
+       /* Disable HEC */
+       WRITEL(0x0, S5P_FIMV_E_MPEG4_OPTIONS_V6);
+       WRITEL(0x0, S5P_FIMV_E_MPEG4_HEC_PERIOD_V6);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
+       unsigned int reg = 0;
+
+       mfc_debug_enter();
+
+       s5p_mfc_set_enc_params(ctx);
+
+       /* profile & level */
+       reg = 0;
+       /** profile */
+       reg |= (0x1 << 4);
+       WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6);
+
+       /* rate control config. */
+       reg = READL(S5P_FIMV_E_RC_CONFIG_V6);
+       /** macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= ((p->rc_mb & 0x1) << 8);
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+       /** frame QP */
+       reg &= ~(0x3F);
+       reg |= p_h263->rc_frame_qp & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6);
+
+       /* max & min value of QP */
+       reg = 0;
+       /** max QP */
+       reg |= ((p_h263->rc_max_qp & 0x3F) << 8);
+       /** min QP */
+       reg |= p_h263->rc_min_qp & 0x3F;
+       WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6);
+
+       /* other QPs */
+       WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+       if (!p->rc_frame && !p->rc_mb) {
+               reg = 0;
+               reg |= ((p_h263->rc_b_frame_qp & 0x3F) << 16);
+               reg |= ((p_h263->rc_p_frame_qp & 0x3F) << 8);
+               reg |= p_h263->rc_frame_qp & 0x3F;
+               WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+       }
+
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+               reg = 0;
+               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+               reg |= p->rc_framerate_denom & 0xFFFF;
+               WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6);
+       }
+
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE_V6);
+
+               if (p->rc_frame)
+                       WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6);
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Initialize decoding */
+int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int reg = 0;
+       int fmo_aso_ctrl = 0;
+
+       mfc_debug_enter();
+       mfc_debug(2, "InstNo: %d/%d\n", ctx->inst_no,
+                       S5P_FIMV_CH_SEQ_HEADER_V6);
+       mfc_debug(2, "BUFs: %08x %08x %08x\n",
+                 READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6),
+                 READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6),
+                 READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6));
+
+       /* FMO_ASO_CTRL - 0: Enable, 1: Disable */
+       reg |= (fmo_aso_ctrl << S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6);
+
+       /* When user sets desplay_delay to 0,
+        * It works as "display_delay enable" and delay set to 0.
+        * If user wants display_delay disable, It should be
+        * set to negative value. */
+       if (ctx->display_delay >= 0) {
+               reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6);
+               WRITEL(ctx->display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6);
+       }
+       /* Setup loop filter, for decoding this is only valid for MPEG4 */
+       if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC) {
+               mfc_debug(2, "Set loop filter to: %d\n",
+                               ctx->loop_filter_mpeg4);
+               reg |= (ctx->loop_filter_mpeg4 <<
+                               S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6);
+       }
+       if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)
+               reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6);
+
+       WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6);
+
+       /* 0: NV12(CbCr), 1: NV21(CrCb) */
+       if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M)
+               WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT_V6);
+       else
+               WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6);
+
+       /* sei parse */
+       WRITEL(ctx->sei_fp_parse & 0x1, S5P_FIMV_D_SEI_ENABLE_V6);
+
+       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                       S5P_FIMV_CH_SEQ_HEADER_V6, NULL);
+
+       mfc_debug_leave();
+       return 0;
+}
+
+static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int dpb;
+       if (flush)
+               dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (1 << 14);
+       else
+               dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & ~(1 << 14);
+       WRITEL(dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+}
+
+/* Decode a single frame */
+int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx,
+                       enum s5p_mfc_decode_arg last_frame)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       WRITEL(ctx->dec_dst_flag, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6);
+       WRITEL(ctx->slice_interface & 0x1, S5P_FIMV_D_SLICE_IF_ENABLE_V6);
+
+       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+       /* Issue different commands to instance basing on whether it
+        * is the last frame or not. */
+       switch (last_frame) {
+       case 0:
+               s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                               S5P_FIMV_CH_FRAME_START_V6, NULL);
+               break;
+       case 1:
+               s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                               S5P_FIMV_CH_LAST_FRAME_V6, NULL);
+               break;
+       default:
+               mfc_err("Unsupported last frame arg.\n");
+               return -EINVAL;
+       }
+
+       mfc_debug(2, "Decoding a usual frame.\n");
+       return 0;
+}
+
+int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+               s5p_mfc_set_enc_params_h264(ctx);
+       else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC)
+               s5p_mfc_set_enc_params_mpeg4(ctx);
+       else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC)
+               s5p_mfc_set_enc_params_h263(ctx);
+       else {
+               mfc_err("Unknown codec for encoding (%x).\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+       }
+
+       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                       S5P_FIMV_CH_SEQ_HEADER_V6, NULL);
+
+       return 0;
+}
+
+int s5p_mfc_h264_set_aso_slice_order_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
+       int i;
+
+       if (p_h264->aso) {
+               for (i = 0; i < 8; i++)
+                       WRITEL(p_h264->aso_slice_order[i],
+                               S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6 + i * 4);
+       }
+       return 0;
+}
+
+/* Encode a single frame */
+int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_debug(2, "++\n");
+
+       /* memory structure cur. frame */
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+               s5p_mfc_h264_set_aso_slice_order_v6(ctx);
+
+       s5p_mfc_set_slice_mode(ctx);
+
+       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                       S5P_FIMV_CH_FRAME_START_V6, NULL);
+
+       mfc_debug(2, "--\n");
+
+       return 0;
+}
+
+static inline int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
+{
+       unsigned long flags;
+       int new_ctx;
+       int cnt;
+
+       spin_lock_irqsave(&dev->condlock, flags);
+       mfc_debug(2, "Previos context: %d (bits %08lx)\n", dev->curr_ctx,
+                                                       dev->ctx_work_bits);
+       new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
+       cnt = 0;
+       while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
+               new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
+               cnt++;
+               if (cnt > MFC_NUM_CONTEXTS) {
+                       /* No contexts to run */
+                       spin_unlock_irqrestore(&dev->condlock, flags);
+                       return -EAGAIN;
+               }
+       }
+       spin_unlock_irqrestore(&dev->condlock, flags);
+       return new_ctx;
+}
+
+static inline void s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *temp_vb;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+
+       /* Frames are being decoded */
+       if (list_empty(&ctx->src_queue)) {
+               mfc_debug(2, "No src buffers.\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return;
+       }
+       /* Get the next source buffer */
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       temp_vb->flags |= MFC_BUF_FLAG_USED;
+       s5p_mfc_set_dec_stream_buffer_v6(ctx,
+                       vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0, 0);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_decode_one_frame_v6(ctx, 1);
+}
+
+static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *temp_vb;
+       unsigned long flags;
+       int last_frame = 0;
+       unsigned int index;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+
+       /* Frames are being decoded */
+       if (list_empty(&ctx->src_queue)) {
+               mfc_debug(2, "No src buffers.\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EAGAIN;
+       }
+       /* Get the next source buffer */
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       temp_vb->flags |= MFC_BUF_FLAG_USED;
+       s5p_mfc_set_dec_stream_buffer_v6(ctx,
+               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
+                       ctx->consumed_stream,
+                       temp_vb->b->v4l2_planes[0].bytesused);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+
+       index = temp_vb->b->v4l2_buf.index;
+
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
+               last_frame = 1;
+               mfc_debug(2, "Setting ctx->state to FINISHING\n");
+               ctx->state = MFCINST_FINISHING;
+       }
+       s5p_mfc_decode_one_frame_v6(ctx, last_frame);
+
+       return 0;
+}
+
+static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *dst_mb;
+       struct s5p_mfc_buf *src_mb;
+       unsigned long src_y_addr, src_c_addr, dst_addr;
+       /*
+       unsigned int src_y_size, src_c_size;
+       */
+       unsigned int dst_size;
+       unsigned int index;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+
+       if (list_empty(&ctx->src_queue)) {
+               mfc_debug(2, "no src buffers.\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EAGAIN;
+       }
+
+       if (list_empty(&ctx->dst_queue)) {
+               mfc_debug(2, "no dst buffers.\n");
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               return -EAGAIN;
+       }
+
+       src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       src_mb->flags |= MFC_BUF_FLAG_USED;
+       src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
+       src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
+
+       mfc_debug(2, "enc src y addr: 0x%08lx", src_y_addr);
+       mfc_debug(2, "enc src c addr: 0x%08lx", src_c_addr);
+
+       s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr);
+
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_mb->flags |= MFC_BUF_FLAG_USED;
+       dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
+       dst_size = vb2_plane_size(dst_mb->b, 0);
+
+       s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
+
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+
+       index = src_mb->b->v4l2_buf.index;
+
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_encode_one_frame_v6(ctx);
+
+       return 0;
+}
+
+static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *temp_vb;
+
+       /* Initializing decoding - parsing header */
+       spin_lock_irqsave(&dev->irqlock, flags);
+       mfc_debug(2, "Preparing to init decoding.\n");
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
+       s5p_mfc_set_dec_stream_buffer_v6(ctx,
+               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0,
+                       temp_vb->b->v4l2_planes[0].bytesused);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_init_decode_v6(ctx);
+}
+
+static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *dst_mb;
+       unsigned long dst_addr;
+       unsigned int dst_size;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
+       dst_size = vb2_plane_size(dst_mb->b, 0);
+       s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_init_encode_v6(ctx);
+}
+
+static inline int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int ret;
+       /* Header was parsed now start processing
+        * First set the output frame buffers
+        * s5p_mfc_alloc_dec_buffers(ctx); */
+
+       if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
+               mfc_err("It seems that not all destionation buffers were\n"
+                       "mmaped.MFC requires that all destination are mmaped\n"
+                       "before starting processing.\n");
+               return -EAGAIN;
+       }
+
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       ret = s5p_mfc_set_dec_frame_buffer_v6(ctx);
+       if (ret) {
+               mfc_err("Failed to alloc frame mem.\n");
+               ctx->state = MFCINST_ERROR;
+       }
+       return ret;
+}
+
+static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int ret;
+
+       ret = s5p_mfc_alloc_codec_buffers_v6(ctx);
+       if (ret) {
+               mfc_err("Failed to allocate encoding buffers.\n");
+               return -ENOMEM;
+       }
+
+       /* Header was generated now starting processing
+        * First set the reference frame buffers
+        */
+       if (ctx->capture_state != QUEUE_BUFS_REQUESTED) {
+               mfc_err("It seems that destionation buffers were not\n"
+                       "requested.MFC requires that header should be generated\n"
+                       "before allocating codec buffer.\n");
+               return -EAGAIN;
+       }
+
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       ret = s5p_mfc_set_enc_ref_buffer_v6(ctx);
+       if (ret) {
+               mfc_err("Failed to alloc frame mem.\n");
+               ctx->state = MFCINST_ERROR;
+       }
+       return ret;
+}
+
+/* Try running an operation on hardware */
+void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_ctx *ctx;
+       int new_ctx;
+       unsigned int ret = 0;
+
+       mfc_debug(1, "Try run dev: %p\n", dev);
+
+       /* Check whether hardware is not running */
+       if (test_and_set_bit(0, &dev->hw_lock) != 0) {
+               /* This is perfectly ok, the scheduled ctx should wait */
+               mfc_debug(1, "Couldn't lock HW.\n");
+               return;
+       }
+
+       /* Choose the context to run */
+       new_ctx = s5p_mfc_get_new_ctx(dev);
+       if (new_ctx < 0) {
+               /* No contexts to run */
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
+                       mfc_err("Failed to unlock hardware.\n");
+                       return;
+               }
+
+               mfc_debug(1, "No ctx is scheduled to be run.\n");
+               return;
+       }
+
+       mfc_debug(1, "New context: %d\n", new_ctx);
+       ctx = dev->ctx[new_ctx];
+       mfc_debug(1, "Seting new context to %p\n", ctx);
+       /* Got context to run in ctx */
+       mfc_debug(1, "ctx->dst_queue_cnt=%d ctx->dpb_count=%d ctx->src_queue_cnt=%d\n",
+               ctx->dst_queue_cnt, ctx->dpb_count, ctx->src_queue_cnt);
+       mfc_debug(1, "ctx->state=%d\n", ctx->state);
+       /* Last frame has already been sent to MFC
+        * Now obtaining frames from MFC buffer */
+
+       s5p_mfc_clock_on();
+       if (ctx->type == MFCINST_DECODER) {
+               switch (ctx->state) {
+               case MFCINST_FINISHING:
+                       s5p_mfc_run_dec_last_frames(ctx);
+                       break;
+               case MFCINST_RUNNING:
+                       ret = s5p_mfc_run_dec_frame(ctx);
+                       break;
+               case MFCINST_INIT:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_RETURN_INST:
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_GOT_INST:
+                       s5p_mfc_run_init_dec(ctx);
+                       break;
+               case MFCINST_HEAD_PARSED:
+                       ret = s5p_mfc_run_init_dec_buffers(ctx);
+                       break;
+               case MFCINST_RES_CHANGE_INIT:
+                       s5p_mfc_run_dec_last_frames(ctx);
+                       break;
+               case MFCINST_RES_CHANGE_FLUSH:
+                       s5p_mfc_run_dec_last_frames(ctx);
+                       break;
+               case MFCINST_RES_CHANGE_END:
+                       mfc_debug(2, "Finished remaining frames after resolution change.\n");
+                       ctx->capture_state = QUEUE_FREE;
+                       mfc_debug(2, "Will re-init the codec`.\n");
+                       s5p_mfc_run_init_dec(ctx);
+                       break;
+               default:
+                       ret = -EAGAIN;
+               }
+       } else if (ctx->type == MFCINST_ENCODER) {
+               switch (ctx->state) {
+               case MFCINST_FINISHING:
+               case MFCINST_RUNNING:
+                       ret = s5p_mfc_run_enc_frame(ctx);
+                       break;
+               case MFCINST_INIT:
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_RETURN_INST:
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_GOT_INST:
+                       s5p_mfc_run_init_enc(ctx);
+                       break;
+               case MFCINST_HEAD_PARSED: /* Only for MFC6.x */
+                       ret = s5p_mfc_run_init_enc_buffers(ctx);
+                       break;
+               default:
+                       ret = -EAGAIN;
+               }
+       } else {
+               mfc_err("invalid context type: %d\n", ctx->type);
+               ret = -EAGAIN;
+       }
+
+       if (ret) {
+               /* Free hardware lock */
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+                       mfc_err("Failed to unlock hardware.\n");
+
+               /* This is in deed imporant, as no operation has been
+                * scheduled, reduce the clock count as no one will
+                * ever do this, because no interrupt related to this try_run
+                * will ever come from hardware. */
+               s5p_mfc_clock_off();
+       }
+}
+
+
+void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq)
+{
+       struct s5p_mfc_buf *b;
+       int i;
+
+       while (!list_empty(lh)) {
+               b = list_entry(lh->next, struct s5p_mfc_buf, list);
+               for (i = 0; i < b->b->num_planes; i++)
+                       vb2_set_plane_payload(b->b, i, 0);
+               vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
+               list_del(&b->list);
+       }
+}
+
+void s5p_mfc_clear_int_flags_v6(struct s5p_mfc_dev *dev)
+{
+       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
+       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_INT_V6);
+}
+
+void s5p_mfc_write_info_v6(struct s5p_mfc_ctx *ctx, unsigned int data,
+               unsigned int ofs)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       s5p_mfc_clock_on();
+       WRITEL(data, ofs);
+       s5p_mfc_clock_off();
+}
+
+unsigned int s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned int ofs)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int ret;
+
+       s5p_mfc_clock_on();
+       ret = READL(ofs);
+       s5p_mfc_clock_off();
+
+       return ret;
+}
+
+int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6);
+}
+
+int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6);
+}
+
+int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DISPLAY_STATUS_V6);
+}
+
+int s5p_mfc_get_decoded_status_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DECODED_STATUS_V6);
+}
+
+int s5p_mfc_get_dec_frame_type_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DECODED_FRAME_TYPE_V6) &
+               S5P_FIMV_DECODE_FRAME_MASK_V6;
+}
+
+int s5p_mfc_get_disp_frame_type_v6(struct s5p_mfc_ctx *ctx)
+{
+       return mfc_read(ctx->dev, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6) &
+               S5P_FIMV_DECODE_FRAME_MASK_V6;
+}
+
+int s5p_mfc_get_consumed_stream_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DECODED_NAL_SIZE_V6);
+}
+
+int s5p_mfc_get_int_reason_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_RISC2HOST_CMD_V6) &
+               S5P_FIMV_RISC2HOST_CMD_MASK;
+}
+
+int s5p_mfc_get_int_err_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_ERROR_CODE_V6);
+}
+
+int s5p_mfc_err_dec_v6(unsigned int err)
+{
+       return (err & S5P_FIMV_ERR_DEC_MASK_V6) >> S5P_FIMV_ERR_DEC_SHIFT_V6;
+}
+
+int s5p_mfc_err_dspl_v6(unsigned int err)
+{
+       return (err & S5P_FIMV_ERR_DSPL_MASK_V6) >> S5P_FIMV_ERR_DSPL_SHIFT_V6;
+}
+
+int s5p_mfc_get_img_width_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6);
+}
+
+int s5p_mfc_get_img_height_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6);
+}
+
+int s5p_mfc_get_dpb_count_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_MIN_NUM_DPB_V6);
+}
+
+int s5p_mfc_get_mv_count_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_MIN_NUM_MV_V6);
+}
+
+int s5p_mfc_get_inst_no_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_RET_INSTANCE_ID_V6);
+}
+
+int s5p_mfc_get_enc_dpb_count_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_E_NUM_DPB_V6);
+}
+
+int s5p_mfc_get_enc_strm_size_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_E_STREAM_SIZE_V6);
+}
+
+int s5p_mfc_get_enc_slice_type_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_E_SLICE_TYPE_V6);
+}
+
+int s5p_mfc_get_enc_pic_count_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_E_PICTURE_COUNT_V6);
+}
+
+int s5p_mfc_get_sei_avail_status_v6(struct s5p_mfc_ctx *ctx)
+{
+       return mfc_read(ctx->dev, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6);
+}
+
+int s5p_mfc_get_mvc_num_views_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_MVC_NUM_VIEWS_V6);
+}
+
+int s5p_mfc_get_mvc_view_id_v6(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_D_MVC_VIEW_ID_V6);
+}
+
+unsigned int s5p_mfc_get_pic_type_top_v6(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v6(ctx, PIC_TIME_TOP_V6);
+}
+
+unsigned int s5p_mfc_get_pic_type_bot_v6(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v6(ctx, PIC_TIME_BOT_V6);
+}
+
+unsigned int s5p_mfc_get_crop_info_h_v6(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v6(ctx, CROP_INFO_H_V6);
+}
+
+unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v6(ctx, CROP_INFO_V_V6);
+}
+
+/* Initialize opr function pointers for MFC v6 */
+static struct s5p_mfc_hw_ops s5p_mfc_ops_v6 = {
+       .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v6,
+       .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v6,
+       .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v6,
+       .release_codec_buffers = s5p_mfc_release_codec_buffers_v6,
+       .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v6,
+       .release_instance_buffer = s5p_mfc_release_instance_buffer_v6,
+       .alloc_dev_context_buffer =
+               s5p_mfc_alloc_dev_context_buffer_v6,
+       .release_dev_context_buffer =
+               s5p_mfc_release_dev_context_buffer_v6,
+       .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v6,
+       .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v6,
+       .set_dec_stream_buffer = s5p_mfc_set_dec_stream_buffer_v6,
+       .set_dec_frame_buffer = s5p_mfc_set_dec_frame_buffer_v6,
+       .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v6,
+       .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v6,
+       .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v6,
+       .set_enc_ref_buffer = s5p_mfc_set_enc_ref_buffer_v6,
+       .init_decode = s5p_mfc_init_decode_v6,
+       .init_encode = s5p_mfc_init_encode_v6,
+       .encode_one_frame = s5p_mfc_encode_one_frame_v6,
+       .try_run = s5p_mfc_try_run_v6,
+       .cleanup_queue = s5p_mfc_cleanup_queue_v6,
+       .clear_int_flags = s5p_mfc_clear_int_flags_v6,
+       .write_info = s5p_mfc_write_info_v6,
+       .read_info = s5p_mfc_read_info_v6,
+       .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v6,
+       .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v6,
+       .get_dspl_status = s5p_mfc_get_dspl_status_v6,
+       .get_dec_status = s5p_mfc_get_dec_status_v6,
+       .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v6,
+       .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v6,
+       .get_consumed_stream = s5p_mfc_get_consumed_stream_v6,
+       .get_int_reason = s5p_mfc_get_int_reason_v6,
+       .get_int_err = s5p_mfc_get_int_err_v6,
+       .err_dec = s5p_mfc_err_dec_v6,
+       .err_dspl = s5p_mfc_err_dspl_v6,
+       .get_img_width = s5p_mfc_get_img_width_v6,
+       .get_img_height = s5p_mfc_get_img_height_v6,
+       .get_dpb_count = s5p_mfc_get_dpb_count_v6,
+       .get_mv_count = s5p_mfc_get_mv_count_v6,
+       .get_inst_no = s5p_mfc_get_inst_no_v6,
+       .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v6,
+       .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v6,
+       .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v6,
+       .get_enc_pic_count = s5p_mfc_get_enc_pic_count_v6,
+       .get_sei_avail_status = s5p_mfc_get_sei_avail_status_v6,
+       .get_mvc_num_views = s5p_mfc_get_mvc_num_views_v6,
+       .get_mvc_view_id = s5p_mfc_get_mvc_view_id_v6,
+       .get_pic_type_top = s5p_mfc_get_pic_type_top_v6,
+       .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v6,
+       .get_crop_info_h = s5p_mfc_get_crop_info_h_v6,
+       .get_crop_info_v = s5p_mfc_get_crop_info_v_v6,
+};
+
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void)
+{
+       return &s5p_mfc_ops_v6;
+}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
new file mode 100644 (file)
index 0000000..ab164ef
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * Contains declarations of hw related functions.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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 S5P_MFC_OPR_V6_H_
+#define S5P_MFC_OPR_V6_H_
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_opr.h"
+
+#define MFC_CTRL_MODE_CUSTOM   MFC_CTRL_MODE_SFR
+
+#define MB_WIDTH(x_size)               DIV_ROUND_UP(x_size, 16)
+#define MB_HEIGHT(y_size)              DIV_ROUND_UP(y_size, 16)
+#define S5P_MFC_DEC_MV_SIZE_V6(x, y)   (MB_WIDTH(x) * \
+                                       (((MB_HEIGHT(y)+1)/2)*2) * 64 + 128)
+
+/* Definition */
+#define ENC_MULTI_SLICE_MB_MAX         ((1 << 30) - 1)
+#define ENC_MULTI_SLICE_BIT_MIN                2800
+#define ENC_INTRA_REFRESH_MB_MAX       ((1 << 18) - 1)
+#define ENC_VBV_BUF_SIZE_MAX           ((1 << 30) - 1)
+#define ENC_H264_LOOP_FILTER_AB_MIN    -12
+#define ENC_H264_LOOP_FILTER_AB_MAX    12
+#define ENC_H264_RC_FRAME_RATE_MAX     ((1 << 16) - 1)
+#define ENC_H263_RC_FRAME_RATE_MAX     ((1 << 16) - 1)
+#define ENC_H264_PROFILE_MAX           3
+#define ENC_H264_LEVEL_MAX             42
+#define ENC_MPEG4_VOP_TIME_RES_MAX     ((1 << 16) - 1)
+#define FRAME_DELTA_H264_H263          1
+#define TIGHT_CBR_MAX                  10
+
+/* Definitions for shared memory compatibility */
+#define PIC_TIME_TOP_V6                S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6
+#define PIC_TIME_BOT_V6                S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6
+#define CROP_INFO_H_V6         S5P_FIMV_D_DISPLAY_CROP_INFO1_V6
+#define CROP_INFO_V_V6         S5P_FIMV_D_DISPLAY_CROP_INFO2_V6
+
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void);
+#endif /* S5P_MFC_OPR_V6_H_ */
index 0503d14ac94e141931ca250f744f82db4476822c..367db755228932f410c6157e06f67d8ac00b477f 100644 (file)
@@ -20,7 +20,6 @@
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_pm.h"
 
-#define MFC_CLKNAME            "sclk_mfc"
 #define MFC_GATE_CLK_NAME      "mfc"
 
 #define CLK_DEBUG
@@ -51,7 +50,7 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
                goto err_p_ip_clk;
        }
 
-       pm->clock = clk_get(&dev->plat_dev->dev, MFC_CLKNAME);
+       pm->clock = clk_get(&dev->plat_dev->dev, dev->variant->mclk_name);
        if (IS_ERR(pm->clock)) {
                mfc_err("Failed to get MFC clock\n");
                ret = PTR_ERR(pm->clock);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
deleted file mode 100644 (file)
index b5933d2..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.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.
- */
-
-#ifdef CONFIG_ARCH_EXYNOS4
-#include <linux/dma-mapping.h>
-#endif
-#include <linux/io.h>
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_debug.h"
-
-int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       void *shm_alloc_ctx = dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
-
-       ctx->shm_alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx,
-                                                       SHARED_BUF_SIZE);
-       if (IS_ERR(ctx->shm_alloc)) {
-               mfc_err("failed to allocate shared memory\n");
-               return PTR_ERR(ctx->shm_alloc);
-       }
-       /* shm_ofs only keeps the offset from base (port a) */
-       ctx->shm_ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm_alloc)
-                                                               - dev->bank1;
-       BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
-       ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc);
-       if (!ctx->shm) {
-               vb2_dma_contig_memops.put(ctx->shm_alloc);
-               ctx->shm_ofs = 0;
-               ctx->shm_alloc = NULL;
-               mfc_err("failed to virt addr of shared memory\n");
-               return -ENOMEM;
-       }
-       memset((void *)ctx->shm, 0, SHARED_BUF_SIZE);
-       wmb();
-       return 0;
-}
-
index 403d7f17bfab1277adba82ed59d0650f99dd16aa..9fd9d1c5b218a5b51ff0522b9969db06e795706c 100644 (file)
@@ -1376,6 +1376,7 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
        __u32 pixfmt = pix->pixelformat;
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx2_camera_dev *pcdev = ici->priv;
+       struct mx2_fmt_cfg *emma_prp;
        unsigned int width_limit;
        int ret;
 
@@ -1438,12 +1439,11 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
                __func__, pcdev->s_width, pcdev->s_height);
 
        /* If the sensor does not support image size try PrP resizing */
-       pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code,
+       emma_prp = mx27_emma_prp_get_format(xlate->code,
                                                   xlate->host_fmt->fourcc);
 
-       memset(pcdev->resizing, 0, sizeof(pcdev->resizing));
        if ((mf.width != pix->width || mf.height != pix->height) &&
-               pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) {
+               emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) {
                if (mx2_emmaprp_resize(pcdev, &mf, pix, false) < 0)
                        dev_dbg(icd->parent, "%s: can't resize\n", __func__);
        }
@@ -1655,6 +1655,7 @@ static int __devinit mx27_camera_emma_init(struct platform_device *pdev)
        irq_emma = platform_get_irq(pdev, 1);
        if (!res_emma || !irq_emma) {
                dev_err(pcdev->dev, "no EMMA resources\n");
+               err = -ENODEV;
                goto out;
        }
 
index 3be92944f8e7efd7e44d8ff0f7acf37c8f8af084..d3f0b84e2d7086e24b4e75a863e34d23464cda15 100644 (file)
@@ -950,11 +950,11 @@ static int soc_camera_s_selection(struct file *file, void *fh,
 
        /* In all these cases cropping emulation will not help */
        if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-           (s->target != V4L2_SEL_TGT_COMPOSE_ACTIVE &&
-            s->target != V4L2_SEL_TGT_CROP_ACTIVE))
+           (s->target != V4L2_SEL_TGT_COMPOSE &&
+            s->target != V4L2_SEL_TGT_CROP))
                return -EINVAL;
 
-       if (s->target == V4L2_SEL_TGT_COMPOSE_ACTIVE) {
+       if (s->target == V4L2_SEL_TGT_COMPOSE) {
                /* No output size change during a running capture! */
                if (is_streaming(ici, icd) &&
                    (icd->user_width != s->r.width ||
@@ -974,7 +974,7 @@ static int soc_camera_s_selection(struct file *file, void *fh,
 
        ret = ici->ops->set_selection(icd, s);
        if (!ret &&
-           s->target == V4L2_SEL_TGT_COMPOSE_ACTIVE) {
+           s->target == V4L2_SEL_TGT_COMPOSE) {
                icd->user_width = s->r.width;
                icd->user_height = s->r.height;
                if (!icd->streamer)
@@ -1184,7 +1184,8 @@ static int soc_camera_probe(struct soc_camera_device *icd)
        sd->grp_id = soc_camera_grp_id(icd);
        v4l2_set_subdev_hostdata(sd, icd);
 
-       if (v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler, NULL))
+       ret = v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler, NULL);
+       if (ret < 0)
                goto ectrl;
 
        /* At this point client .probe() should have run already */
@@ -1529,12 +1530,11 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
 {
        struct soc_camera_link *icl = pdev->dev.platform_data;
        struct soc_camera_device *icd;
-       int ret;
 
        if (!icl)
                return -EINVAL;
 
-       icd = kzalloc(sizeof(*icd), GFP_KERNEL);
+       icd = devm_kzalloc(&pdev->dev, sizeof(*icd), GFP_KERNEL);
        if (!icd)
                return -ENOMEM;
 
@@ -1543,19 +1543,10 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
        icd->pdev = &pdev->dev;
        platform_set_drvdata(pdev, icd);
 
-       ret = soc_camera_device_register(icd);
-       if (ret < 0)
-               goto escdevreg;
-
        icd->user_width         = DEFAULT_WIDTH;
        icd->user_height        = DEFAULT_HEIGHT;
 
-       return 0;
-
-escdevreg:
-       kfree(icd);
-
-       return ret;
+       return soc_camera_device_register(icd);
 }
 
 /*
@@ -1572,8 +1563,6 @@ static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev)
 
        list_del(&icd->list);
 
-       kfree(icd);
-
        return 0;
 }
 
@@ -1586,18 +1575,7 @@ static struct platform_driver __refdata soc_camera_pdrv = {
        },
 };
 
-static int __init soc_camera_init(void)
-{
-       return platform_driver_register(&soc_camera_pdrv);
-}
-
-static void __exit soc_camera_exit(void)
-{
-       platform_driver_unregister(&soc_camera_pdrv);
-}
-
-module_init(soc_camera_init);
-module_exit(soc_camera_exit);
+module_platform_driver(soc_camera_pdrv);
 
 MODULE_DESCRIPTION("Image capture bus driver");
 MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
index e5024cfd27a713ffa77403471275b62e6ba264e3..4ef55ec8045e432fcc9576e130e902bc92446bed 100644 (file)
@@ -308,7 +308,7 @@ static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id)
                                        READCHAN_BLERD) >> 10;
                        rds = radio->registers[RDSD];
                        break;
-               };
+               }
 
                /* Fill the V4L2 RDS buffer */
                put_unaligned_le16(rds, &tmpbuf);
index be076f7181e728b1ab177ca340290a2c1ae29dc4..62f3edec39bc262022f5b6310b19a9efb3502497 100644 (file)
@@ -446,7 +446,7 @@ static void si470x_int_in_callback(struct urb *urb)
                                                READCHAN_BLERD) >> 10;
                                rds = radio->registers[RDSD];
                                break;
-                       };
+                       }
 
                        /* Fill the V4L2 RDS buffer */
                        put_unaligned_le16(rds, &tmpbuf);
index a9e6d17015ef545cc11aa3fc4562acd403a41683..e3079c142c5f87af79ee9e11a4268b7ae46c5283 100644 (file)
@@ -1009,7 +1009,7 @@ static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id,
 
        default:
                rval = -EINVAL;
-       };
+       }
 
        return rval;
 }
@@ -1081,7 +1081,7 @@ static int si4713_write_econtrol_string(struct si4713_device *sdev,
        default:
                rval = -EINVAL;
                break;
-       };
+       }
 
 exit:
        return rval;
@@ -1130,7 +1130,7 @@ static int si4713_write_econtrol_tune(struct si4713_device *sdev,
        default:
                rval = -EINVAL;
                goto unlock;
-       };
+       }
 
        if (sdev->power_state)
                rval = si4713_tx_tune_power(sdev, power, antcap);
@@ -1420,7 +1420,7 @@ static int si4713_read_econtrol_string(struct si4713_device *sdev,
        default:
                rval = -EINVAL;
                break;
-       };
+       }
 
 exit:
        return rval;
@@ -1473,7 +1473,7 @@ static int si4713_read_econtrol_tune(struct si4713_device *sdev,
                break;
        default:
                rval = -EINVAL;
-       };
+       }
 
 unlock:
        mutex_unlock(&sdev->mutex);
@@ -1698,7 +1698,7 @@ static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
        default:
                rval = -EINVAL;
                break;
-       };
+       }
 
        return rval;
 }
index 647dd951b0e8c31772e66bcdc333a54c3f839574..d05ac15b5de48673cafbd9825afa8925c3a3c5e7 100644 (file)
@@ -881,10 +881,13 @@ static int ene_set_tx_mask(struct rc_dev *rdev, u32 tx_mask)
 static int ene_set_tx_carrier(struct rc_dev *rdev, u32 carrier)
 {
        struct ene_device *dev = rdev->priv;
-       u32 period = 2000000 / carrier;
+       u32 period;
 
        dbg("TX: attempt to set tx carrier to %d kHz", carrier);
+       if (carrier == 0)
+               return -EINVAL;
 
+       period = 2000000 / carrier;
        if (period && (period > ENE_CIRMOD_PRD_MAX ||
                        period < ENE_CIRMOD_PRD_MIN)) {
 
index 1e4c68a5cecfedfa24c2053dd1b67db88f83e5a3..51d7057aca0443414f8325e119a1da81a2e03840 100644 (file)
@@ -28,6 +28,7 @@
 #include <media/rc-core.h>
 
 #define DRIVER_NAME "iguanair"
+#define BUF_SIZE 152
 
 struct iguanair {
        struct rc_dev *rc;
@@ -35,26 +36,23 @@ struct iguanair {
        struct device *dev;
        struct usb_device *udev;
 
-       int pipe_out;
        uint16_t version;
        uint8_t bufsize;
+       uint8_t cycle_overhead;
 
        struct mutex lock;
 
        /* receiver support */
        bool receiver_on;
-       dma_addr_t dma_in;
+       dma_addr_t dma_in, dma_out;
        uint8_t *buf_in;
-       struct urb *urb_in;
+       struct urb *urb_in, *urb_out;
        struct completion completion;
 
        /* transmit support */
        bool tx_overflow;
        uint32_t carrier;
-       uint8_t cycle_overhead;
-       uint8_t channels;
-       uint8_t busy4;
-       uint8_t busy7;
+       struct send_packet *packet;
 
        char name[64];
        char phys[64];
@@ -73,7 +71,8 @@ struct iguanair {
 #define DIR_IN                 0xdc
 #define DIR_OUT                        0xcd
 
-#define MAX_PACKET_SIZE                8u
+#define MAX_IN_PACKET          8u
+#define MAX_OUT_PACKET         (sizeof(struct send_packet) + BUF_SIZE)
 #define TIMEOUT                        1000
 #define RX_RESOLUTION          21333
 
@@ -191,20 +190,25 @@ static void iguanair_rx(struct urb *urb)
                dev_warn(ir->dev, "failed to resubmit urb: %d\n", rc);
 }
 
-static int iguanair_send(struct iguanair *ir, void *data, unsigned size)
+static void iguanair_irq_out(struct urb *urb)
 {
-       int rc, transferred;
+       struct iguanair *ir = urb->context;
+
+       if (urb->status)
+               dev_dbg(ir->dev, "Error: out urb status = %d\n", urb->status);
+}
+
+static int iguanair_send(struct iguanair *ir, unsigned size)
+{
+       int rc;
 
        INIT_COMPLETION(ir->completion);
 
-       rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data, size,
-                                                       &transferred, TIMEOUT);
+       ir->urb_out->transfer_buffer_length = size;
+       rc = usb_submit_urb(ir->urb_out, GFP_KERNEL);
        if (rc)
                return rc;
 
-       if (transferred != size)
-               return -EIO;
-
        if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0)
                return -ETIMEDOUT;
 
@@ -213,14 +217,13 @@ static int iguanair_send(struct iguanair *ir, void *data, unsigned size)
 
 static int iguanair_get_features(struct iguanair *ir)
 {
-       struct packet packet;
        int rc;
 
-       packet.start = 0;
-       packet.direction = DIR_OUT;
-       packet.cmd = CMD_GET_VERSION;
+       ir->packet->header.start = 0;
+       ir->packet->header.direction = DIR_OUT;
+       ir->packet->header.cmd = CMD_GET_VERSION;
 
-       rc = iguanair_send(ir, &packet, sizeof(packet));
+       rc = iguanair_send(ir, sizeof(ir->packet->header));
        if (rc) {
                dev_info(ir->dev, "failed to get version\n");
                goto out;
@@ -235,17 +238,23 @@ static int iguanair_get_features(struct iguanair *ir)
        ir->bufsize = 150;
        ir->cycle_overhead = 65;
 
-       packet.cmd = CMD_GET_BUFSIZE;
+       ir->packet->header.cmd = CMD_GET_BUFSIZE;
 
-       rc = iguanair_send(ir, &packet, sizeof(packet));
+       rc = iguanair_send(ir, sizeof(ir->packet->header));
        if (rc) {
                dev_info(ir->dev, "failed to get buffer size\n");
                goto out;
        }
 
-       packet.cmd = CMD_GET_FEATURES;
+       if (ir->bufsize > BUF_SIZE) {
+               dev_info(ir->dev, "buffer size %u larger than expected\n",
+                                                               ir->bufsize);
+               ir->bufsize = BUF_SIZE;
+       }
+
+       ir->packet->header.cmd = CMD_GET_FEATURES;
 
-       rc = iguanair_send(ir, &packet, sizeof(packet));
+       rc = iguanair_send(ir, sizeof(ir->packet->header));
        if (rc) {
                dev_info(ir->dev, "failed to get features\n");
                goto out;
@@ -257,13 +266,18 @@ out:
 
 static int iguanair_receiver(struct iguanair *ir, bool enable)
 {
-       struct packet packet = { 0, DIR_OUT, enable ?
-                               CMD_RECEIVER_ON : CMD_RECEIVER_OFF };
+       int rc;
+
+       ir->packet->header.start = 0;
+       ir->packet->header.direction = DIR_OUT;
+       ir->packet->header.cmd = enable ? CMD_RECEIVER_ON : CMD_RECEIVER_OFF;
 
        if (enable)
                ir_raw_event_reset(ir->rc);
 
-       return iguanair_send(ir, &packet, sizeof(packet));
+       rc = iguanair_send(ir, sizeof(ir->packet->header));
+
+       return rc;
 }
 
 /*
@@ -308,8 +322,8 @@ static int iguanair_set_tx_carrier(struct rc_dev *dev, uint32_t carrier)
                fours = (cycles - sevens * 7) / 4;
 
                /* magic happens here */
-               ir->busy7 = (4 - sevens) * 2;
-               ir->busy4 = 110 - fours;
+               ir->packet->busy7 = (4 - sevens) * 2;
+               ir->packet->busy4 = 110 - fours;
        }
 
        mutex_unlock(&ir->lock);
@@ -325,7 +339,7 @@ static int iguanair_set_tx_mask(struct rc_dev *dev, uint32_t mask)
                return 4;
 
        mutex_lock(&ir->lock);
-       ir->channels = mask;
+       ir->packet->channels = mask << 4;
        mutex_unlock(&ir->lock);
 
        return 0;
@@ -337,16 +351,9 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
        uint8_t space;
        unsigned i, size, periods, bytes;
        int rc;
-       struct send_packet *packet;
 
        mutex_lock(&ir->lock);
 
-       packet = kmalloc(sizeof(*packet) + ir->bufsize, GFP_KERNEL);
-       if (!packet) {
-               rc = -ENOMEM;
-               goto out;
-       }
-
        /* convert from us to carrier periods */
        for (i = space = size = 0; i < count; i++) {
                periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000);
@@ -356,11 +363,11 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
                        break;
                }
                while (periods > 127) {
-                       packet->payload[size++] = 127 | space;
+                       ir->packet->payload[size++] = 127 | space;
                        periods -= 127;
                }
 
-               packet->payload[size++] = periods | space;
+               ir->packet->payload[size++] = periods | space;
                space ^= 0x80;
        }
 
@@ -369,36 +376,19 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
                goto out;
        }
 
-       packet->header.start = 0;
-       packet->header.direction = DIR_OUT;
-       packet->header.cmd = CMD_SEND;
-       packet->length = size;
-       packet->channels = ir->channels << 4;
-       packet->busy7 = ir->busy7;
-       packet->busy4 = ir->busy4;
-
-       if (ir->receiver_on) {
-               rc = iguanair_receiver(ir, false);
-               if (rc) {
-                       dev_warn(ir->dev, "disable receiver before transmit failed\n");
-                       goto out;
-               }
-       }
+       ir->packet->header.start = 0;
+       ir->packet->header.direction = DIR_OUT;
+       ir->packet->header.cmd = CMD_SEND;
+       ir->packet->length = size;
 
        ir->tx_overflow = false;
 
-       rc = iguanair_send(ir, packet, size + 8);
+       rc = iguanair_send(ir, sizeof(*ir->packet) + size);
 
        if (rc == 0 && ir->tx_overflow)
                rc = -EOVERFLOW;
 
-       if (ir->receiver_on) {
-               if (iguanair_receiver(ir, true))
-                       dev_warn(ir->dev, "re-enable receiver after transmit failed\n");
-       }
-
 out:
-       kfree(packet);
        mutex_unlock(&ir->lock);
 
        return rc ? rc : count;
@@ -411,8 +401,6 @@ static int iguanair_open(struct rc_dev *rdev)
 
        mutex_lock(&ir->lock);
 
-       BUG_ON(ir->receiver_on);
-
        rc = iguanair_receiver(ir, true);
        if (rc == 0)
                ir->receiver_on = true;
@@ -443,7 +431,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
        struct usb_device *udev = interface_to_usbdev(intf);
        struct iguanair *ir;
        struct rc_dev *rc;
-       int ret, pipein;
+       int ret, pipein, pipeout;
        struct usb_host_interface *idesc;
 
        ir = kzalloc(sizeof(*ir), GFP_KERNEL);
@@ -453,11 +441,14 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
                goto out;
        }
 
-       ir->buf_in = usb_alloc_coherent(udev, MAX_PACKET_SIZE, GFP_KERNEL,
+       ir->buf_in = usb_alloc_coherent(udev, MAX_IN_PACKET, GFP_KERNEL,
                                                                &ir->dma_in);
+       ir->packet = usb_alloc_coherent(udev, MAX_OUT_PACKET, GFP_KERNEL,
+                                                               &ir->dma_out);
        ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
+       ir->urb_out = usb_alloc_urb(0, GFP_KERNEL);
 
-       if (!ir->buf_in || !ir->urb_in) {
+       if (!ir->buf_in || !ir->packet || !ir->urb_in || !ir->urb_out) {
                ret = -ENOMEM;
                goto out;
        }
@@ -472,13 +463,18 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
        ir->rc = rc;
        ir->dev = &intf->dev;
        ir->udev = udev;
-       ir->pipe_out = usb_sndintpipe(udev,
-                               idesc->endpoint[1].desc.bEndpointAddress);
        mutex_init(&ir->lock);
+
        init_completion(&ir->completion);
+       pipeout = usb_sndintpipe(udev,
+                               idesc->endpoint[1].desc.bEndpointAddress);
+       usb_fill_int_urb(ir->urb_out, udev, pipeout, ir->packet, MAX_OUT_PACKET,
+                                               iguanair_irq_out, ir, 1);
+       ir->urb_out->transfer_dma = ir->dma_out;
+       ir->urb_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
        pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress);
-       usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_PACKET_SIZE,
+       usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_IN_PACKET,
                                                         iguanair_rx, ir, 1);
        ir->urb_in->transfer_dma = ir->dma_in;
        ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -528,11 +524,14 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
        return 0;
 out2:
        usb_kill_urb(ir->urb_in);
+       usb_kill_urb(ir->urb_out);
 out:
        if (ir) {
                usb_free_urb(ir->urb_in);
-               usb_free_coherent(udev, MAX_PACKET_SIZE, ir->buf_in,
-                                                               ir->dma_in);
+               usb_free_urb(ir->urb_out);
+               usb_free_coherent(udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
+               usb_free_coherent(udev, MAX_OUT_PACKET, ir->packet,
+                                                               ir->dma_out);
        }
        rc_free_device(rc);
        kfree(ir);
@@ -546,8 +545,11 @@ static void __devexit iguanair_disconnect(struct usb_interface *intf)
        rc_unregister_device(ir->rc);
        usb_set_intfdata(intf, NULL);
        usb_kill_urb(ir->urb_in);
+       usb_kill_urb(ir->urb_out);
        usb_free_urb(ir->urb_in);
-       usb_free_coherent(ir->udev, MAX_PACKET_SIZE, ir->buf_in, ir->dma_in);
+       usb_free_urb(ir->urb_out);
+       usb_free_coherent(ir->udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
+       usb_free_coherent(ir->udev, MAX_OUT_PACKET, ir->packet, ir->dma_out);
        kfree(ir);
 }
 
@@ -565,6 +567,7 @@ static int iguanair_suspend(struct usb_interface *intf, pm_message_t message)
        }
 
        usb_kill_urb(ir->urb_in);
+       usb_kill_urb(ir->urb_out);
 
        mutex_unlock(&ir->lock);
 
index 569124b03de3f8ecfa67321a536e144b628b81cd..870c93052fd0a0a97dc2138f1f5694d52507feba 100644 (file)
@@ -203,13 +203,13 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
        /* TX settings */
        case LIRC_SET_TRANSMITTER_MASK:
                if (!dev->s_tx_mask)
-                       return -EINVAL;
+                       return -ENOSYS;
 
                return dev->s_tx_mask(dev, val);
 
        case LIRC_SET_SEND_CARRIER:
                if (!dev->s_tx_carrier)
-                       return -EINVAL;
+                       return -ENOSYS;
 
                return dev->s_tx_carrier(dev, val);
 
index c64e9e30045db6c23469dcca884ff2578e83a5e9..2fa71d0d72d7e6364f751918b9d258e49c24a410 100644 (file)
 #include <linux/module.h>
 
 static struct rc_map_table msi_digivox_ii[] = {
-       { 0x0002, KEY_2 },
-       { 0x0003, KEY_UP },              /* up */
-       { 0x0004, KEY_3 },
-       { 0x0005, KEY_CHANNELDOWN },
-       { 0x0008, KEY_5 },
-       { 0x0009, KEY_0 },
-       { 0x000b, KEY_8 },
-       { 0x000d, KEY_DOWN },            /* down */
-       { 0x0010, KEY_9 },
-       { 0x0011, KEY_7 },
-       { 0x0014, KEY_VOLUMEUP },
-       { 0x0015, KEY_CHANNELUP },
-       { 0x0016, KEY_OK },
-       { 0x0017, KEY_POWER2 },
-       { 0x001a, KEY_1 },
-       { 0x001c, KEY_4 },
-       { 0x001d, KEY_6 },
-       { 0x001f, KEY_VOLUMEDOWN },
+       { 0x0302, KEY_2 },
+       { 0x0303, KEY_UP },              /* up */
+       { 0x0304, KEY_3 },
+       { 0x0305, KEY_CHANNELDOWN },
+       { 0x0308, KEY_5 },
+       { 0x0309, KEY_0 },
+       { 0x030b, KEY_8 },
+       { 0x030d, KEY_DOWN },            /* down */
+       { 0x0310, KEY_9 },
+       { 0x0311, KEY_7 },
+       { 0x0314, KEY_VOLUMEUP },
+       { 0x0315, KEY_CHANNELUP },
+       { 0x0316, KEY_OK },
+       { 0x0317, KEY_POWER2 },
+       { 0x031a, KEY_1 },
+       { 0x031c, KEY_4 },
+       { 0x031d, KEY_6 },
+       { 0x031f, KEY_VOLUMEDOWN },
 };
 
 static struct rc_map_list msi_digivox_ii_map = {
index 699eef39128bf3eacf91a08d1a1026a1dfac1653..2ea913a44ae887b8cfe48503e68c707201ae2a88 100644 (file)
@@ -517,6 +517,9 @@ static int nvt_set_tx_carrier(struct rc_dev *dev, u32 carrier)
        struct nvt_dev *nvt = dev->priv;
        u16 val;
 
+       if (carrier == 0)
+               return -EINVAL;
+
        nvt_cir_reg_write(nvt, 1, CIR_CP);
        val = 3000000 / (carrier) - 1;
        nvt_cir_reg_write(nvt, val & 0xff, CIR_CC);
index 49731b1a9c57f09a5e9aa43a199e7f5f4e5d766a..9f5a17bb5ef5df9d09e09519a2424dbac2e0e158 100644 (file)
@@ -890,6 +890,9 @@ static int redrat3_set_tx_carrier(struct rc_dev *rcdev, u32 carrier)
        struct device *dev = rr3->dev;
 
        rr3_dbg(dev, "Setting modulation frequency to %u", carrier);
+       if (carrier == 0)
+               return -EINVAL;
+
        rr3->carrier = carrier;
 
        return carrier;
index 30ae1f24abc3b536ec6e0735c3a3be9f5f270a74..7c9b5f33113b225405a33a30edd2098c4f6ffa52 100644 (file)
@@ -184,7 +184,7 @@ enum wbcir_txstate {
 };
 
 /* Misc */
-#define WBCIR_NAME     "Winbond CIR"
+#define WBCIR_NAME     "winbond-cir"
 #define WBCIR_ID_FAMILY          0xF1 /* Family ID for the WPCD376I    */
 #define        WBCIR_ID_CHIP            0x04 /* Chip ID for the WPCD376I       */
 #define INVALID_SCANCODE   0x7FFFFFFF /* Invalid with all protos       */
index 0ed9091ff48eb02d951b2888614534788cfb688b..2e1a02e360ff0cd7279fed8ca20b80a3ee0b8ad8 100644 (file)
@@ -245,7 +245,7 @@ struct mt2063_state {
 /*
  * mt2063_write - Write data into the I2C bus
  */
-static u32 mt2063_write(struct mt2063_state *state, u8 reg, u8 *data, u32 len)
+static int mt2063_write(struct mt2063_state *state, u8 reg, u8 *data, u32 len)
 {
        struct dvb_frontend *fe = state->frontend;
        int ret;
@@ -277,9 +277,9 @@ static u32 mt2063_write(struct mt2063_state *state, u8 reg, u8 *data, u32 len)
 /*
  * mt2063_write - Write register data into the I2C bus, caching the value
  */
-static u32 mt2063_setreg(struct mt2063_state *state, u8 reg, u8 val)
+static int mt2063_setreg(struct mt2063_state *state, u8 reg, u8 val)
 {
-       u32 status;
+       int status;
 
        dprintk(2, "\n");
 
@@ -298,10 +298,10 @@ static u32 mt2063_setreg(struct mt2063_state *state, u8 reg, u8 val)
 /*
  * mt2063_read - Read data from the I2C bus
  */
-static u32 mt2063_read(struct mt2063_state *state,
+static int mt2063_read(struct mt2063_state *state,
                           u8 subAddress, u8 *pData, u32 cnt)
 {
-       u32 status = 0; /* Status to be returned        */
+       int status = 0; /* Status to be returned        */
        struct dvb_frontend *fe = state->frontend;
        u32 i = 0;
 
@@ -816,7 +816,7 @@ static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
  */
 static u32 MT2063_AvoidSpurs(struct MT2063_AvoidSpursData_t *pAS_Info)
 {
-       u32 status = 0;
+       int status = 0;
        u32 fm, fp;             /*  restricted range on LO's        */
        pAS_Info->bSpurAvoided = 0;
        pAS_Info->nSpursFound = 0;
@@ -935,14 +935,14 @@ static u32 MT2063_AvoidSpurs(struct MT2063_AvoidSpursData_t *pAS_Info)
  *
  * This function returns 0, if no lock, 1 if locked and a value < 1 if error
  */
-static unsigned int mt2063_lockStatus(struct mt2063_state *state)
+static int mt2063_lockStatus(struct mt2063_state *state)
 {
        const u32 nMaxWait = 100;       /*  wait a maximum of 100 msec   */
        const u32 nPollRate = 2;        /*  poll status bits every 2 ms */
        const u32 nMaxLoops = nMaxWait / nPollRate;
        const u8 LO1LK = 0x80;
        u8 LO2LK = 0x08;
-       u32 status;
+       int status;
        u32 nDelays = 0;
 
        dprintk(2, "\n");
@@ -1069,7 +1069,7 @@ static u32 mt2063_get_dnc_output_enable(struct mt2063_state *state,
 static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state,
                                        enum MT2063_DNC_Output_Enable nValue)
 {
-       u32 status = 0; /* Status to be returned        */
+       int status = 0; /* Status to be returned        */
        u8 val = 0;
 
        dprintk(2, "\n");
@@ -1203,7 +1203,7 @@ static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state,
 static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
                                  enum mt2063_delivery_sys Mode)
 {
-       u32 status = 0; /* Status to be returned        */
+       int status = 0; /* Status to be returned        */
        u8 val;
        u32 longval;
 
@@ -1345,7 +1345,7 @@ static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
 static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state,
                                     enum MT2063_Mask_Bits Bits)
 {
-       u32 status = 0;
+       int status = 0;
 
        dprintk(2, "\n");
        Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD);   /* Only valid bits for this tuner */
@@ -1374,7 +1374,7 @@ static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state,
  */
 static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
 {
-       u32 status;
+       int status;
 
        dprintk(2, "\n");
        if (Shutdown == 1)
@@ -1540,7 +1540,7 @@ static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
 static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
 {                              /* RF input center frequency   */
 
-       u32 status = 0;
+       int status = 0;
        u32 LO1;                /*  1st LO register value           */
        u32 Num1;               /*  Numerator for LO1 reg. value    */
        u32 f_IF1;              /*  1st IF requested                */
@@ -1803,7 +1803,7 @@ static const u8 MT2063B3_defaults[] = {
 
 static int mt2063_init(struct dvb_frontend *fe)
 {
-       u32 status;
+       int status;
        struct mt2063_state *state = fe->tuner_priv;
        u8 all_resets = 0xF0;   /* reset/load bits */
        const u8 *def = NULL;
@@ -2249,8 +2249,8 @@ struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
        dprintk(2, "\n");
 
        state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
-       if (state == NULL)
-               goto error;
+       if (!state)
+               return NULL;
 
        state->config = config;
        state->i2c = i2c;
@@ -2261,18 +2261,15 @@ struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
 
        printk(KERN_INFO "%s: Attaching MT2063\n", __func__);
        return fe;
-
-error:
-       kfree(state);
-       return NULL;
 }
 EXPORT_SYMBOL_GPL(mt2063_attach);
 
+#if 0
 /*
  * Ancillary routines visible outside mt2063
  * FIXME: Remove them in favor of using standard tuner callbacks
  */
-unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
+static int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
 {
        struct mt2063_state *state = fe->tuner_priv;
        int err = 0;
@@ -2285,9 +2282,8 @@ unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
 
        return err;
 }
-EXPORT_SYMBOL_GPL(tuner_MT2063_SoftwareShutdown);
 
-unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
+static int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
 {
        struct mt2063_state *state = fe->tuner_priv;
        int err = 0;
@@ -2300,7 +2296,7 @@ unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
 
        return err;
 }
-EXPORT_SYMBOL_GPL(tuner_MT2063_ClearPowerMaskBits);
+#endif
 
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
 MODULE_DESCRIPTION("MT2063 Silicon tuner");
index 3f5cfd93713f17d17668f798659c872558861a9a..ab24170c15719029d1f76deb0f06fca78f015bbf 100644 (file)
@@ -23,10 +23,6 @@ static inline struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
        return NULL;
 }
 
-/* FIXME: Should use the standard DVB attachment interfaces */
-unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe);
-unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe);
-
 #endif /* CONFIG_DVB_MT2063 */
 
 #endif /* __MT2063_H__ */
index 221171eeb0c32ab8d7e34c036abba3e70789e81b..18c77afe2e4ff8f32345a56d6aae199de1062c74 100644 (file)
@@ -187,7 +187,8 @@ int tda18271_read_extended(struct dvb_frontend *fe)
        return (ret == 2 ? 0 : ret);
 }
 
-int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
+static int __tda18271_write_regs(struct dvb_frontend *fe, int idx, int len,
+                       bool lock_i2c)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        unsigned char *regs = priv->tda18271_regs;
@@ -198,7 +199,6 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
 
        BUG_ON((len == 0) || (idx + len > sizeof(buf)));
 
-
        switch (priv->small_i2c) {
        case TDA18271_03_BYTE_CHUNK_INIT:
                max = 3;
@@ -214,7 +214,19 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
                max = 39;
        }
 
-       tda18271_i2c_gate_ctrl(fe, 1);
+
+       /*
+        * If lock_i2c is true, it will take the I2C bus for tda18271 private
+        * usage during the entire write ops, as otherwise, bad things could
+        * happen.
+        * During device init, several write operations will happen. So,
+        * tda18271_init_regs controls the I2C lock directly,
+        * disabling lock_i2c here.
+        */
+       if (lock_i2c) {
+               tda18271_i2c_gate_ctrl(fe, 1);
+               i2c_lock_adapter(priv->i2c_props.adap);
+       }
        while (len) {
                if (max > len)
                        max = len;
@@ -226,14 +238,17 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
                msg.len = max + 1;
 
                /* write registers */
-               ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
+               ret = __i2c_transfer(priv->i2c_props.adap, &msg, 1);
                if (ret != 1)
                        break;
 
                idx += max;
                len -= max;
        }
-       tda18271_i2c_gate_ctrl(fe, 0);
+       if (lock_i2c) {
+               i2c_unlock_adapter(priv->i2c_props.adap);
+               tda18271_i2c_gate_ctrl(fe, 0);
+       }
 
        if (ret != 1)
                tda_err("ERROR: idx = 0x%x, len = %d, "
@@ -242,10 +257,16 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
        return (ret == 1 ? 0 : ret);
 }
 
+int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
+{
+       return __tda18271_write_regs(fe, idx, len, true);
+}
+
 /*---------------------------------------------------------------------*/
 
-int tda18271_charge_pump_source(struct dvb_frontend *fe,
-                               enum tda18271_pll pll, int force)
+static int __tda18271_charge_pump_source(struct dvb_frontend *fe,
+                                        enum tda18271_pll pll, int force,
+                                        bool lock_i2c)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        unsigned char *regs = priv->tda18271_regs;
@@ -255,9 +276,16 @@ int tda18271_charge_pump_source(struct dvb_frontend *fe,
        regs[r_cp] &= ~0x20;
        regs[r_cp] |= ((force & 1) << 5);
 
-       return tda18271_write_regs(fe, r_cp, 1);
+       return __tda18271_write_regs(fe, r_cp, 1, lock_i2c);
+}
+
+int tda18271_charge_pump_source(struct dvb_frontend *fe,
+                               enum tda18271_pll pll, int force)
+{
+       return __tda18271_charge_pump_source(fe, pll, force, true);
 }
 
+
 int tda18271_init_regs(struct dvb_frontend *fe)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
@@ -267,6 +295,13 @@ int tda18271_init_regs(struct dvb_frontend *fe)
                i2c_adapter_id(priv->i2c_props.adap),
                priv->i2c_props.addr);
 
+       /*
+        * Don't let any other I2C transfer to happen at adapter during init,
+        * as those could cause bad things
+        */
+       tda18271_i2c_gate_ctrl(fe, 1);
+       i2c_lock_adapter(priv->i2c_props.adap);
+
        /* initialize registers */
        switch (priv->id) {
        case TDA18271HDC1:
@@ -352,28 +387,28 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_EB22] = 0x48;
        regs[R_EB23] = 0xb0;
 
-       tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
+       __tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS, false);
 
        /* setup agc1 gain */
        regs[R_EB17] = 0x00;
-       tda18271_write_regs(fe, R_EB17, 1);
+       __tda18271_write_regs(fe, R_EB17, 1, false);
        regs[R_EB17] = 0x03;
-       tda18271_write_regs(fe, R_EB17, 1);
+       __tda18271_write_regs(fe, R_EB17, 1, false);
        regs[R_EB17] = 0x43;
-       tda18271_write_regs(fe, R_EB17, 1);
+       __tda18271_write_regs(fe, R_EB17, 1, false);
        regs[R_EB17] = 0x4c;
-       tda18271_write_regs(fe, R_EB17, 1);
+       __tda18271_write_regs(fe, R_EB17, 1, false);
 
        /* setup agc2 gain */
        if ((priv->id) == TDA18271HDC1) {
                regs[R_EB20] = 0xa0;
-               tda18271_write_regs(fe, R_EB20, 1);
+               __tda18271_write_regs(fe, R_EB20, 1, false);
                regs[R_EB20] = 0xa7;
-               tda18271_write_regs(fe, R_EB20, 1);
+               __tda18271_write_regs(fe, R_EB20, 1, false);
                regs[R_EB20] = 0xe7;
-               tda18271_write_regs(fe, R_EB20, 1);
+               __tda18271_write_regs(fe, R_EB20, 1, false);
                regs[R_EB20] = 0xec;
-               tda18271_write_regs(fe, R_EB20, 1);
+               __tda18271_write_regs(fe, R_EB20, 1, false);
        }
 
        /* image rejection calibration */
@@ -391,21 +426,21 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_MD2] = 0x08;
        regs[R_MD3] = 0x00;
 
-       tda18271_write_regs(fe, R_EP3, 11);
+       __tda18271_write_regs(fe, R_EP3, 11, false);
 
        if ((priv->id) == TDA18271HDC2) {
                /* main pll cp source on */
-               tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1);
+               __tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1, false);
                msleep(1);
 
                /* main pll cp source off */
-               tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0);
+               __tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0, false);
        }
 
        msleep(5); /* pll locking */
 
        /* launch detector */
-       tda18271_write_regs(fe, R_EP1, 1);
+       __tda18271_write_regs(fe, R_EP1, 1, false);
        msleep(5); /* wanted low measurement */
 
        regs[R_EP5] = 0x85;
@@ -413,11 +448,11 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_CD1] = 0x66;
        regs[R_CD2] = 0x70;
 
-       tda18271_write_regs(fe, R_EP3, 7);
+       __tda18271_write_regs(fe, R_EP3, 7, false);
        msleep(5); /* pll locking */
 
        /* launch optimization algorithm */
-       tda18271_write_regs(fe, R_EP2, 1);
+       __tda18271_write_regs(fe, R_EP2, 1, false);
        msleep(30); /* image low optimization completion */
 
        /* mid-band */
@@ -428,11 +463,11 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_MD1] = 0x73;
        regs[R_MD2] = 0x1a;
 
-       tda18271_write_regs(fe, R_EP3, 11);
+       __tda18271_write_regs(fe, R_EP3, 11, false);
        msleep(5); /* pll locking */
 
        /* launch detector */
-       tda18271_write_regs(fe, R_EP1, 1);
+       __tda18271_write_regs(fe, R_EP1, 1, false);
        msleep(5); /* wanted mid measurement */
 
        regs[R_EP5] = 0x86;
@@ -440,11 +475,11 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_CD1] = 0x66;
        regs[R_CD2] = 0xa0;
 
-       tda18271_write_regs(fe, R_EP3, 7);
+       __tda18271_write_regs(fe, R_EP3, 7, false);
        msleep(5); /* pll locking */
 
        /* launch optimization algorithm */
-       tda18271_write_regs(fe, R_EP2, 1);
+       __tda18271_write_regs(fe, R_EP2, 1, false);
        msleep(30); /* image mid optimization completion */
 
        /* high-band */
@@ -456,30 +491,33 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_MD1] = 0x71;
        regs[R_MD2] = 0xcd;
 
-       tda18271_write_regs(fe, R_EP3, 11);
+       __tda18271_write_regs(fe, R_EP3, 11, false);
        msleep(5); /* pll locking */
 
        /* launch detector */
-       tda18271_write_regs(fe, R_EP1, 1);
+       __tda18271_write_regs(fe, R_EP1, 1, false);
        msleep(5); /* wanted high measurement */
 
        regs[R_EP5] = 0x87;
        regs[R_CD1] = 0x65;
        regs[R_CD2] = 0x50;
 
-       tda18271_write_regs(fe, R_EP3, 7);
+       __tda18271_write_regs(fe, R_EP3, 7, false);
        msleep(5); /* pll locking */
 
        /* launch optimization algorithm */
-       tda18271_write_regs(fe, R_EP2, 1);
+       __tda18271_write_regs(fe, R_EP2, 1, false);
        msleep(30); /* image high optimization completion */
 
        /* return to normal mode */
        regs[R_EP4] = 0x64;
-       tda18271_write_regs(fe, R_EP4, 1);
+       __tda18271_write_regs(fe, R_EP4, 1, false);
 
        /* synchronize */
-       tda18271_write_regs(fe, R_EP1, 1);
+       __tda18271_write_regs(fe, R_EP1, 1, false);
+
+       i2c_unlock_adapter(priv->i2c_props.adap);
+       tda18271_i2c_gate_ctrl(fe, 0);
 
        return 0;
 }
index 824f1911ee21bcdcf3282ef33ffece13a1f3b654..3d7526e28d426f8ca119f4d3b1326abd469b7622 100644 (file)
@@ -500,7 +500,7 @@ static int af9015_read_config(struct dvb_usb_device *d)
                case 3:
                        state->af9013_config[i].clock = 25000000;
                        break;
-               };
+               }
                dev_dbg(&d->udev->dev, "%s: [%d] xtal=%d set clock=%d\n",
                                __func__, i, val,
                                state->af9013_config[i].clock);
@@ -568,7 +568,7 @@ static int af9015_read_config(struct dvb_usb_device *d)
                                        "supported, please report!\n",
                                        KBUILD_MODNAME, val);
                        return -ENODEV;
-               };
+               }
 
                state->af9013_config[i].tuner = val;
                dev_dbg(&d->udev->dev, "%s: [%d] tuner id=%d\n",
index aabd3fc03ea7e1594c00aab276364b857e9459ff..ea27eaff4e34fdc77d9739d82b4620698a58fca7 100644 (file)
@@ -520,7 +520,7 @@ static int af9035_read_config(struct dvb_usb_device *d)
                        dev_warn(&d->udev->dev, "%s: tuner id=%02x not " \
                                        "supported, please report!",
                                        KBUILD_MODNAME, tmp);
-               };
+               }
 
                /* tuner IF frequency */
                ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_L + eeprom_shift, &tmp);
index 8d7fef84afd8b5d0d2b93c1d49ec7e7306f3d94a..83684ed023cd9bba08a20ae9cfe682f636da5a36 100644 (file)
@@ -93,7 +93,7 @@ static int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
        /* call the universal NEC remote processor, to find out the key's state and event */
        dvb_usb_nec_rc_key_to_event(d,key,event,state);
        if (key[0] != 0)
-               deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+               deb_rc("key: %*ph\n", 5, key);
        ret = 0;
 out:
        kfree(key);
index 0a98548ecd172448bed6c60b0cf9a5ee182c6ca8..9fd1527494ebd65ab200c38f13a20e28330034a1 100644 (file)
@@ -172,8 +172,7 @@ static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
                if (*event != d->last_event)
                        st->rc_counter = 0;
 
-               deb_rc("key: %x %x %x %x %x\n",
-                      key[0], key[1], key[2], key[3], key[4]);
+               deb_rc("key: %*ph\n", 5, key);
        }
        return 0;
 }
index a76bbb29ca36eeb0c5a3cfc0b42fe9a7ae422df8..af0d4321845b575589ca5a045eb2490f207d1d42 100644 (file)
@@ -473,7 +473,7 @@ int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
        dvb_usb_generic_rw(d,&cmd,1,key,5,0);
        dvb_usb_nec_rc_key_to_event(d,key,event,state);
        if (key[0] != 0)
-               deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+               deb_info("key: %*ph\n", 5, key);
        return 0;
 }
 EXPORT_SYMBOL(dibusb_rc_query);
index ff34419a4c88438ca74ac0eac19180d9fbeafd07..772bde3c5020a63b026567cf6e62ba44f2c8714b 100644 (file)
@@ -253,7 +253,7 @@ static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
        }
 
        if (key[0] != 0)
-               deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+               deb_rc("key: %*ph\n", 5, key);
        return 0;
 }
 
index 66f205c112b2fe784d5bff6dc1ed0033ee606d68..c357fb3b0a883c382a6c480a0c9567f665f8d10e 100644 (file)
@@ -84,7 +84,7 @@ static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
        dvb_usb_generic_rw(d,&cmd,1,key,5,0);
        dvb_usb_nec_rc_key_to_event(d,key,event,state);
        if (key[0] != 0)
-               deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+               deb_info("key: %*ph\n", 5, key);
        return 0;
 }
 
index 288af29a8bb74294195119343b50151b9f044ec9..661bb75be955c7f6ba474382675aa50755b2ed4f 100644 (file)
@@ -358,7 +358,7 @@ static int m920x_firmware_download(struct usb_device *udev, const struct firmwar
 
        if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0)
                goto done;
-       deb("%x %x %x %x\n", read[0], read[1], read[2], read[3]);
+       deb("%*ph\n", 4, read);
 
        if ((ret = m920x_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0)
                goto done;
index acefaa89cc53724fa69d8c2afe1831990d8ed433..7a8c8c18590fdcb16c561cff57ea6d2abc6f875e 100644 (file)
@@ -677,6 +677,7 @@ static struct usb_device_id technisat_usb2_id_table[] = {
        { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_DVB_S2) },
        { 0 }           /* Terminating entry */
 };
+MODULE_DEVICE_TABLE(usb, technisat_usb2_id_table);
 
 /* device description */
 static struct dvb_usb_device_properties technisat_usb2_devices = {
index f7297ae76b4888f8a8aafc3b52e09f4b0066fd3d..16a84f9f46d8421e9c902a2b9886a950f1e6bc4d 100644 (file)
@@ -2203,7 +2203,7 @@ EXPORT_SYMBOL_GPL(em28xx_tuner_callback);
 
 static inline void em28xx_set_model(struct em28xx *dev)
 {
-       memcpy(&dev->board, &em28xx_boards[dev->model], sizeof(dev->board));
+       dev->board = em28xx_boards[dev->model];
 
        /* Those are the default values for the majority of boards
           Use those values if not specified otherwise at boards entry
index 913e5227897a3c4b68a7ad51ec254c7bb51d41e0..13ae821949e9f5f3007aaf77554e63e1551cc28e 100644 (file)
@@ -574,18 +574,19 @@ static void pctv_520e_init(struct em28xx *dev)
                i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
 };
 
-static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe, int val)
+static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct em28xx *dev = fe->dvb->priv;
 #ifdef CONFIG_GPIOLIB
        struct em28xx_dvb *dvb = dev->dvb;
        int ret;
        unsigned long flags;
 
-       if (val)
-               flags = GPIOF_OUT_INIT_LOW;
+       if (c->lna == 1)
+               flags = GPIOF_OUT_INIT_HIGH; /* enable LNA */
        else
-               flags = GPIOF_OUT_INIT_HIGH;
+               flags = GPIOF_OUT_INIT_LOW; /* disable LNA */
 
        ret = gpio_request_one(dvb->lna_gpio, flags, NULL);
        if (ret)
@@ -595,8 +596,8 @@ static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe, int val)
 
        return ret;
 #else
-       dev_warn(&dev->udev->dev, "%s: LNA control is disabled\n",
-                       KBUILD_MODNAME);
+       dev_warn(&dev->udev->dev, "%s: LNA control is disabled (lna=%u)\n",
+                       KBUILD_MODNAME, c->lna);
        return 0;
 #endif
 }
index b62740846061d583bfed4d5c56365c7fb89586c9..34a26e0cfe77565f81924b325fb06a9d78750009 100644 (file)
@@ -100,12 +100,21 @@ int stk1160_write_reg(struct stk1160 *dev, u16 reg, u16 value)
 
 void stk1160_select_input(struct stk1160 *dev)
 {
+       int route;
        static const u8 gctrl[] = {
-               0x98, 0x90, 0x88, 0x80
+               0x98, 0x90, 0x88, 0x80, 0x98
        };
 
-       if (dev->ctl_input < ARRAY_SIZE(gctrl))
+       if (dev->ctl_input == STK1160_SVIDEO_INPUT)
+               route = SAA7115_SVIDEO3;
+       else
+               route = SAA7115_COMPOSITE0;
+
+       if (dev->ctl_input < ARRAY_SIZE(gctrl)) {
+               v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
+                               route, 0, 0);
                stk1160_write_reg(dev, STK1160_GCTRL, gctrl[dev->ctl_input]);
+       }
 }
 
 /* TODO: We should break this into pieces */
@@ -351,8 +360,6 @@ static int stk1160_probe(struct usb_interface *interface,
 
        /* i2c reset saa711x */
        v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0);
-       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
-                               0, 0, 0);
        v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
 
        /* reset stk1160 to default values */
index fe6e857969cadb0c2807a788f1c59973e9219229..6694f9e2ca576c59fd0028992036b8cea101af04 100644 (file)
@@ -419,7 +419,12 @@ static int vidioc_enum_input(struct file *file, void *priv,
        if (i->index > STK1160_MAX_INPUT)
                return -EINVAL;
 
-       sprintf(i->name, "Composite%d", i->index);
+       /* S-Video special handling */
+       if (i->index == STK1160_SVIDEO_INPUT)
+               sprintf(i->name, "S-Video");
+       else
+               sprintf(i->name, "Composite%d", i->index);
+
        i->type = V4L2_INPUT_TYPE_CAMERA;
        i->std = dev->vdev.tvnorms;
        return 0;
index 3feba0033f98df4439795121c2004a1c5048b256..68c8707d36abed789d196ccd3e8a5d528b0b78ac 100644 (file)
@@ -46,7 +46,8 @@
 
 #define STK1160_MIN_PKT_SIZE 3072
 
-#define STK1160_MAX_INPUT 3
+#define STK1160_MAX_INPUT 4
+#define STK1160_SVIDEO_INPUT 4
 
 #define STK1160_I2C_TIMEOUT 100
 
index 5577381b5bf057357c6c4f591e4eb09269c2eb38..18a91fae6bc1869e644ffa05e5e103e13b67a3dc 100644 (file)
@@ -122,21 +122,27 @@ static struct vb2_ops uvc_queue_qops = {
        .buf_finish = uvc_buffer_finish,
 };
 
-void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
+int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
                    int drop_corrupted)
 {
+       int ret;
+
        queue->queue.type = type;
        queue->queue.io_modes = VB2_MMAP | VB2_USERPTR;
        queue->queue.drv_priv = queue;
        queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
        queue->queue.ops = &uvc_queue_qops;
        queue->queue.mem_ops = &vb2_vmalloc_memops;
-       vb2_queue_init(&queue->queue);
+       ret = vb2_queue_init(&queue->queue);
+       if (ret)
+               return ret;
 
        mutex_init(&queue->mutex);
        spin_lock_init(&queue->irqlock);
        INIT_LIST_HEAD(&queue->irqqueue);
        queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0;
+
+       return 0;
 }
 
 /* -----------------------------------------------------------------------------
index 1c15b4227bdbd3886ff0e2db32ad00d73b10524e..57c3076a4625b09d4b75d05671c3bfbe38eb9109 100644 (file)
@@ -1755,7 +1755,9 @@ int uvc_video_init(struct uvc_streaming *stream)
        atomic_set(&stream->active, 0);
 
        /* Initialize the video buffers queue. */
-       uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);
+       ret = uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);
+       if (ret)
+               return ret;
 
        /* Alternate setting 0 should be the default, yet the XBox Live Vision
         * Cam (and possibly other devices) crash or otherwise misbehave if
index 3764040475bbe75647cd7b14f3a66f1e6383aef7..af216ec45e390fa1bc8863372fd742b6b43b53da 100644 (file)
@@ -600,7 +600,7 @@ extern struct uvc_driver uvc_driver;
 extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id);
 
 /* Video buffers queue management. */
-extern void uvc_queue_init(struct uvc_video_queue *queue,
+extern int uvc_queue_init(struct uvc_video_queue *queue,
                enum v4l2_buf_type type, int drop_corrupted);
 extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
                struct v4l2_requestbuffers *rb);
index 631cdc0e0bdaab5524b0f9a6eff5bc8208791a2b..f6ee201d9347de19c52d12c7d0f15d86fb09eeec 100644 (file)
@@ -384,6 +384,25 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
                "Extended SAR",
                NULL,
        };
+       static const char * const h264_fp_arrangement_type[] = {
+               "Checkerboard",
+               "Column",
+               "Row",
+               "Side by Side",
+               "Top Bottom",
+               "Temporal",
+               NULL,
+       };
+       static const char * const h264_fmo_map_type[] = {
+               "Interleaved Slices",
+               "Scattered Slices",
+               "Foreground with Leftover",
+               "Box Out",
+               "Raster Scan",
+               "Wipe Scan",
+               "Explicit",
+               NULL,
+       };
        static const char * const mpeg_mpeg4_level[] = {
                "0",
                "0b",
@@ -508,6 +527,10 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
                return h264_profile;
        case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
                return vui_sar_idc;
+       case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:
+               return h264_fp_arrangement_type;
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:
+               return h264_fmo_map_type;
        case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
                return mpeg_mpeg4_level;
        case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
@@ -643,6 +666,22 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH:        return "Horizontal Size of SAR";
        case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:           return "Aspect Ratio VUI Enable";
        case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:              return "VUI Aspect Ratio IDC";
+       case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:        return "H264 Enable Frame Packing SEI";
+       case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0:   return "H264 Set Curr. Frame as Frame0";
+       case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:  return "H264 FP Arrangement Type";
+       case V4L2_CID_MPEG_VIDEO_H264_FMO:                      return "H264 Flexible MB Ordering";
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:             return "H264 Map Type for FMO";
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP:          return "H264 FMO Number of Slice Groups";
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION:     return "H264 FMO Direction of Change";
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE:          return "H264 FMO Size of 1st Slice Grp";
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH:           return "H264 FMO No. of Consecutive MBs";
+       case V4L2_CID_MPEG_VIDEO_H264_ASO:                      return "H264 Arbitrary Slice Ordering";
+       case V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER:          return "H264 ASO Slice Order";
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING:      return "Enable H264 Hierarchical Coding";
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE: return "H264 Hierarchical Coding Type";
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:return "H264 Number of HC Layers";
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP:
+                                                               return "H264 Set QP Value for HC Layers";
        case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:              return "MPEG4 I-Frame QP Value";
        case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:              return "MPEG4 P-Frame QP Value";
        case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:              return "MPEG4 B-Frame QP Value";
@@ -657,6 +696,7 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_MPEG_VIDEO_VBV_SIZE:                      return "VBV Buffer Size";
        case V4L2_CID_MPEG_VIDEO_DEC_PTS:                       return "Video Decoder PTS";
        case V4L2_CID_MPEG_VIDEO_DEC_FRAME:                     return "Video Decoder Frame Count";
+       case V4L2_CID_MPEG_VIDEO_VBV_DELAY:                     return "Initial Delay for VBV Control";
 
        /* CAMERA controls */
        /* Keep the order of the 'case's the same as in videodev2.h! */
@@ -749,6 +789,7 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_IMAGE_PROC_CLASS:         return "Image Processing Controls";
        case V4L2_CID_LINK_FREQ:                return "Link Frequency";
        case V4L2_CID_PIXEL_RATE:               return "Pixel Rate";
+       case V4L2_CID_TEST_PATTERN:             return "Test Pattern";
 
        /* DV controls */
        case V4L2_CID_DV_CLASS:                 return "Digital Video Controls";
@@ -853,6 +894,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
        case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
        case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
+       case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:
        case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
        case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
        case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
@@ -862,6 +905,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_DV_TX_MODE:
        case V4L2_CID_DV_TX_RGB_RANGE:
        case V4L2_CID_DV_RX_RGB_RANGE:
+       case V4L2_CID_TEST_PATTERN:
                *type = V4L2_CTRL_TYPE_MENU;
                break;
        case V4L2_CID_LINK_FREQ:
@@ -1648,6 +1692,36 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
 
+/* Helper function for standard menu controls with driver defined menu */
+struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
+                       const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
+                       s32 mask, s32 def, const char * const *qmenu)
+{
+       enum v4l2_ctrl_type type;
+       const char *name;
+       u32 flags;
+       s32 step;
+       s32 min;
+
+       /* v4l2_ctrl_new_std_menu_items() should only be called for
+        * standard controls without a standard menu.
+        */
+       if (v4l2_ctrl_get_menu(id)) {
+               handler_set_err(hdl, -EINVAL);
+               return NULL;
+       }
+
+       v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
+       if (type != V4L2_CTRL_TYPE_MENU || qmenu == NULL) {
+               handler_set_err(hdl, -EINVAL);
+               return NULL;
+       }
+       return v4l2_ctrl_new(hdl, ops, id, name, type, 0, max, mask, def,
+                            flags, qmenu, NULL, NULL);
+
+}
+EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items);
+
 /* Helper function for standard integer menu controls */
 struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
                        const struct v4l2_ctrl_ops *ops,
index 9d3e46c446ad7cf502ca49fe6dcaa1d85ec09277..8f388ff31ebb8732fd1793778c578f9395df777a 100644 (file)
@@ -157,8 +157,7 @@ static const char *v4l2_memory_names[] = {
        [V4L2_MEMORY_OVERLAY] = "overlay",
 };
 
-#define prt_names(a, arr) ((((a) >= 0) && ((a) < ARRAY_SIZE(arr))) ? \
-                          arr[a] : "unknown")
+#define prt_names(a, arr) (((unsigned)(a)) < ARRAY_SIZE(arr) ? arr[a] : "unknown")
 
 /* ------------------------------------------------------------------ */
 /* debug help functions                                               */
@@ -2188,6 +2187,7 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
        int ret = 0;
 
        switch (cmd) {
+       case VIDIOC_PREPARE_BUF:
        case VIDIOC_QUERYBUF:
        case VIDIOC_QBUF:
        case VIDIOC_DQBUF: {
@@ -2211,6 +2211,10 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
                struct v4l2_subdev_edid *edid = parg;
 
                if (edid->blocks) {
+                       if (edid->blocks > 256) {
+                               ret = -EINVAL;
+                               break;
+                       }
                        *user_ptr = (void __user *)edid->edid;
                        *kernel_ptr = (void *)&edid->edid;
                        *array_size = edid->blocks * 128;
index e6a26b433e87ffe74728a5e3b93ca353d6e1d83d..432df119af278dd953a492fece76552a4c8d3e86 100644 (file)
@@ -276,6 +276,9 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
  */
 static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
+       if (!V4L2_TYPE_IS_MULTIPLANAR(b->type))
+               return 0;
+
        /* Is memory for copying plane information present? */
        if (NULL == b->m.planes) {
                dprintk(1, "Multi-planar buffer passed but "
@@ -331,10 +334,9 @@ static bool __buffers_in_use(struct vb2_queue *q)
  * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
  * returned to userspace
  */
-static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
+static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 {
        struct vb2_queue *q = vb->vb2_queue;
-       int ret;
 
        /* Copy back data such as timestamp, flags, etc. */
        memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
@@ -342,14 +344,11 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
        b->reserved = vb->v4l2_buf.reserved;
 
        if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
-               ret = __verify_planes_array(vb, b);
-               if (ret)
-                       return ret;
-
                /*
                 * Fill in plane-related data if userspace provided an array
-                * for it. The memory and size is verified above.
+                * for it. The caller has already verified memory and size.
                 */
+               b->length = vb->num_planes;
                memcpy(b->m.planes, vb->v4l2_planes,
                        b->length * sizeof(struct v4l2_plane));
        } else {
@@ -391,8 +390,6 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 
        if (__buffer_in_use(q, vb))
                b->flags |= V4L2_BUF_FLAG_MAPPED;
-
-       return 0;
 }
 
 /**
@@ -411,6 +408,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
 {
        struct vb2_buffer *vb;
+       int ret;
 
        if (b->type != q->type) {
                dprintk(1, "querybuf: wrong buffer type\n");
@@ -422,8 +420,10 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
                return -EINVAL;
        }
        vb = q->bufs[b->index];
-
-       return __fill_v4l2_buffer(vb, b);
+       ret = __verify_planes_array(vb, b);
+       if (!ret)
+               __fill_v4l2_buffer(vb, b);
+       return ret;
 }
 EXPORT_SYMBOL(vb2_querybuf);
 
@@ -813,24 +813,16 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
 EXPORT_SYMBOL_GPL(vb2_buffer_done);
 
 /**
- * __fill_vb2_buffer() - fill a vb2_buffer with information provided in
- * a v4l2_buffer by the userspace
+ * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
+ * v4l2_buffer by the userspace. The caller has already verified that struct
+ * v4l2_buffer has a valid number of planes.
  */
-static int __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
+static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
                                struct v4l2_plane *v4l2_planes)
 {
        unsigned int plane;
-       int ret;
 
        if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
-               /*
-                * Verify that the userspace gave us a valid array for
-                * plane information.
-                */
-               ret = __verify_planes_array(vb, b);
-               if (ret)
-                       return ret;
-
                /* Fill in driver-provided information for OUTPUT types */
                if (V4L2_TYPE_IS_OUTPUT(b->type)) {
                        /*
@@ -872,8 +864,6 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
        vb->v4l2_buf.field = b->field;
        vb->v4l2_buf.timestamp = b->timestamp;
        vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_STATE_FLAGS;
-
-       return 0;
 }
 
 /**
@@ -888,10 +878,8 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
        int ret;
        int write = !V4L2_TYPE_IS_OUTPUT(q->type);
 
-       /* Verify and copy relevant information provided by the userspace */
-       ret = __fill_vb2_buffer(vb, b, planes);
-       if (ret)
-               return ret;
+       /* Copy relevant information provided by the userspace */
+       __fill_vb2_buffer(vb, b, planes);
 
        for (plane = 0; plane < vb->num_planes; ++plane) {
                /* Skip the plane if already verified */
@@ -966,7 +954,8 @@ err:
  */
 static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
-       return __fill_vb2_buffer(vb, b, vb->v4l2_planes);
+       __fill_vb2_buffer(vb, b, vb->v4l2_planes);
+       return 0;
 }
 
 /**
@@ -1059,7 +1048,9 @@ int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
                dprintk(1, "%s(): invalid buffer state %d\n", __func__, vb->state);
                return -EINVAL;
        }
-
+       ret = __verify_planes_array(vb, b);
+       if (ret < 0)
+               return ret;
        ret = __buf_prepare(vb, b);
        if (ret < 0)
                return ret;
@@ -1147,6 +1138,9 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
                ret = -EINVAL;
                goto unlock;
        }
+       ret = __verify_planes_array(vb, b);
+       if (ret)
+               goto unlock;
 
        switch (vb->state) {
        case VB2_BUF_STATE_DEQUEUED:
@@ -1243,8 +1237,10 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
                 * the locks or return an error if one occurred.
                 */
                call_qop(q, wait_finish, q);
-               if (ret)
+               if (ret) {
+                       dprintk(1, "Sleep was interrupted\n");
                        return ret;
+               }
        }
        return 0;
 }
@@ -1255,7 +1251,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
  * Will sleep if required for nonblocking == false.
  */
 static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
-                               int nonblocking)
+                               struct v4l2_buffer *b, int nonblocking)
 {
        unsigned long flags;
        int ret;
@@ -1273,10 +1269,16 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
         */
        spin_lock_irqsave(&q->done_lock, flags);
        *vb = list_first_entry(&q->done_list, struct vb2_buffer, done_entry);
-       list_del(&(*vb)->done_entry);
+       /*
+        * Only remove the buffer from done_list if v4l2_buffer can handle all
+        * the planes.
+        */
+       ret = __verify_planes_array(*vb, b);
+       if (!ret)
+               list_del(&(*vb)->done_entry);
        spin_unlock_irqrestore(&q->done_lock, flags);
 
-       return 0;
+       return ret;
 }
 
 /**
@@ -1335,12 +1337,9 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
                dprintk(1, "dqbuf: invalid buffer type\n");
                return -EINVAL;
        }
-
-       ret = __vb2_get_done_vb(q, &vb, nonblocking);
-       if (ret < 0) {
-               dprintk(1, "dqbuf: error getting next done buffer\n");
+       ret = __vb2_get_done_vb(q, &vb, b, nonblocking);
+       if (ret < 0)
                return ret;
-       }
 
        ret = call_qop(q, buf_finish, vb);
        if (ret) {
index 99c73352c430c5aefc6f679853a3826c48f1b55c..b151b7c1bd59d9fe0f7cad745802572a6f7156ea 100644 (file)
@@ -60,16 +60,6 @@ config ATMEL_PWM
          purposes including software controlled power-efficient backlights
          on LCD displays, motor control, and waveform generation.
 
-config AB8500_PWM
-       bool "AB8500 PWM support"
-       depends on AB8500_CORE && ARCH_U8500
-       select HAVE_PWM
-       depends on !PWM
-       help
-         This driver exports functions to enable/disble/config/free Pulse
-         Width Modulation in the Analog Baseband Chip AB8500.
-         It is used by led and backlight driver to control the intensity.
-
 config ATMEL_TCLIB
        bool "Atmel AT32/AT91 Timer/Counter Library"
        depends on (AVR32 || ARCH_AT91)
index b88df7a350b8a4f984f46bc35f4cb404fc7e2110..2129377c0de6ee32862c99a68a41b222784d9939 100644 (file)
@@ -44,7 +44,6 @@ obj-$(CONFIG_VMWARE_BALLOON)  += vmw_balloon.o
 obj-$(CONFIG_ARM_CHARLCD)      += arm-charlcd.o
 obj-$(CONFIG_PCH_PHUB)         += pch_phub.o
 obj-y                          += ti-st/
-obj-$(CONFIG_AB8500_PWM)       += ab8500-pwm.o
 obj-y                          += lis3lv02d/
 obj-y                          += carma/
 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
index 8ac5246e2ab2bc85a6ba82ee0a0eab732130fdf6..06c42cfb7c34d9fa972c48eeb257e5e8b50b43b8 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/suspend.h>
 #include <linux/fault-inject.h>
 #include <linux/random.h>
+#include <linux/slab.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 #include "sd_ops.h"
 #include "sdio_ops.h"
 
+/*
+ * Background operations can take a long time, depending on the housekeeping
+ * operations the card has to perform.
+ */
+#define MMC_BKOPS_MAX_TIMEOUT  (4 * 60 * 1000) /* max time to wait in ms */
+
 static struct workqueue_struct *workqueue;
 static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
 
@@ -245,6 +252,70 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
        host->ops->request(host, mrq);
 }
 
+/**
+ *     mmc_start_bkops - start BKOPS for supported cards
+ *     @card: MMC card to start BKOPS
+ *     @form_exception: A flag to indicate if this function was
+ *                      called due to an exception raised by the card
+ *
+ *     Start background operations whenever requested.
+ *     When the urgent BKOPS bit is set in a R1 command response
+ *     then background operations should be started immediately.
+*/
+void mmc_start_bkops(struct mmc_card *card, bool from_exception)
+{
+       int err;
+       int timeout;
+       bool use_busy_signal;
+
+       BUG_ON(!card);
+
+       if (!card->ext_csd.bkops_en || mmc_card_doing_bkops(card))
+               return;
+
+       err = mmc_read_bkops_status(card);
+       if (err) {
+               pr_err("%s: Failed to read bkops status: %d\n",
+                      mmc_hostname(card->host), err);
+               return;
+       }
+
+       if (!card->ext_csd.raw_bkops_status)
+               return;
+
+       if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2 &&
+           from_exception)
+               return;
+
+       mmc_claim_host(card->host);
+       if (card->ext_csd.raw_bkops_status >= EXT_CSD_BKOPS_LEVEL_2) {
+               timeout = MMC_BKOPS_MAX_TIMEOUT;
+               use_busy_signal = true;
+       } else {
+               timeout = 0;
+               use_busy_signal = false;
+       }
+
+       err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                       EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal);
+       if (err) {
+               pr_warn("%s: Error %d starting bkops\n",
+                       mmc_hostname(card->host), err);
+               goto out;
+       }
+
+       /*
+        * For urgent bkops status (LEVEL_2 and more)
+        * bkops executed synchronously, otherwise
+        * the operation is in progress
+        */
+       if (!use_busy_signal)
+               mmc_card_set_doing_bkops(card);
+out:
+       mmc_release_host(card->host);
+}
+EXPORT_SYMBOL(mmc_start_bkops);
+
 static void mmc_wait_done(struct mmc_request *mrq)
 {
        complete(&mrq->completion);
@@ -354,6 +425,14 @@ 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);
+               /*
+                * Check BKOPS urgency for each R1 response
+                */
+               if (host->card && mmc_card_mmc(host->card) &&
+                   ((mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1) ||
+                    (mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1B)) &&
+                   (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT))
+                       mmc_start_bkops(host->card, true);
        }
 
        if (!err && areq)
@@ -398,7 +477,7 @@ EXPORT_SYMBOL(mmc_wait_for_req);
  *     @card: the MMC card associated with the HPI transfer
  *
  *     Issued High Priority Interrupt, and check for card status
- *     util out-of prg-state.
+ *     until out-of prg-state.
  */
 int mmc_interrupt_hpi(struct mmc_card *card)
 {
@@ -424,8 +503,9 @@ int mmc_interrupt_hpi(struct mmc_card *card)
        case R1_STATE_IDLE:
        case R1_STATE_READY:
        case R1_STATE_STBY:
+       case R1_STATE_TRAN:
                /*
-                * In idle states, HPI is not needed and the caller
+                * In idle and transfer states, HPI is not needed and the caller
                 * can issue the next intended command immediately
                 */
                goto out;
@@ -488,6 +568,64 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries
 
 EXPORT_SYMBOL(mmc_wait_for_cmd);
 
+/**
+ *     mmc_stop_bkops - stop ongoing BKOPS
+ *     @card: MMC card to check BKOPS
+ *
+ *     Send HPI command to stop ongoing background operations to
+ *     allow rapid servicing of foreground operations, e.g. read/
+ *     writes. Wait until the card comes out of the programming state
+ *     to avoid errors in servicing read/write requests.
+ */
+int mmc_stop_bkops(struct mmc_card *card)
+{
+       int err = 0;
+
+       BUG_ON(!card);
+       err = mmc_interrupt_hpi(card);
+
+       /*
+        * If err is EINVAL, we can't issue an HPI.
+        * It should complete the BKOPS.
+        */
+       if (!err || (err == -EINVAL)) {
+               mmc_card_clr_doing_bkops(card);
+               err = 0;
+       }
+
+       return err;
+}
+EXPORT_SYMBOL(mmc_stop_bkops);
+
+int mmc_read_bkops_status(struct mmc_card *card)
+{
+       int err;
+       u8 *ext_csd;
+
+       /*
+        * In future work, we should consider storing the entire ext_csd.
+        */
+       ext_csd = kmalloc(512, GFP_KERNEL);
+       if (!ext_csd) {
+               pr_err("%s: could not allocate buffer to receive the ext_csd.\n",
+                      mmc_hostname(card->host));
+               return -ENOMEM;
+       }
+
+       mmc_claim_host(card->host);
+       err = mmc_send_ext_csd(card, ext_csd);
+       mmc_release_host(card->host);
+       if (err)
+               goto out;
+
+       card->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS];
+       card->ext_csd.raw_exception_status = ext_csd[EXT_CSD_EXP_EVENTS_STATUS];
+out:
+       kfree(ext_csd);
+       return err;
+}
+EXPORT_SYMBOL(mmc_read_bkops_status);
+
 /**
  *     mmc_set_data_timeout - set the timeout for a data command
  *     @data: data phase for command
@@ -975,7 +1113,8 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
                int             tmp;
                int             voltage;
 
-               /* REVISIT mmc_vddrange_to_ocrmask() may have set some
+               /*
+                * REVISIT mmc_vddrange_to_ocrmask() may have set some
                 * bits this regulator doesn't quite support ... don't
                 * be too picky, most cards and regulators are OK with
                 * a 0.1V range goof (it's a small error percentage).
@@ -989,12 +1128,13 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
                        max_uV = min_uV + 100 * 1000;
                }
 
-               /* avoid needless changes to this voltage; the regulator
-                * might not allow this operation
+               /*
+                * If we're using a fixed/static regulator, don't call
+                * regulator_set_voltage; it would fail.
                 */
                voltage = regulator_get_voltage(supply);
 
-               if (mmc->caps2 & MMC_CAP2_BROKEN_VOLTAGE)
+               if (regulator_count_voltages(supply) == 1)
                        min_uV = max_uV = voltage;
 
                if (voltage < 0)
@@ -1133,48 +1273,6 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type)
        mmc_host_clk_release(host);
 }
 
-static void mmc_poweroff_notify(struct mmc_host *host)
-{
-       struct mmc_card *card;
-       unsigned int timeout;
-       unsigned int notify_type = EXT_CSD_NO_POWER_NOTIFICATION;
-       int err = 0;
-
-       card = host->card;
-       mmc_claim_host(host);
-
-       /*
-        * Send power notify command only if card
-        * is mmc and notify state is powered ON
-        */
-       if (card && mmc_card_mmc(card) &&
-           (card->poweroff_notify_state == MMC_POWERED_ON)) {
-
-               if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) {
-                       notify_type = EXT_CSD_POWER_OFF_SHORT;
-                       timeout = card->ext_csd.generic_cmd6_time;
-                       card->poweroff_notify_state = MMC_POWEROFF_SHORT;
-               } else {
-                       notify_type = EXT_CSD_POWER_OFF_LONG;
-                       timeout = card->ext_csd.power_off_longtime;
-                       card->poweroff_notify_state = MMC_POWEROFF_LONG;
-               }
-
-               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                                EXT_CSD_POWER_OFF_NOTIFICATION,
-                                notify_type, timeout);
-
-               if (err && err != -EBADMSG)
-                       pr_err("Device failed to respond within %d poweroff "
-                              "time. Forcefully powering down the device\n",
-                              timeout);
-
-               /* Set the card state to no notification after the poweroff */
-               card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION;
-       }
-       mmc_release_host(host);
-}
-
 /*
  * Apply power to the MMC stack.  This is a two-stage process.
  * First, we enable power to the card without the clock running.
@@ -1237,8 +1335,6 @@ static void mmc_power_up(struct mmc_host *host)
 
 void mmc_power_off(struct mmc_host *host)
 {
-       int err = 0;
-
        if (host->ios.power_mode == MMC_POWER_OFF)
                return;
 
@@ -1247,22 +1343,6 @@ void mmc_power_off(struct mmc_host *host)
        host->ios.clock = 0;
        host->ios.vdd = 0;
 
-       /*
-        * For eMMC 4.5 device send AWAKE command before
-        * POWER_OFF_NOTIFY command, because in sleep state
-        * eMMC 4.5 devices respond to only RESET and AWAKE cmd
-        */
-       if (host->card && mmc_card_is_sleep(host->card) &&
-           host->bus_ops->resume) {
-               err = host->bus_ops->resume(host);
-
-               if (!err)
-                       mmc_poweroff_notify(host);
-               else
-                       pr_warning("%s: error %d during resume "
-                                  "(continue with poweroff sequence)\n",
-                                  mmc_hostname(host), err);
-       }
 
        /*
         * Reset ocr mask to be the highest possible voltage supported for
@@ -2052,6 +2132,11 @@ void mmc_rescan(struct work_struct *work)
        if (host->rescan_disable)
                return;
 
+       /* If there is a non-removable card registered, only scan once */
+       if ((host->caps & MMC_CAP_NONREMOVABLE) && host->rescan_entered)
+               return;
+       host->rescan_entered = 1;
+
        mmc_bus_get(host);
 
        /*
@@ -2327,9 +2412,14 @@ int mmc_suspend_host(struct mmc_host *host)
 
        mmc_bus_get(host);
        if (host->bus_ops && !host->bus_dead) {
-
-               if (host->bus_ops->suspend)
+               if (host->bus_ops->suspend) {
+                       if (mmc_card_doing_bkops(host->card)) {
+                               err = mmc_stop_bkops(host->card);
+                               if (err)
+                                       goto out;
+                       }
                        err = host->bus_ops->suspend(host);
+               }
 
                if (err == -ENOSYS || !host->bus_ops->resume) {
                        /*
@@ -2411,15 +2501,24 @@ int mmc_pm_notify(struct notifier_block *notify_block,
        struct mmc_host *host = container_of(
                notify_block, struct mmc_host, pm_notify);
        unsigned long flags;
-
+       int err = 0;
 
        switch (mode) {
        case PM_HIBERNATION_PREPARE:
        case PM_SUSPEND_PREPARE:
+               if (host->card && mmc_card_mmc(host->card) &&
+                   mmc_card_doing_bkops(host->card)) {
+                       err = mmc_stop_bkops(host->card);
+                       if (err) {
+                               pr_err("%s: didn't stop bkops\n",
+                                       mmc_hostname(host));
+                               return err;
+                       }
+                       mmc_card_clr_doing_bkops(host->card);
+               }
 
                spin_lock_irqsave(&host->lock, flags);
                host->rescan_disable = 1;
-               host->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
                spin_unlock_irqrestore(&host->lock, flags);
                cancel_delayed_work_sync(&host->detect);
 
@@ -2443,7 +2542,6 @@ int mmc_pm_notify(struct notifier_block *notify_block,
 
                spin_lock_irqsave(&host->lock, flags);
                host->rescan_disable = 0;
-               host->power_notify_type = MMC_HOST_PW_NOTIFY_LONG;
                spin_unlock_irqrestore(&host->lock, flags);
                mmc_detect_change(host, 0);
 
index 9ab5b17d488ae45f63756a43bfe8917e88b52e86..d96c643dde1c1b38eeeeaa0504d92f2d960b4088 100644 (file)
@@ -281,7 +281,7 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
        if (err)
                goto out_free;
 
-       for (i = 511; i >= 0; i--)
+       for (i = 0; i < 512; i++)
                n += sprintf(buf + n, "%02x", ext_csd[i]);
        n += sprintf(buf + n, "\n");
        BUG_ON(n != EXT_CSD_STR_LEN);
index 396b25891bb90b59083adeb85769971b6c3057b0..7cc46382fd644643f0323184709c551060fd9fa0 100644 (file)
@@ -463,6 +463,17 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
        }
 
        if (card->ext_csd.rev >= 5) {
+               /* check whether the eMMC card supports BKOPS */
+               if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) {
+                       card->ext_csd.bkops = 1;
+                       card->ext_csd.bkops_en = ext_csd[EXT_CSD_BKOPS_EN];
+                       card->ext_csd.raw_bkops_status =
+                               ext_csd[EXT_CSD_BKOPS_STATUS];
+                       if (!card->ext_csd.bkops_en)
+                               pr_info("%s: BKOPS_EN bit is not set\n",
+                                       mmc_hostname(card->host));
+               }
+
                /* check whether the eMMC card supports HPI */
                if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) {
                        card->ext_csd.hpi = 1;
@@ -996,7 +1007,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                 * so check for success and update the flag
                 */
                if (!err)
-                       card->poweroff_notify_state = MMC_POWERED_ON;
+                       card->ext_csd.power_off_notification = EXT_CSD_POWER_ON;
        }
 
        /*
@@ -1262,6 +1273,35 @@ err:
        return err;
 }
 
+static int mmc_can_poweroff_notify(const struct mmc_card *card)
+{
+       return card &&
+               mmc_card_mmc(card) &&
+               (card->ext_csd.power_off_notification == EXT_CSD_POWER_ON);
+}
+
+static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type)
+{
+       unsigned int timeout = card->ext_csd.generic_cmd6_time;
+       int err;
+
+       /* Use EXT_CSD_POWER_OFF_SHORT as default notification type. */
+       if (notify_type == EXT_CSD_POWER_OFF_LONG)
+               timeout = card->ext_csd.power_off_longtime;
+
+       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                        EXT_CSD_POWER_OFF_NOTIFICATION,
+                        notify_type, timeout);
+       if (err)
+               pr_err("%s: Power Off Notification timed out, %u\n",
+                      mmc_hostname(card->host), timeout);
+
+       /* Disable the power off notification after the switch operation. */
+       card->ext_csd.power_off_notification = EXT_CSD_NO_POWER_NOTIFICATION;
+
+       return err;
+}
+
 /*
  * Host is being removed. Free up the current card.
  */
@@ -1322,11 +1362,11 @@ static int mmc_suspend(struct mmc_host *host)
        BUG_ON(!host->card);
 
        mmc_claim_host(host);
-       if (mmc_card_can_sleep(host)) {
+       if (mmc_can_poweroff_notify(host->card))
+               err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT);
+       else if (mmc_card_can_sleep(host))
                err = mmc_card_sleep(host);
-               if (!err)
-                       mmc_card_set_sleep(host->card);
-       } else if (!mmc_host_is_spi(host))
+       else if (!mmc_host_is_spi(host))
                err = mmc_deselect_cards(host);
        host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
        mmc_release_host(host);
@@ -1348,11 +1388,7 @@ static int mmc_resume(struct mmc_host *host)
        BUG_ON(!host->card);
 
        mmc_claim_host(host);
-       if (mmc_card_is_sleep(host->card)) {
-               err = mmc_card_awake(host);
-               mmc_card_clr_sleep(host->card);
-       } else
-               err = mmc_init_card(host, host->ocr, host->card);
+       err = mmc_init_card(host, host->ocr, host->card);
        mmc_release_host(host);
 
        return err;
@@ -1363,7 +1399,6 @@ static int mmc_power_restore(struct mmc_host *host)
        int ret;
 
        host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
-       mmc_card_clr_sleep(host->card);
        mmc_claim_host(host);
        ret = mmc_init_card(host, host->ocr, host->card);
        mmc_release_host(host);
index 0ed2cc5f35b662dcded214fba101fa2f5a042c92..a0e172042e658da3e3053ba851fc7c5bce2a631b 100644 (file)
@@ -230,6 +230,10 @@ mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode)
        return 0;
 }
 
+/*
+ * NOTE: void *buf, caller for the buf is required to use DMA-capable
+ * buffer or on-stack buffer (with some overhead in callee).
+ */
 static int
 mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
                u32 opcode, void *buf, unsigned len)
@@ -239,13 +243,19 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
        struct mmc_data data = {0};
        struct scatterlist sg;
        void *data_buf;
+       int is_on_stack;
 
-       /* dma onto stack is unsafe/nonportable, but callers to this
-        * routine normally provide temporary on-stack buffers ...
-        */
-       data_buf = kmalloc(len, GFP_KERNEL);
-       if (data_buf == NULL)
-               return -ENOMEM;
+       is_on_stack = object_is_on_stack(buf);
+       if (is_on_stack) {
+               /*
+                * dma onto stack is unsafe/nonportable, but callers to this
+                * routine normally provide temporary on-stack buffers ...
+                */
+               data_buf = kmalloc(len, GFP_KERNEL);
+               if (!data_buf)
+                       return -ENOMEM;
+       } else
+               data_buf = buf;
 
        mrq.cmd = &cmd;
        mrq.data = &data;
@@ -280,8 +290,10 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
 
        mmc_wait_for_req(host, &mrq);
 
-       memcpy(buf, data_buf, len);
-       kfree(data_buf);
+       if (is_on_stack) {
+               memcpy(buf, data_buf, len);
+               kfree(data_buf);
+       }
 
        if (cmd.error)
                return cmd.error;
@@ -294,24 +306,32 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
 int mmc_send_csd(struct mmc_card *card, u32 *csd)
 {
        int ret, i;
+       u32 *csd_tmp;
 
        if (!mmc_host_is_spi(card->host))
                return mmc_send_cxd_native(card->host, card->rca << 16,
                                csd, MMC_SEND_CSD);
 
-       ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16);
+       csd_tmp = kmalloc(16, GFP_KERNEL);
+       if (!csd_tmp)
+               return -ENOMEM;
+
+       ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd_tmp, 16);
        if (ret)
-               return ret;
+               goto err;
 
        for (i = 0;i < 4;i++)
-               csd[i] = be32_to_cpu(csd[i]);
+               csd[i] = be32_to_cpu(csd_tmp[i]);
 
-       return 0;
+err:
+       kfree(csd_tmp);
+       return ret;
 }
 
 int mmc_send_cid(struct mmc_host *host, u32 *cid)
 {
        int ret, i;
+       u32 *cid_tmp;
 
        if (!mmc_host_is_spi(host)) {
                if (!host->card)
@@ -320,14 +340,20 @@ int mmc_send_cid(struct mmc_host *host, u32 *cid)
                                cid, MMC_SEND_CID);
        }
 
-       ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16);
+       cid_tmp = kmalloc(16, GFP_KERNEL);
+       if (!cid_tmp)
+               return -ENOMEM;
+
+       ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid_tmp, 16);
        if (ret)
-               return ret;
+               goto err;
 
        for (i = 0;i < 4;i++)
-               cid[i] = be32_to_cpu(cid[i]);
+               cid[i] = be32_to_cpu(cid_tmp[i]);
 
-       return 0;
+err:
+       kfree(cid_tmp);
+       return ret;
 }
 
 int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
@@ -367,18 +393,19 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc)
 }
 
 /**
- *     mmc_switch - modify EXT_CSD register
+ *     __mmc_switch - modify EXT_CSD register
  *     @card: the MMC card associated with the data transfer
  *     @set: cmd set values
  *     @index: EXT_CSD register index
  *     @value: value to program into EXT_CSD register
  *     @timeout_ms: timeout (ms) for operation performed by register write,
  *                   timeout of zero implies maximum possible timeout
+ *     @use_busy_signal: use the busy signal as response type
  *
  *     Modifies the EXT_CSD register for selected card.
  */
-int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
-              unsigned int timeout_ms)
+int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
+              unsigned int timeout_ms, bool use_busy_signal)
 {
        int err;
        struct mmc_command cmd = {0};
@@ -392,13 +419,23 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
                  (index << 16) |
                  (value << 8) |
                  set;
-       cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+       cmd.flags = MMC_CMD_AC;
+       if (use_busy_signal)
+               cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B;
+       else
+               cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1;
+
+
        cmd.cmd_timeout_ms = timeout_ms;
 
        err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
        if (err)
                return err;
 
+       /* No need to check card status in case of unblocking command */
+       if (!use_busy_signal)
+               return 0;
+
        /* Must check status to be sure of no errors */
        do {
                err = mmc_send_status(card, &status);
@@ -423,6 +460,13 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(__mmc_switch);
+
+int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
+               unsigned int timeout_ms)
+{
+       return __mmc_switch(card, set, index, value, timeout_ms, true);
+}
 EXPORT_SYMBOL_GPL(mmc_switch);
 
 int mmc_send_status(struct mmc_card *card, u32 *status)
index 236842ec955aa59f4af1ddc5fed8ab44a043dc89..6bf68799fe9733c18643d4e65f57c313abcd5b0b 100644 (file)
@@ -193,14 +193,7 @@ static int sdio_bus_remove(struct device *dev)
 }
 
 #ifdef CONFIG_PM
-
-static int pm_no_operation(struct device *dev)
-{
-       return 0;
-}
-
 static const struct dev_pm_ops sdio_bus_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation)
        SET_RUNTIME_PM_OPS(
                pm_generic_runtime_suspend,
                pm_generic_runtime_resume,
index 058242916cef1089ee2a8a22e8901464df7f4997..08c6b3dfe080497509e9f431d0ababdc51626b29 100644 (file)
@@ -100,7 +100,13 @@ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio)
 
        ctx = host->slot.handler_priv;
 
-       return gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label);
+       ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label);
+       if (ret < 0)
+               return ret;
+
+       ctx->ro_gpio = gpio;
+
+       return 0;
 }
 EXPORT_SYMBOL(mmc_gpio_request_ro);
 
index aa131b32e3b2981231ef0144398dce93c71c0ccc..9bf10e7bbfaffaafed7a373cb320cfb76c5e7fce 100644 (file)
@@ -540,6 +540,15 @@ config MMC_DW_PLTFM
 
          If unsure, say Y.
 
+config MMC_DW_EXYNOS
+       tristate "Exynos specific extentions for Synopsys DW Memory Card Interface"
+       depends on MMC_DW
+       select MMC_DW_PLTFM
+       help
+         This selects support for Samsung Exynos SoC specific extensions to the
+         Synopsys DesignWare Memory Card Interface driver. Select this option
+         for platforms based on Exynos4 and Exynos5 SoC's.
+
 config MMC_DW_PCI
        tristate "Synopsys Designware MCI support on PCI bus"
        depends on MMC_DW && PCI
index 8922b06be9256d3b1c9f24117e5b47f29b054dc6..17ad0a7ba40b4bfcb79c665df49c4798747cece3 100644 (file)
@@ -39,6 +39,7 @@ 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_EXYNOS)    += dw_mmc-exynos.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
index ab56f7db53150e907c406daff62be29fd5686cec..c97001e15227aba5b337c5cb07da0a799969d6dd 100644 (file)
 #define atmci_writel(port,reg,value)                   \
        __raw_writel((value), (port)->regs + reg)
 
+/* On AVR chips the Peripheral DMA Controller is not connected to MCI. */
+#ifdef CONFIG_AVR32
+#      define ATMCI_PDC_CONNECTED      0
+#else
+#      define ATMCI_PDC_CONNECTED      1
+#endif
+
 /*
  * Fix sconfig's burst size according to atmel MCI. We need to convert them as:
  * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3.
index 852d5fbda630295d0a95cadead64327e9f4bbec9..ddf096e3803f4b0c8a5bf0b19aa0ca9ec215e336 100644 (file)
@@ -19,6 +19,9 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/scatterlist.h>
 #include <linux/seq_file.h>
@@ -71,7 +74,7 @@ enum atmci_pdc_buf {
 };
 
 struct atmel_mci_caps {
-       bool    has_dma;
+       bool    has_dma_conf_reg;
        bool    has_pdc;
        bool    has_cfg_reg;
        bool    has_cstor_reg;
@@ -418,7 +421,7 @@ static int atmci_regs_show(struct seq_file *s, void *v)
        atmci_show_status_reg(s, "SR", buf[ATMCI_SR / 4]);
        atmci_show_status_reg(s, "IMR", buf[ATMCI_IMR / 4]);
 
-       if (host->caps.has_dma) {
+       if (host->caps.has_dma_conf_reg) {
                u32 val;
 
                val = buf[ATMCI_DMA / 4];
@@ -500,6 +503,70 @@ err:
        dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n");
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id atmci_dt_ids[] = {
+       { .compatible = "atmel,hsmci" },
+       { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, atmci_dt_ids);
+
+static struct mci_platform_data __devinit*
+atmci_of_init(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct device_node *cnp;
+       struct mci_platform_data *pdata;
+       u32 slot_id;
+
+       if (!np) {
+               dev_err(&pdev->dev, "device node not found\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               dev_err(&pdev->dev, "could not allocate memory for pdata\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       for_each_child_of_node(np, cnp) {
+               if (of_property_read_u32(cnp, "reg", &slot_id)) {
+                       dev_warn(&pdev->dev, "reg property is missing for %s\n",
+                                cnp->full_name);
+                       continue;
+               }
+
+               if (slot_id >= ATMCI_MAX_NR_SLOTS) {
+                       dev_warn(&pdev->dev, "can't have more than %d slots\n",
+                                ATMCI_MAX_NR_SLOTS);
+                       break;
+               }
+
+               if (of_property_read_u32(cnp, "bus-width",
+                                        &pdata->slot[slot_id].bus_width))
+                       pdata->slot[slot_id].bus_width = 1;
+
+               pdata->slot[slot_id].detect_pin =
+                       of_get_named_gpio(cnp, "cd-gpios", 0);
+
+               pdata->slot[slot_id].detect_is_active_high =
+                       of_property_read_bool(cnp, "cd-inverted");
+
+               pdata->slot[slot_id].wp_pin =
+                       of_get_named_gpio(cnp, "wp-gpios", 0);
+       }
+
+       return pdata;
+}
+#else /* CONFIG_OF */
+static inline struct mci_platform_data*
+atmci_of_init(struct platform_device *dev)
+{
+       return ERR_PTR(-EINVAL);
+}
+#endif
+
 static inline unsigned int atmci_get_version(struct atmel_mci *host)
 {
        return atmci_readl(host, ATMCI_VERSION) & 0x00000fff;
@@ -774,7 +841,7 @@ static void atmci_dma_complete(void *arg)
 
        dev_vdbg(&host->pdev->dev, "DMA complete\n");
 
-       if (host->caps.has_dma)
+       if (host->caps.has_dma_conf_reg)
                /* Disable DMA hardware handshaking on MCI */
                atmci_writel(host, ATMCI_DMA, atmci_readl(host, ATMCI_DMA) & ~ATMCI_DMAEN);
 
@@ -961,7 +1028,9 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
                maxburst = atmci_convert_chksize(host->dma_conf.dst_maxburst);
        }
 
-       atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(maxburst) | ATMCI_DMAEN);
+       if (host->caps.has_dma_conf_reg)
+               atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(maxburst) |
+                       ATMCI_DMAEN);
 
        sglen = dma_map_sg(chan->device->dev, data->sg,
                        data->sg_len, direction);
@@ -2046,6 +2115,13 @@ static int __init atmci_init_slot(struct atmel_mci *host,
        slot->sdc_reg = sdc_reg;
        slot->sdio_irq = sdio_irq;
 
+       dev_dbg(&mmc->class_dev,
+               "slot[%u]: bus_width=%u, detect_pin=%d, "
+               "detect_is_active_high=%s, wp_pin=%d\n",
+               id, slot_data->bus_width, slot_data->detect_pin,
+               slot_data->detect_is_active_high ? "true" : "false",
+               slot_data->wp_pin);
+
        mmc->ops = &atmci_ops;
        mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512);
        mmc->f_max = host->bus_hz / 2;
@@ -2169,7 +2245,10 @@ static bool atmci_configure_dma(struct atmel_mci *host)
 
        pdata = host->pdev->dev.platform_data;
 
-       if (pdata && find_slave_dev(pdata->dma_slave)) {
+       if (!pdata)
+               return false;
+
+       if (pdata->dma_slave && find_slave_dev(pdata->dma_slave)) {
                dma_cap_mask_t mask;
 
                /* Try to grab a DMA channel */
@@ -2210,8 +2289,8 @@ static void __init atmci_get_cap(struct atmel_mci *host)
        dev_info(&host->pdev->dev,
                        "version: 0x%x\n", version);
 
-       host->caps.has_dma = 0;
-       host->caps.has_pdc = 1;
+       host->caps.has_dma_conf_reg = 0;
+       host->caps.has_pdc = ATMCI_PDC_CONNECTED;
        host->caps.has_cfg_reg = 0;
        host->caps.has_cstor_reg = 0;
        host->caps.has_highspeed = 0;
@@ -2228,12 +2307,7 @@ static void __init atmci_get_cap(struct atmel_mci *host)
                host->caps.has_odd_clk_div = 1;
        case 0x400:
        case 0x300:
-#ifdef CONFIG_AT_HDMAC
-               host->caps.has_dma = 1;
-#else
-               dev_info(&host->pdev->dev,
-                       "has dma capability but dma engine is not selected, then use pio\n");
-#endif
+               host->caps.has_dma_conf_reg = 1;
                host->caps.has_pdc = 0;
                host->caps.has_cfg_reg = 1;
                host->caps.has_cstor_reg = 1;
@@ -2268,8 +2342,14 @@ static int __init atmci_probe(struct platform_device *pdev)
        if (!regs)
                return -ENXIO;
        pdata = pdev->dev.platform_data;
-       if (!pdata)
-               return -ENXIO;
+       if (!pdata) {
+               pdata = atmci_of_init(pdev);
+               if (IS_ERR(pdata)) {
+                       dev_err(&pdev->dev, "platform data not available\n");
+                       return PTR_ERR(pdata);
+               }
+       }
+
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
                return irq;
@@ -2308,7 +2388,7 @@ static int __init atmci_probe(struct platform_device *pdev)
 
        /* Get MCI capabilities and set operations according to it */
        atmci_get_cap(host);
-       if (host->caps.has_dma && atmci_configure_dma(host)) {
+       if (atmci_configure_dma(host)) {
                host->prepare_data = &atmci_prepare_data_dma;
                host->submit_data = &atmci_submit_data_dma;
                host->stop_transfer = &atmci_stop_transfer_dma;
@@ -2487,6 +2567,7 @@ static struct platform_driver atmci_driver = {
        .driver         = {
                .name           = "atmel_mci",
                .pm             = ATMCI_PM_OPS,
+               .of_match_table = of_match_ptr(atmci_dt_ids),
        },
 };
 
index a17dd7363cebedc69c41d28b47b6c4fd895a327a..b9b463eca1ec64a2d608f3362ede48cd418842b6 100644 (file)
@@ -24,9 +24,7 @@
 #include <asm/portmux.h>
 #include <asm/bfin_sdh.h>
 
-#if defined(CONFIG_BF51x)
-#define bfin_read_SDH_PWR_CTL          bfin_read_RSI_PWR_CTL
-#define bfin_write_SDH_PWR_CTL         bfin_write_RSI_PWR_CTL
+#if defined(CONFIG_BF51x) || defined(__ADSPBF60x__)
 #define bfin_read_SDH_CLK_CTL          bfin_read_RSI_CLK_CTL
 #define bfin_write_SDH_CLK_CTL         bfin_write_RSI_CLK_CTL
 #define bfin_write_SDH_ARGUMENT                bfin_write_RSI_ARGUMENT
 #define bfin_write_SDH_E_STATUS                bfin_write_RSI_E_STATUS
 #define bfin_read_SDH_STATUS           bfin_read_RSI_STATUS
 #define bfin_write_SDH_MASK0           bfin_write_RSI_MASK0
+#define bfin_write_SDH_E_MASK          bfin_write_RSI_E_MASK
 #define bfin_read_SDH_CFG              bfin_read_RSI_CFG
 #define bfin_write_SDH_CFG             bfin_write_RSI_CFG
+# if defined(__ADSPBF60x__)
+#  define bfin_read_SDH_BLK_SIZE       bfin_read_RSI_BLKSZ
+#  define bfin_write_SDH_BLK_SIZE      bfin_write_RSI_BLKSZ
+# else
+#  define bfin_read_SDH_PWR_CTL                bfin_read_RSI_PWR_CTL
+#  define bfin_write_SDH_PWR_CTL       bfin_write_RSI_PWR_CTL
+# endif
 #endif
 
 struct sdh_host {
@@ -62,6 +68,7 @@ struct sdh_host {
        dma_addr_t              sg_dma;
        int                     dma_len;
 
+       unsigned long           sclk;
        unsigned int            imask;
        unsigned int            power_mode;
        unsigned int            clk_div;
@@ -127,11 +134,15 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data)
        /* Only supports power-of-2 block size */
        if (data->blksz & (data->blksz - 1))
                return -EINVAL;
+#ifndef RSI_BLKSZ
        data_ctl |= ((ffs(data->blksz) - 1) << 4);
+#else
+        bfin_write_SDH_BLK_SIZE(data->blksz);
+#endif
 
        bfin_write_SDH_DATA_CTL(data_ctl);
        /* the time of a host clock period in ns */
-       cycle_ns = 1000000000 / (get_sclk() / (2 * (host->clk_div + 1)));
+       cycle_ns = 1000000000 / (host->sclk / (2 * (host->clk_div + 1)));
        timeout = data->timeout_ns / cycle_ns;
        timeout += data->timeout_clks;
        bfin_write_SDH_DATA_TIMER(timeout);
@@ -145,8 +156,13 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data)
 
        sdh_enable_stat_irq(host, (DAT_CRC_FAIL | DAT_TIME_OUT | DAT_END));
        host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma_dir);
-#if defined(CONFIG_BF54x)
-       dma_cfg |= DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_32 | DMAEN;
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
+       dma_cfg |= DMAFLOW_ARRAY | RESTART | WDSIZE_32 | DMAEN;
+# ifdef RSI_BLKSZ
+       dma_cfg |= PSIZE_32 | NDSIZE_3;
+# else
+       dma_cfg |= NDSIZE_5;
+# endif
        {
                struct scatterlist *sg;
                int i;
@@ -156,7 +172,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data)
                        host->sg_cpu[i].x_count = sg_dma_len(sg) / 4;
                        host->sg_cpu[i].x_modify = 4;
                        dev_dbg(mmc_dev(host->mmc), "%d: start_addr:0x%lx, "
-                               "cfg:0x%x, x_count:0x%x, x_modify:0x%x\n",
+                               "cfg:0x%lx, x_count:0x%lx, x_modify:0x%lx\n",
                                i, host->sg_cpu[i].start_addr,
                                host->sg_cpu[i].cfg, host->sg_cpu[i].x_count,
                                host->sg_cpu[i].x_modify);
@@ -172,6 +188,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data)
        set_dma_curr_desc_addr(host->dma_ch, (unsigned long *)host->sg_dma);
        set_dma_x_count(host->dma_ch, 0);
        set_dma_x_modify(host->dma_ch, 0);
+       SSYNC();
        set_dma_config(host->dma_ch, dma_cfg);
 #elif defined(CONFIG_BF51x)
        /* RSI DMA doesn't work in array mode */
@@ -179,6 +196,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data)
        set_dma_start_addr(host->dma_ch, sg_dma_address(&data->sg[0]));
        set_dma_x_count(host->dma_ch, length / 4);
        set_dma_x_modify(host->dma_ch, 4);
+       SSYNC();
        set_dma_config(host->dma_ch, dma_cfg);
 #endif
        bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E);
@@ -296,7 +314,6 @@ static int sdh_data_done(struct sdh_host *host, unsigned int stat)
        else
                data->bytes_xfered = 0;
 
-       sdh_disable_stat_irq(host, DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN);
        bfin_write_SDH_STATUS_CLR(DAT_END_STAT | DAT_TIMEOUT_STAT | \
                        DAT_CRC_FAIL_STAT | DAT_BLK_END_STAT | RX_OVERRUN | TX_UNDERRUN);
        bfin_write_SDH_DATA_CTL(0);
@@ -321,74 +338,115 @@ static void sdh_request(struct mmc_host *mmc, struct mmc_request *mrq)
        dev_dbg(mmc_dev(host->mmc), "%s enter, mrp:%p, cmd:%p\n", __func__, mrq, mrq->cmd);
        WARN_ON(host->mrq != NULL);
 
+       spin_lock(&host->lock);
        host->mrq = mrq;
        host->data = mrq->data;
 
        if (mrq->data && mrq->data->flags & MMC_DATA_READ) {
                ret = sdh_setup_data(host, mrq->data);
                if (ret)
-                       return;
+                       goto data_err;
        }
 
        sdh_start_cmd(host, mrq->cmd);
+data_err:
+       spin_unlock(&host->lock);
 }
 
 static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        struct sdh_host *host;
-       unsigned long flags;
        u16 clk_ctl = 0;
+#ifndef RSI_BLKSZ
        u16 pwr_ctl = 0;
+#endif
        u16 cfg;
        host = mmc_priv(mmc);
 
-       spin_lock_irqsave(&host->lock, flags);
-       if (ios->clock) {
-               unsigned long  sys_clk, ios_clk;
-               unsigned char clk_div;
-               ios_clk = 2 * ios->clock;
-               sys_clk = get_sclk();
-               clk_div = sys_clk / ios_clk;
-               if (sys_clk % ios_clk == 0)
-                       clk_div -= 1;
-               clk_div = min_t(unsigned char, clk_div, 0xFF);
-               clk_ctl |= clk_div;
-               clk_ctl |= CLK_E;
-               host->clk_div = clk_div;
-       } else
-               sdh_stop_clock(host);
-
-       if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
-#ifdef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND
-               pwr_ctl |= ROD_CTL;
-#else
-               pwr_ctl |= SD_CMD_OD | ROD_CTL;
-#endif
+       spin_lock(&host->lock);
 
-       if (ios->bus_width == MMC_BUS_WIDTH_4) {
-               cfg = bfin_read_SDH_CFG();
+       cfg = bfin_read_SDH_CFG();
+       cfg |= MWE;
+       switch (ios->bus_width) {
+       case MMC_BUS_WIDTH_4:
+#ifndef RSI_BLKSZ
                cfg &= ~PD_SDDAT3;
+#endif
                cfg |= PUP_SDDAT3;
                /* Enable 4 bit SDIO */
-               cfg |= (SD4E | MWE);
-               bfin_write_SDH_CFG(cfg);
-               clk_ctl |= WIDE_BUS;
-       } else {
-               cfg = bfin_read_SDH_CFG();
-               cfg |= MWE;
-               bfin_write_SDH_CFG(cfg);
+               cfg |= SD4E;
+               clk_ctl |= WIDE_BUS_4;
+               break;
+       case MMC_BUS_WIDTH_8:
+#ifndef RSI_BLKSZ
+               cfg &= ~PD_SDDAT3;
+#endif
+               cfg |= PUP_SDDAT3;
+               /* Disable 4 bit SDIO */
+               cfg &= ~SD4E;
+               clk_ctl |= BYTE_BUS_8;
+               break;
+       default:
+               cfg &= ~PUP_SDDAT3;
+               /* Disable 4 bit SDIO */
+               cfg &= ~SD4E;
        }
 
-       bfin_write_SDH_CLK_CTL(clk_ctl);
-
        host->power_mode = ios->power_mode;
-       if (ios->power_mode == MMC_POWER_ON)
+#ifndef RSI_BLKSZ
+       if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) {
+               pwr_ctl |= ROD_CTL;
+# ifndef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND
+               pwr_ctl |= SD_CMD_OD;
+# endif
+       }
+
+       if (ios->power_mode != MMC_POWER_OFF)
                pwr_ctl |= PWR_ON;
+       else
+               pwr_ctl &= ~PWR_ON;
 
        bfin_write_SDH_PWR_CTL(pwr_ctl);
+#else
+# ifndef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND
+       if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
+               cfg |= SD_CMD_OD;
+       else
+               cfg &= ~SD_CMD_OD;
+# endif
+
+
+       if (ios->power_mode != MMC_POWER_OFF)
+               cfg |= PWR_ON;
+       else
+               cfg &= ~PWR_ON;
+
+       bfin_write_SDH_CFG(cfg);
+#endif
        SSYNC();
 
-       spin_unlock_irqrestore(&host->lock, flags);
+       if (ios->power_mode == MMC_POWER_ON && ios->clock) {
+               unsigned char clk_div;
+               clk_div = (get_sclk() / ios->clock - 1) / 2;
+               clk_div = min_t(unsigned char, clk_div, 0xFF);
+               clk_ctl |= clk_div;
+               clk_ctl |= CLK_E;
+               host->clk_div = clk_div;
+               bfin_write_SDH_CLK_CTL(clk_ctl);
+
+       } else
+               sdh_stop_clock(host);
+
+       /* set up sdh interrupt mask*/
+       if (ios->power_mode == MMC_POWER_ON)
+               bfin_write_SDH_MASK0(DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL |
+                       RX_OVERRUN | TX_UNDERRUN | CMD_SENT | CMD_RESP_END |
+                       CMD_TIME_OUT | CMD_CRC_FAIL);
+       else
+               bfin_write_SDH_MASK0(0);
+       SSYNC();
+
+       spin_unlock(&host->lock);
 
        dev_dbg(mmc_dev(host->mmc), "SDH: clk_div = 0x%x actual clock:%ld expected clock:%d\n",
                host->clk_div,
@@ -405,7 +463,7 @@ static irqreturn_t sdh_dma_irq(int irq, void *devid)
 {
        struct sdh_host *host = devid;
 
-       dev_dbg(mmc_dev(host->mmc), "%s enter, irq_stat: 0x%04x\n", __func__,
+       dev_dbg(mmc_dev(host->mmc), "%s enter, irq_stat: 0x%04lx\n", __func__,
                get_dma_curr_irqstat(host->dma_ch));
        clear_dma_irqstat(host->dma_ch);
        SSYNC();
@@ -420,6 +478,9 @@ static irqreturn_t sdh_stat_irq(int irq, void *devid)
        int handled = 0;
 
        dev_dbg(mmc_dev(host->mmc), "%s enter\n", __func__);
+
+       spin_lock(&host->lock);
+
        status = bfin_read_SDH_E_STATUS();
        if (status & SD_CARD_DET) {
                mmc_detect_change(host->mmc, 0);
@@ -437,11 +498,30 @@ static irqreturn_t sdh_stat_irq(int irq, void *devid)
        if (status & (DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN))
                handled |= sdh_data_done(host, status);
 
+       spin_unlock(&host->lock);
+
        dev_dbg(mmc_dev(host->mmc), "%s exit\n\n", __func__);
 
        return IRQ_RETVAL(handled);
 }
 
+static void sdh_reset(void)
+{
+#if defined(CONFIG_BF54x)
+       /* Secure Digital Host shares DMA with Nand controller */
+       bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1);
+#endif
+
+       bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN);
+       SSYNC();
+
+       /* Disable card inserting detection pin. set MMC_CAP_NEEDS_POLL, and
+        * mmc stack will do the detection.
+        */
+       bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3));
+       SSYNC();
+}
+
 static int __devinit sdh_probe(struct platform_device *pdev)
 {
        struct mmc_host *mmc;
@@ -462,8 +542,16 @@ static int __devinit sdh_probe(struct platform_device *pdev)
        }
 
        mmc->ops = &sdh_ops;
-       mmc->max_segs = 32;
+#if defined(CONFIG_BF51x)
+       mmc->max_segs = 1;
+#else
+       mmc->max_segs = PAGE_SIZE / sizeof(struct dma_desc_array);
+#endif
+#ifdef RSI_BLKSZ
+       mmc->max_seg_size = -1;
+#else
        mmc->max_seg_size = 1 << 16;
+#endif
        mmc->max_blk_size = 1 << 11;
        mmc->max_blk_count = 1 << 11;
        mmc->max_req_size = PAGE_SIZE;
@@ -473,6 +561,7 @@ static int __devinit sdh_probe(struct platform_device *pdev)
        mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NEEDS_POLL;
        host = mmc_priv(mmc);
        host->mmc = mmc;
+       host->sclk = get_sclk();
 
        spin_lock_init(&host->lock);
        host->irq = drv_data->irq_int0;
@@ -497,7 +586,6 @@ static int __devinit sdh_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(pdev, mmc);
-       mmc_add_host(mmc);
 
        ret = request_irq(host->irq, sdh_stat_irq, 0, "SDH Status IRQ", host);
        if (ret) {
@@ -510,20 +598,10 @@ static int __devinit sdh_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "unable to request peripheral pins\n");
                goto out4;
        }
-#if defined(CONFIG_BF54x)
-       /* Secure Digital Host shares DMA with Nand controller */
-       bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1);
-#endif
-
-       bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN);
-       SSYNC();
 
-       /* Disable card inserting detection pin. set MMC_CAP_NEES_POLL, and
-        * mmc stack will do the detection.
-        */
-       bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3));
-       SSYNC();
+       sdh_reset();
 
+       mmc_add_host(mmc);
        return 0;
 
 out4:
@@ -571,7 +649,6 @@ static int sdh_suspend(struct platform_device *dev, pm_message_t state)
        if (mmc)
                ret = mmc_suspend_host(mmc);
 
-       bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() & ~PWR_ON);
        peripheral_free_list(drv_data->pin_req);
 
        return ret;
@@ -589,16 +666,7 @@ static int sdh_resume(struct platform_device *dev)
                return ret;
        }
 
-       bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() | PWR_ON);
-#if defined(CONFIG_BF54x)
-       /* Secure Digital Host shares DMA with Nand controller */
-       bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1);
-#endif
-       bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN);
-       SSYNC();
-
-       bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3));
-       SSYNC();
+       sdh_reset();
 
        if (mmc)
                ret = mmc_resume_host(mmc);
index 3dfd3473269de965bb0500acd2ef5512ebe9269f..20636772c09bd2aa2b794f44c3029e1f57559578 100644 (file)
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
+#include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
+#include <linux/edma.h>
 #include <linux/mmc/mmc.h>
 
 #include <linux/platform_data/mmc-davinci.h>
-#include <mach/edma.h>
 
 /*
  * Register Definitions
@@ -200,21 +201,13 @@ struct mmc_davinci_host {
        u32 bytes_left;
 
        u32 rxdma, txdma;
+       struct dma_chan *dma_tx;
+       struct dma_chan *dma_rx;
        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
-        * more links.  The entries for a given transfer differ only
-        * by memory buffer (address, length) and link field.
-        */
-       struct edmacc_param     tx_template;
-       struct edmacc_param     rx_template;
-       unsigned                n_link;
-       u32                     links[MAX_NR_SG - 1];
-
        /* For PIO we walk scatterlists one segment at a time. */
        unsigned int            sg_len;
        struct scatterlist *sg;
@@ -410,153 +403,74 @@ static void mmc_davinci_start_command(struct mmc_davinci_host *host,
 
 static void davinci_abort_dma(struct mmc_davinci_host *host)
 {
-       int sync_dev;
+       struct dma_chan *sync_dev;
 
        if (host->data_dir == DAVINCI_MMC_DATADIR_READ)
-               sync_dev = host->rxdma;
+               sync_dev = host->dma_rx;
        else
-               sync_dev = host->txdma;
-
-       edma_stop(sync_dev);
-       edma_clean_channel(sync_dev);
-}
-
-static void
-mmc_davinci_xfer_done(struct mmc_davinci_host *host, struct mmc_data *data);
-
-static void mmc_davinci_dma_cb(unsigned channel, u16 ch_status, void *data)
-{
-       if (DMA_COMPLETE != ch_status) {
-               struct mmc_davinci_host *host = data;
-
-               /* Currently means:  DMA Event Missed, or "null" transfer
-                * request was seen.  In the future, TC errors (like bad
-                * addresses) might be presented too.
-                */
-               dev_warn(mmc_dev(host->mmc), "DMA %s error\n",
-                       (host->data->flags & MMC_DATA_WRITE)
-                               ? "write" : "read");
-               host->data->error = -EIO;
-               mmc_davinci_xfer_done(host, host->data);
-       }
-}
-
-/* Set up tx or rx template, to be modified and updated later */
-static void __init mmc_davinci_dma_setup(struct mmc_davinci_host *host,
-               bool tx, struct edmacc_param *template)
-{
-       unsigned        sync_dev;
-       const u16       acnt = 4;
-       const u16       bcnt = rw_threshold >> 2;
-       const u16       ccnt = 0;
-       u32             src_port = 0;
-       u32             dst_port = 0;
-       s16             src_bidx, dst_bidx;
-       s16             src_cidx, dst_cidx;
-
-       /*
-        * A-B Sync transfer:  each DMA request is for one "frame" of
-        * rw_threshold bytes, broken into "acnt"-size chunks repeated
-        * "bcnt" times.  Each segment needs "ccnt" such frames; since
-        * we tell the block layer our mmc->max_seg_size limit, we can
-        * trust (later) that it's within bounds.
-        *
-        * The FIFOs are read/written in 4-byte chunks (acnt == 4) and
-        * EDMA will optimize memory operations to use larger bursts.
-        */
-       if (tx) {
-               sync_dev = host->txdma;
-
-               /* src_prt, ccnt, and link to be set up later */
-               src_bidx = acnt;
-               src_cidx = acnt * bcnt;
-
-               dst_port = host->mem_res->start + DAVINCI_MMCDXR;
-               dst_bidx = 0;
-               dst_cidx = 0;
-       } else {
-               sync_dev = host->rxdma;
-
-               src_port = host->mem_res->start + DAVINCI_MMCDRR;
-               src_bidx = 0;
-               src_cidx = 0;
-
-               /* dst_prt, ccnt, and link to be set up later */
-               dst_bidx = acnt;
-               dst_cidx = acnt * bcnt;
-       }
-
-       /*
-        * We can't use FIFO mode for the FIFOs because MMC FIFO addresses
-        * are not 256-bit (32-byte) aligned.  So we use INCR, and the W8BIT
-        * parameter is ignored.
-        */
-       edma_set_src(sync_dev, src_port, INCR, W8BIT);
-       edma_set_dest(sync_dev, dst_port, INCR, W8BIT);
+               sync_dev = host->dma_tx;
 
-       edma_set_src_index(sync_dev, src_bidx, src_cidx);
-       edma_set_dest_index(sync_dev, dst_bidx, dst_cidx);
-
-       edma_set_transfer_params(sync_dev, acnt, bcnt, ccnt, 8, ABSYNC);
-
-       edma_read_slot(sync_dev, template);
-
-       /* don't bother with irqs or chaining */
-       template->opt |= EDMA_CHAN_SLOT(sync_dev) << 12;
+       dmaengine_terminate_all(sync_dev);
 }
 
-static void mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
+static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
                struct mmc_data *data)
 {
-       struct edmacc_param     *template;
-       int                     channel, slot;
-       unsigned                link;
-       struct scatterlist      *sg;
-       unsigned                sg_len;
-       unsigned                bytes_left = host->bytes_left;
-       const unsigned          shift = ffs(rw_threshold) - 1;
+       struct dma_chan *chan;
+       struct dma_async_tx_descriptor *desc;
+       int ret = 0;
 
        if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
-               template = &host->tx_template;
-               channel = host->txdma;
+               struct dma_slave_config dma_tx_conf = {
+                       .direction = DMA_MEM_TO_DEV,
+                       .dst_addr = host->mem_res->start + DAVINCI_MMCDXR,
+                       .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+                       .dst_maxburst =
+                               rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES,
+               };
+               chan = host->dma_tx;
+               dmaengine_slave_config(host->dma_tx, &dma_tx_conf);
+
+               desc = dmaengine_prep_slave_sg(host->dma_tx,
+                               data->sg,
+                               host->sg_len,
+                               DMA_MEM_TO_DEV,
+                               DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               if (!desc) {
+                       dev_dbg(mmc_dev(host->mmc),
+                               "failed to allocate DMA TX descriptor");
+                       ret = -1;
+                       goto out;
+               }
        } else {
-               template = &host->rx_template;
-               channel = host->rxdma;
-       }
-
-       /* We know sg_len and ccnt will never be out of range because
-        * we told the mmc layer which in turn tells the block layer
-        * to ensure that it only hands us one scatterlist segment
-        * per EDMA PARAM entry.  Update the PARAM
-        * entries needed for each segment of this scatterlist.
-        */
-       for (slot = channel, link = 0, sg = data->sg, sg_len = host->sg_len;
-                       sg_len-- != 0 && bytes_left;
-                       sg = sg_next(sg), slot = host->links[link++]) {
-               u32             buf = sg_dma_address(sg);
-               unsigned        count = sg_dma_len(sg);
-
-               template->link_bcntrld = sg_len
-                               ? (EDMA_CHAN_SLOT(host->links[link]) << 5)
-                               : 0xffff;
-
-               if (count > bytes_left)
-                       count = bytes_left;
-               bytes_left -= count;
-
-               if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE)
-                       template->src = buf;
-               else
-                       template->dst = buf;
-               template->ccnt = count >> shift;
-
-               edma_write_slot(slot, template);
+               struct dma_slave_config dma_rx_conf = {
+                       .direction = DMA_DEV_TO_MEM,
+                       .src_addr = host->mem_res->start + DAVINCI_MMCDRR,
+                       .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+                       .src_maxburst =
+                               rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES,
+               };
+               chan = host->dma_rx;
+               dmaengine_slave_config(host->dma_rx, &dma_rx_conf);
+
+               desc = dmaengine_prep_slave_sg(host->dma_rx,
+                               data->sg,
+                               host->sg_len,
+                               DMA_DEV_TO_MEM,
+                               DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               if (!desc) {
+                       dev_dbg(mmc_dev(host->mmc),
+                               "failed to allocate DMA RX descriptor");
+                       ret = -1;
+                       goto out;
+               }
        }
 
-       if (host->version == MMC_CTLR_VERSION_2)
-               edma_clear_event(channel);
+       dmaengine_submit(desc);
+       dma_async_issue_pending(chan);
 
-       edma_start(channel);
+out:
+       return ret;
 }
 
 static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host,
@@ -564,6 +478,7 @@ static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host,
 {
        int i;
        int mask = rw_threshold - 1;
+       int ret = 0;
 
        host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
                                ((data->flags & MMC_DATA_WRITE)
@@ -583,70 +498,48 @@ static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host,
        }
 
        host->do_dma = 1;
-       mmc_davinci_send_dma_request(host, data);
+       ret = mmc_davinci_send_dma_request(host, data);
 
-       return 0;
+       return ret;
 }
 
 static void __init_or_module
 davinci_release_dma_channels(struct mmc_davinci_host *host)
 {
-       unsigned        i;
-
        if (!host->use_dma)
                return;
 
-       for (i = 0; i < host->n_link; i++)
-               edma_free_slot(host->links[i]);
-
-       edma_free_channel(host->txdma);
-       edma_free_channel(host->rxdma);
+       dma_release_channel(host->dma_tx);
+       dma_release_channel(host->dma_rx);
 }
 
 static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host)
 {
-       u32 link_size;
-       int r, i;
-
-       /* Acquire master DMA write channel */
-       r = edma_alloc_channel(host->txdma, mmc_davinci_dma_cb, host,
-                       EVENTQ_DEFAULT);
-       if (r < 0) {
-               dev_warn(mmc_dev(host->mmc), "alloc %s channel err %d\n",
-                               "tx", r);
-               return r;
-       }
-       mmc_davinci_dma_setup(host, true, &host->tx_template);
-
-       /* Acquire master DMA read channel */
-       r = edma_alloc_channel(host->rxdma, mmc_davinci_dma_cb, host,
-                       EVENTQ_DEFAULT);
-       if (r < 0) {
-               dev_warn(mmc_dev(host->mmc), "alloc %s channel err %d\n",
-                               "rx", r);
-               goto free_master_write;
+       int r;
+       dma_cap_mask_t mask;
+
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+
+       host->dma_tx =
+               dma_request_channel(mask, edma_filter_fn, &host->txdma);
+       if (!host->dma_tx) {
+               dev_err(mmc_dev(host->mmc), "Can't get dma_tx channel\n");
+               return -ENODEV;
        }
-       mmc_davinci_dma_setup(host, false, &host->rx_template);
 
-       /* Allocate parameter RAM slots, which will later be bound to a
-        * channel as needed to handle a scatterlist.
-        */
-       link_size = min_t(unsigned, host->nr_sg, ARRAY_SIZE(host->links));
-       for (i = 0; i < link_size; i++) {
-               r = edma_alloc_slot(EDMA_CTLR(host->txdma), EDMA_SLOT_ANY);
-               if (r < 0) {
-                       dev_dbg(mmc_dev(host->mmc), "dma PaRAM alloc --> %d\n",
-                               r);
-                       break;
-               }
-               host->links[i] = r;
+       host->dma_rx =
+               dma_request_channel(mask, edma_filter_fn, &host->rxdma);
+       if (!host->dma_rx) {
+               dev_err(mmc_dev(host->mmc), "Can't get dma_rx channel\n");
+               r = -ENODEV;
+               goto free_master_write;
        }
-       host->n_link = i;
 
        return 0;
 
 free_master_write:
-       edma_free_channel(host->txdma);
+       dma_release_channel(host->dma_tx);
 
        return r;
 }
@@ -1359,7 +1252,7 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
         * Each hw_seg uses one EDMA parameter RAM slot, always one
         * channel and then usually some linked slots.
         */
-       mmc->max_segs           = 1 + host->n_link;
+       mmc->max_segs           = MAX_NR_SG;
 
        /* EDMA limit per hw segment (one or two MBytes) */
        mmc->max_seg_size       = MAX_CCNT * rw_threshold;
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
new file mode 100644 (file)
index 0000000..660bbc5
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Exynos Specific Extensions for Synopsys DW Multimedia Card Interface driver
+ *
+ * Copyright (C) 2012, Samsung Electronics Co., 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/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+
+#define NUM_PINS(x)                    (x + 2)
+
+#define SDMMC_CLKSEL                   0x09C
+#define SDMMC_CLKSEL_CCLK_SAMPLE(x)    (((x) & 7) << 0)
+#define SDMMC_CLKSEL_CCLK_DRIVE(x)     (((x) & 7) << 16)
+#define SDMMC_CLKSEL_CCLK_DIVIDER(x)   (((x) & 7) << 24)
+#define SDMMC_CLKSEL_GET_DRV_WD3(x)    (((x) >> 16) & 0x7)
+#define SDMMC_CLKSEL_TIMING(x, y, z)   (SDMMC_CLKSEL_CCLK_SAMPLE(x) |  \
+                                       SDMMC_CLKSEL_CCLK_DRIVE(y) |    \
+                                       SDMMC_CLKSEL_CCLK_DIVIDER(z))
+
+#define SDMMC_CMD_USE_HOLD_REG         BIT(29)
+
+#define EXYNOS4210_FIXED_CIU_CLK_DIV   2
+#define EXYNOS4412_FIXED_CIU_CLK_DIV   4
+
+/* Variations in Exynos specific dw-mshc controller */
+enum dw_mci_exynos_type {
+       DW_MCI_TYPE_EXYNOS4210,
+       DW_MCI_TYPE_EXYNOS4412,
+       DW_MCI_TYPE_EXYNOS5250,
+};
+
+/* Exynos implementation specific driver private data */
+struct dw_mci_exynos_priv_data {
+       enum dw_mci_exynos_type         ctrl_type;
+       u8                              ciu_div;
+       u32                             sdr_timing;
+       u32                             ddr_timing;
+};
+
+static struct dw_mci_exynos_compatible {
+       char                            *compatible;
+       enum dw_mci_exynos_type         ctrl_type;
+} exynos_compat[] = {
+       {
+               .compatible     = "samsung,exynos4210-dw-mshc",
+               .ctrl_type      = DW_MCI_TYPE_EXYNOS4210,
+       }, {
+               .compatible     = "samsung,exynos4412-dw-mshc",
+               .ctrl_type      = DW_MCI_TYPE_EXYNOS4412,
+       }, {
+               .compatible     = "samsung,exynos5250-dw-mshc",
+               .ctrl_type      = DW_MCI_TYPE_EXYNOS5250,
+       },
+};
+
+static int dw_mci_exynos_priv_init(struct dw_mci *host)
+{
+       struct dw_mci_exynos_priv_data *priv;
+       int idx;
+
+       priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv) {
+               dev_err(host->dev, "mem alloc failed for private data\n");
+               return -ENOMEM;
+       }
+
+       for (idx = 0; idx < ARRAY_SIZE(exynos_compat); idx++) {
+               if (of_device_is_compatible(host->dev->of_node,
+                                       exynos_compat[idx].compatible))
+                       priv->ctrl_type = exynos_compat[idx].ctrl_type;
+       }
+
+       host->priv = priv;
+       return 0;
+}
+
+static int dw_mci_exynos_setup_clock(struct dw_mci *host)
+{
+       struct dw_mci_exynos_priv_data *priv = host->priv;
+
+       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5250)
+               host->bus_hz /= (priv->ciu_div + 1);
+       else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412)
+               host->bus_hz /= EXYNOS4412_FIXED_CIU_CLK_DIV;
+       else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210)
+               host->bus_hz /= EXYNOS4210_FIXED_CIU_CLK_DIV;
+
+       return 0;
+}
+
+static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr)
+{
+       /*
+        * Exynos4412 and Exynos5250 extends the use of CMD register with the
+        * use of bit 29 (which is reserved on standard MSHC controllers) for
+        * optionally bypassing the HOLD register for command and data. The
+        * HOLD register should be bypassed in case there is no phase shift
+        * applied on CMD/DATA that is sent to the card.
+        */
+       if (SDMMC_CLKSEL_GET_DRV_WD3(mci_readl(host, CLKSEL)))
+               *cmdr |= SDMMC_CMD_USE_HOLD_REG;
+}
+
+static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+       struct dw_mci_exynos_priv_data *priv = host->priv;
+
+       if (ios->timing == MMC_TIMING_UHS_DDR50)
+               mci_writel(host, CLKSEL, priv->ddr_timing);
+       else
+               mci_writel(host, CLKSEL, priv->sdr_timing);
+}
+
+static int dw_mci_exynos_parse_dt(struct dw_mci *host)
+{
+       struct dw_mci_exynos_priv_data *priv = host->priv;
+       struct device_node *np = host->dev->of_node;
+       u32 timing[2];
+       u32 div = 0;
+       int ret;
+
+       of_property_read_u32(np, "samsung,dw-mshc-ciu-div", &div);
+       priv->ciu_div = div;
+
+       ret = of_property_read_u32_array(np,
+                       "samsung,dw-mshc-sdr-timing", timing, 2);
+       if (ret)
+               return ret;
+
+       priv->sdr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div);
+
+       ret = of_property_read_u32_array(np,
+                       "samsung,dw-mshc-ddr-timing", timing, 2);
+       if (ret)
+               return ret;
+
+       priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div);
+       return 0;
+}
+
+static int dw_mci_exynos_setup_bus(struct dw_mci *host,
+                               struct device_node *slot_np, u8 bus_width)
+{
+       int idx, gpio, ret;
+
+       if (!slot_np)
+               return -EINVAL;
+
+       /* cmd + clock + bus-width pins */
+       for (idx = 0; idx < NUM_PINS(bus_width); idx++) {
+               gpio = of_get_gpio(slot_np, idx);
+               if (!gpio_is_valid(gpio)) {
+                       dev_err(host->dev, "invalid gpio: %d\n", gpio);
+                       return -EINVAL;
+               }
+
+               ret = devm_gpio_request(host->dev, gpio, "dw-mci-bus");
+               if (ret) {
+                       dev_err(host->dev, "gpio [%d] request failed\n", gpio);
+                       return -EBUSY;
+               }
+       }
+
+       gpio = of_get_named_gpio(slot_np, "wp-gpios", 0);
+       if (gpio_is_valid(gpio)) {
+               if (devm_gpio_request(host->dev, gpio, "dw-mci-wp"))
+                       dev_info(host->dev, "gpio [%d] request failed\n",
+                                               gpio);
+       } else {
+               dev_info(host->dev, "wp gpio not available");
+               host->pdata->quirks |= DW_MCI_QUIRK_NO_WRITE_PROTECT;
+       }
+
+       if (host->pdata->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
+               return 0;
+
+       gpio = of_get_named_gpio(slot_np, "samsung,cd-pinmux-gpio", 0);
+       if (gpio_is_valid(gpio)) {
+               if (devm_gpio_request(host->dev, gpio, "dw-mci-cd"))
+                       dev_err(host->dev, "gpio [%d] request failed\n", gpio);
+       } else {
+               dev_info(host->dev, "cd gpio not available");
+       }
+
+       return 0;
+}
+
+/* Exynos5250 controller specific capabilities */
+static unsigned long exynos5250_dwmmc_caps[4] = {
+       MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR |
+               MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23,
+       MMC_CAP_CMD23,
+       MMC_CAP_CMD23,
+       MMC_CAP_CMD23,
+};
+
+static struct dw_mci_drv_data exynos5250_drv_data = {
+       .caps                   = exynos5250_dwmmc_caps,
+       .init                   = dw_mci_exynos_priv_init,
+       .setup_clock            = dw_mci_exynos_setup_clock,
+       .prepare_command        = dw_mci_exynos_prepare_command,
+       .set_ios                = dw_mci_exynos_set_ios,
+       .parse_dt               = dw_mci_exynos_parse_dt,
+       .setup_bus              = dw_mci_exynos_setup_bus,
+};
+
+static const struct of_device_id dw_mci_exynos_match[] = {
+       { .compatible = "samsung,exynos5250-dw-mshc",
+                       .data = (void *)&exynos5250_drv_data, },
+       {},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
+
+int dw_mci_exynos_probe(struct platform_device *pdev)
+{
+       struct dw_mci_drv_data *drv_data;
+       const struct of_device_id *match;
+
+       match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node);
+       drv_data = match->data;
+       return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+static struct platform_driver dw_mci_exynos_pltfm_driver = {
+       .probe          = dw_mci_exynos_probe,
+       .remove         = __exit_p(dw_mci_pltfm_remove),
+       .driver         = {
+               .name           = "dwmmc_exynos",
+               .of_match_table = of_match_ptr(dw_mci_exynos_match),
+               .pm             = &dw_mci_pltfm_pmops,
+       },
+};
+
+module_platform_driver(dw_mci_exynos_pltfm_driver);
+
+MODULE_DESCRIPTION("Samsung Specific DW-MSHC Driver Extension");
+MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dwmmc-exynos");
index dc0d25a013e043f40536a125a63420cfe923595d..edb37e9135ae3741b5bafef61633c2740e01f8f1 100644 (file)
@@ -59,7 +59,7 @@ static int __devinit dw_mci_pci_probe(struct pci_dev *pdev,
 
        host->irq = pdev->irq;
        host->irq_flags = IRQF_SHARED;
-       host->dev = pdev->dev;
+       host->dev = &pdev->dev;
        host->pdata = &pci_board_data;
 
        host->regs = pci_iomap(pdev, PCI_BAR_NO, COMPLETE_BAR);
@@ -140,18 +140,7 @@ static struct pci_driver dw_mci_pci_driver = {
        },
 };
 
-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_pci_driver(dw_mci_pci_driver);
 
 MODULE_DESCRIPTION("DW Multimedia Card PCI Interface driver");
 MODULE_AUTHOR("Shashidhar Hiremath <shashidharh@vayavyalabs.com>");
index 92ec3eb3aae767bece2b75da7fc272f7982cd730..c960ca7ffbe694fa367ff7ca88c83003b3da59a6 100644 (file)
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/dw_mmc.h>
+#include <linux/of.h>
+
 #include "dw_mmc.h"
 
-static int dw_mci_pltfm_probe(struct platform_device *pdev)
+int dw_mci_pltfm_register(struct platform_device *pdev,
+                               struct dw_mci_drv_data *drv_data)
 {
        struct dw_mci *host;
        struct resource *regs;
        int ret;
 
-       host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL);
+       host = devm_kzalloc(&pdev->dev, 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;
-       }
+       if (!regs)
+               return -ENXIO;
 
        host->irq = platform_get_irq(pdev, 0);
-       if (host->irq < 0) {
-               ret = host->irq;
-               goto err_free;
-       }
+       if (host->irq < 0)
+               return host->irq;
 
-       host->dev = pdev->dev;
+       host->drv_data = drv_data;
+       host->dev = &pdev->dev;
        host->irq_flags = 0;
        host->pdata = pdev->dev.platform_data;
-       ret = -ENOMEM;
-       host->regs = ioremap(regs->start, resource_size(regs));
+       host->regs = devm_request_and_ioremap(&pdev->dev, regs);
        if (!host->regs)
-               goto err_free;
+               return -ENOMEM;
+
+       if (host->drv_data->init) {
+               ret = host->drv_data->init(host);
+               if (ret)
+                       return ret;
+       }
+
        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;
 }
+EXPORT_SYMBOL_GPL(dw_mci_pltfm_register);
 
-static int __exit dw_mci_pltfm_remove(struct platform_device *pdev)
+static int __devinit dw_mci_pltfm_probe(struct platform_device *pdev)
+{
+       return dw_mci_pltfm_register(pdev, NULL);
+}
+
+static int __devexit 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;
 }
+EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove);
 
 #ifdef CONFIG_PM_SLEEP
 /*
@@ -105,12 +109,20 @@ static int dw_mci_pltfm_resume(struct device *dev)
 #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);
+SIMPLE_DEV_PM_OPS(dw_mci_pltfm_pmops, dw_mci_pltfm_suspend, dw_mci_pltfm_resume);
+EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops);
+
+static const struct of_device_id dw_mci_pltfm_match[] = {
+       { .compatible = "snps,dw-mshc", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
 
 static struct platform_driver dw_mci_pltfm_driver = {
        .remove         = __exit_p(dw_mci_pltfm_remove),
        .driver         = {
                .name           = "dw_mmc",
+               .of_match_table = of_match_ptr(dw_mci_pltfm_match),
                .pm             = &dw_mci_pltfm_pmops,
        },
 };
diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h
new file mode 100644 (file)
index 0000000..301f245
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Synopsys DesignWare Multimedia Card Interface Platform driver
+ *
+ * Copyright (C) 2012, Samsung Electronics Co., 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.
+ */
+
+#ifndef _DW_MMC_PLTFM_H_
+#define _DW_MMC_PLTFM_H_
+
+extern int dw_mci_pltfm_register(struct platform_device *pdev,
+                               struct dw_mci_drv_data *drv_data);
+extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev);
+extern const struct dev_pm_ops dw_mci_pltfm_pmops;
+
+#endif /* _DW_MMC_PLTFM_H_ */
index af40d227bece22ecb51bb0862df913aadc3ce6da..c2828f35c3b8812b4de12cb0fd4b75c28fa09bbf 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/bitops.h>
 #include <linux/regulator/consumer.h>
 #include <linux/workqueue.h>
+#include <linux/of.h>
 
 #include "dw_mmc.h"
 
@@ -230,6 +231,7 @@ static void dw_mci_set_timeout(struct dw_mci *host)
 static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
 {
        struct mmc_data *data;
+       struct dw_mci_slot *slot = mmc_priv(mmc);
        u32 cmdr;
        cmd->error = -EINPROGRESS;
 
@@ -259,6 +261,9 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
                        cmdr |= SDMMC_CMD_DAT_WR;
        }
 
+       if (slot->host->drv_data->prepare_command)
+               slot->host->drv_data->prepare_command(slot->host, &cmdr);
+
        return cmdr;
 }
 
@@ -266,7 +271,7 @@ static void dw_mci_start_command(struct dw_mci *host,
                                 struct mmc_command *cmd, u32 cmd_flags)
 {
        host->cmd = cmd;
-       dev_vdbg(&host->dev,
+       dev_vdbg(host->dev,
                 "start command: ARGR=0x%08x CMDR=0x%08x\n",
                 cmd->arg, cmd_flags);
 
@@ -308,7 +313,7 @@ static void dw_mci_dma_cleanup(struct dw_mci *host)
 
        if (data)
                if (!data->host_cookie)
-                       dma_unmap_sg(&host->dev,
+                       dma_unmap_sg(host->dev,
                                     data->sg,
                                     data->sg_len,
                                     dw_mci_get_dma_dir(data));
@@ -334,7 +339,7 @@ static void dw_mci_idmac_complete_dma(struct dw_mci *host)
 {
        struct mmc_data *data = host->data;
 
-       dev_vdbg(&host->dev, "DMA complete\n");
+       dev_vdbg(host->dev, "DMA complete\n");
 
        host->dma_ops->cleanup(host);
 
@@ -405,23 +410,11 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
 static int dw_mci_idmac_init(struct dw_mci *host)
 {
        struct idmac_desc *p;
-       int i, dma_support;
+       int i;
 
        /* Number of descriptors in the ring buffer */
        host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
 
-       /* Check if Hardware Configuration Register has support for DMA */
-       dma_support = (mci_readl(host, HCON) >> 16) & 0x3;
-
-       if (!dma_support || dma_support > 2) {
-               dev_err(&host->dev,
-                       "Host Controller does not support IDMA Tx.\n");
-               host->dma_ops = NULL;
-               return -ENODEV;
-       }
-
-       dev_info(&host->dev, "Using internal DMA controller.\n");
-
        /* Forward link the descriptor list */
        for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
                p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1));
@@ -476,7 +469,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host,
                        return -EINVAL;
        }
 
-       sg_len = dma_map_sg(&host->dev,
+       sg_len = dma_map_sg(host->dev,
                            data->sg,
                            data->sg_len,
                            dw_mci_get_dma_dir(data));
@@ -519,7 +512,7 @@ static void dw_mci_post_req(struct mmc_host *mmc,
                return;
 
        if (data->host_cookie)
-               dma_unmap_sg(&slot->host->dev,
+               dma_unmap_sg(slot->host->dev,
                             data->sg,
                             data->sg_len,
                             dw_mci_get_dma_dir(data));
@@ -545,7 +538,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
 
        host->using_dma = 1;
 
-       dev_vdbg(&host->dev,
+       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);
@@ -814,6 +807,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                slot->clock = ios->clock;
        }
 
+       if (slot->host->drv_data->set_ios)
+               slot->host->drv_data->set_ios(slot->host, ios);
+
        switch (ios->power_mode) {
        case MMC_POWER_UP:
                set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags);
@@ -830,7 +826,9 @@ static int dw_mci_get_ro(struct mmc_host *mmc)
        struct dw_mci_board *brd = slot->host->pdata;
 
        /* Use platform get_ro function, else try on board write protect */
-       if (brd->get_ro)
+       if (brd->quirks & DW_MCI_QUIRK_NO_WRITE_PROTECT)
+               read_only = 0;
+       else if (brd->get_ro)
                read_only = brd->get_ro(slot->id);
        else
                read_only =
@@ -939,12 +937,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->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->dev, "list empty\n");
+               dev_vdbg(host->dev, "list empty\n");
                host->state = STATE_IDLE;
        }
 
@@ -1083,7 +1081,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
                                        data->bytes_xfered = 0;
                                        data->error = -ETIMEDOUT;
                                } else {
-                                       dev_err(&host->dev,
+                                       dev_err(host->dev,
                                                "data FIFO error "
                                                "(status=%08x)\n",
                                                status);
@@ -1767,12 +1765,60 @@ static void dw_mci_work_routine_card(struct work_struct *work)
        }
 }
 
-static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
+#ifdef CONFIG_OF
+/* given a slot id, find out the device node representing that slot */
+static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot)
+{
+       struct device_node *np;
+       const __be32 *addr;
+       int len;
+
+       if (!dev || !dev->of_node)
+               return NULL;
+
+       for_each_child_of_node(dev->of_node, np) {
+               addr = of_get_property(np, "reg", &len);
+               if (!addr || (len < sizeof(int)))
+                       continue;
+               if (be32_to_cpup(addr) == slot)
+                       return np;
+       }
+       return NULL;
+}
+
+/* find out bus-width for a given slot */
+static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
+{
+       struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
+       u32 bus_wd = 1;
+
+       if (!np)
+               return 1;
+
+       if (of_property_read_u32(np, "bus-width", &bus_wd))
+               dev_err(dev, "bus-width property not found, assuming width"
+                              " as 1\n");
+       return bus_wd;
+}
+#else /* CONFIG_OF */
+static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
+{
+       return 1;
+}
+static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot)
+{
+       return NULL;
+}
+#endif /* CONFIG_OF */
+
+static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 {
        struct mmc_host *mmc;
        struct dw_mci_slot *slot;
+       int ctrl_id, ret;
+       u8 bus_width;
 
-       mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), &host->dev);
+       mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev);
        if (!mmc)
                return -ENOMEM;
 
@@ -1780,6 +1826,7 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        slot->id = id;
        slot->mmc = mmc;
        slot->host = host;
+       host->slot[id] = slot;
 
        mmc->ops = &dw_mci_ops;
        mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510);
@@ -1800,21 +1847,44 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        if (host->pdata->caps)
                mmc->caps = host->pdata->caps;
 
+       if (host->dev->of_node) {
+               ctrl_id = of_alias_get_id(host->dev->of_node, "mshc");
+               if (ctrl_id < 0)
+                       ctrl_id = 0;
+       } else {
+               ctrl_id = to_platform_device(host->dev)->id;
+       }
+       if (host->drv_data && host->drv_data->caps)
+               mmc->caps |= host->drv_data->caps[ctrl_id];
+
        if (host->pdata->caps2)
                mmc->caps2 = host->pdata->caps2;
 
        if (host->pdata->get_bus_wd)
-               if (host->pdata->get_bus_wd(slot->id) >= 4)
-                       mmc->caps |= MMC_CAP_4_BIT_DATA;
+               bus_width = host->pdata->get_bus_wd(slot->id);
+       else if (host->dev->of_node)
+               bus_width = dw_mci_of_get_bus_wd(host->dev, slot->id);
+       else
+               bus_width = 1;
+
+       if (host->drv_data->setup_bus) {
+               struct device_node *slot_np;
+               slot_np = dw_mci_of_find_slot_node(host->dev, slot->id);
+               ret = host->drv_data->setup_bus(host, slot_np, bus_width);
+               if (ret)
+                       goto err_setup_bus;
+       }
+
+       switch (bus_width) {
+       case 8:
+               mmc->caps |= MMC_CAP_8_BIT_DATA;
+       case 4:
+               mmc->caps |= MMC_CAP_4_BIT_DATA;
+       }
 
        if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED)
                mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
 
-       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;
@@ -1850,7 +1920,6 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        else
                clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 
-       host->slot[id] = slot;
        mmc_add_host(mmc);
 
 #if defined(CONFIG_DEBUG_FS)
@@ -1867,6 +1936,10 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        queue_work(host->card_workqueue, &host->card_work);
 
        return 0;
+
+err_setup_bus:
+       mmc_free_host(mmc);
+       return -EINVAL;
 }
 
 static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
@@ -1884,10 +1957,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->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->dev, "%s: could not alloc DMA memory\n",
+               dev_err(host->dev, "%s: could not alloc DMA memory\n",
                        __func__);
                goto no_dma;
        }
@@ -1895,6 +1968,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->dev, "Using internal DMA controller.\n");
 #endif
 
        if (!host->dma_ops)
@@ -1903,12 +1977,12 @@ static void dw_mci_init_dma(struct dw_mci *host)
        if (host->dma_ops->init && host->dma_ops->start &&
            host->dma_ops->stop && host->dma_ops->cleanup) {
                if (host->dma_ops->init(host)) {
-                       dev_err(&host->dev, "%s: Unable to initialize "
+                       dev_err(host->dev, "%s: Unable to initialize "
                                "DMA Controller.\n", __func__);
                        goto no_dma;
                }
        } else {
-               dev_err(&host->dev, "DMA initialization not found.\n");
+               dev_err(host->dev, "DMA initialization not found.\n");
                goto no_dma;
        }
 
@@ -1916,7 +1990,7 @@ static void dw_mci_init_dma(struct dw_mci *host)
        return;
 
 no_dma:
-       dev_info(&host->dev, "Using PIO mode.\n");
+       dev_info(host->dev, "Using PIO mode.\n");
        host->use_dma = 0;
        return;
 }
@@ -1942,30 +2016,133 @@ static bool mci_wait_reset(struct device *dev, struct dw_mci *host)
        return false;
 }
 
+#ifdef CONFIG_OF
+static struct dw_mci_of_quirks {
+       char *quirk;
+       int id;
+} of_quirks[] = {
+       {
+               .quirk  = "supports-highspeed",
+               .id     = DW_MCI_QUIRK_HIGHSPEED,
+       }, {
+               .quirk  = "broken-cd",
+               .id     = DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
+       },
+};
+
+static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
+{
+       struct dw_mci_board *pdata;
+       struct device *dev = host->dev;
+       struct device_node *np = dev->of_node;
+       int idx, ret;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               dev_err(dev, "could not allocate memory for pdata\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       /* find out number of slots supported */
+       if (of_property_read_u32(dev->of_node, "num-slots",
+                               &pdata->num_slots)) {
+               dev_info(dev, "num-slots property not found, "
+                               "assuming 1 slot is available\n");
+               pdata->num_slots = 1;
+       }
+
+       /* get quirks */
+       for (idx = 0; idx < ARRAY_SIZE(of_quirks); idx++)
+               if (of_get_property(np, of_quirks[idx].quirk, NULL))
+                       pdata->quirks |= of_quirks[idx].id;
+
+       if (of_property_read_u32(np, "fifo-depth", &pdata->fifo_depth))
+               dev_info(dev, "fifo-depth property not found, using "
+                               "value of FIFOTH register as default\n");
+
+       of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms);
+
+       if (host->drv_data->parse_dt) {
+               ret = host->drv_data->parse_dt(host);
+               if (ret)
+                       return ERR_PTR(ret);
+       }
+
+       return pdata;
+}
+
+#else /* CONFIG_OF */
+static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
+{
+       return ERR_PTR(-EINVAL);
+}
+#endif /* CONFIG_OF */
+
 int dw_mci_probe(struct dw_mci *host)
 {
        int width, i, ret = 0;
        u32 fifo_size;
+       int init_slots = 0;
 
-       if (!host->pdata || !host->pdata->init) {
-               dev_err(&host->dev,
-                       "Platform data must supply init function\n");
-               return -ENODEV;
+       if (!host->pdata) {
+               host->pdata = dw_mci_parse_dt(host);
+               if (IS_ERR(host->pdata)) {
+                       dev_err(host->dev, "platform data not available\n");
+                       return -EINVAL;
+               }
        }
 
        if (!host->pdata->select_slot && host->pdata->num_slots > 1) {
-               dev_err(&host->dev,
+               dev_err(host->dev,
                        "Platform data must supply select_slot function\n");
                return -ENODEV;
        }
 
-       if (!host->pdata->bus_hz) {
-               dev_err(&host->dev,
+       host->biu_clk = clk_get(host->dev, "biu");
+       if (IS_ERR(host->biu_clk)) {
+               dev_dbg(host->dev, "biu clock not available\n");
+       } else {
+               ret = clk_prepare_enable(host->biu_clk);
+               if (ret) {
+                       dev_err(host->dev, "failed to enable biu clock\n");
+                       clk_put(host->biu_clk);
+                       return ret;
+               }
+       }
+
+       host->ciu_clk = clk_get(host->dev, "ciu");
+       if (IS_ERR(host->ciu_clk)) {
+               dev_dbg(host->dev, "ciu clock not available\n");
+       } else {
+               ret = clk_prepare_enable(host->ciu_clk);
+               if (ret) {
+                       dev_err(host->dev, "failed to enable ciu clock\n");
+                       clk_put(host->ciu_clk);
+                       goto err_clk_biu;
+               }
+       }
+
+       if (IS_ERR(host->ciu_clk))
+               host->bus_hz = host->pdata->bus_hz;
+       else
+               host->bus_hz = clk_get_rate(host->ciu_clk);
+
+       if (host->drv_data->setup_clock) {
+               ret = host->drv_data->setup_clock(host);
+               if (ret) {
+                       dev_err(host->dev,
+                               "implementation specific clock setup failed\n");
+                       goto err_clk_ciu;
+               }
+       }
+
+       if (!host->bus_hz) {
+               dev_err(host->dev,
                        "Platform data must supply bus speed\n");
-               return -ENODEV;
+               ret = -ENODEV;
+               goto err_clk_ciu;
        }
 
-       host->bus_hz = host->pdata->bus_hz;
        host->quirks = host->pdata->quirks;
 
        spin_lock_init(&host->lock);
@@ -1998,7 +2175,7 @@ int dw_mci_probe(struct dw_mci *host)
        }
 
        /* Reset all blocks */
-       if (!mci_wait_reset(&host->dev, host))
+       if (!mci_wait_reset(host->dev, host))
                return -ENODEV;
 
        host->dma_ops = host->pdata->dma_ops;
@@ -2054,10 +2231,18 @@ int dw_mci_probe(struct dw_mci *host)
        /* We need at least one slot to succeed */
        for (i = 0; i < host->num_slots; i++) {
                ret = dw_mci_init_slot(host, i);
-               if (ret) {
-                       ret = -ENODEV;
-                       goto err_init_slot;
-               }
+               if (ret)
+                       dev_dbg(host->dev, "slot %d init failed\n", i);
+               else
+                       init_slots++;
+       }
+
+       if (init_slots) {
+               dev_info(host->dev, "%d slots initialized\n", init_slots);
+       } else {
+               dev_dbg(host->dev, "attempted to initialize %d slots, "
+                                       "but failed on all\n", host->num_slots);
+               goto err_init_slot;
        }
 
        /*
@@ -2065,7 +2250,7 @@ int dw_mci_probe(struct dw_mci *host)
         * Need to check the version-id and set data-offset for DATA register.
         */
        host->verid = SDMMC_GET_VERID(mci_readl(host, VERID));
-       dev_info(&host->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;
@@ -2082,22 +2267,16 @@ int dw_mci_probe(struct dw_mci *host)
                   DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
        mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
 
-       dev_info(&host->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",
                 host->irq, width, fifo_size);
        if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
-               dev_info(&host->dev, "Internal DMAC interrupt fix enabled.\n");
+               dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n");
 
        return 0;
 
 err_init_slot:
-       /* De-init any initialized slots */
-       while (i > 0) {
-               if (host->slot[i])
-                       dw_mci_cleanup_slot(host->slot[i], i);
-               i--;
-       }
        free_irq(host->irq, host);
 
 err_workqueue:
@@ -2106,13 +2285,24 @@ err_workqueue:
 err_dmaunmap:
        if (host->use_dma && host->dma_ops->exit)
                host->dma_ops->exit(host);
-       dma_free_coherent(&host->dev, PAGE_SIZE,
+       dma_free_coherent(host->dev, PAGE_SIZE,
                          host->sg_cpu, host->sg_dma);
 
        if (host->vmmc) {
                regulator_disable(host->vmmc);
                regulator_put(host->vmmc);
        }
+
+err_clk_ciu:
+       if (!IS_ERR(host->ciu_clk)) {
+               clk_disable_unprepare(host->ciu_clk);
+               clk_put(host->ciu_clk);
+       }
+err_clk_biu:
+       if (!IS_ERR(host->biu_clk)) {
+               clk_disable_unprepare(host->biu_clk);
+               clk_put(host->biu_clk);
+       }
        return ret;
 }
 EXPORT_SYMBOL(dw_mci_probe);
@@ -2125,7 +2315,7 @@ void dw_mci_remove(struct dw_mci *host)
        mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */
 
        for (i = 0; i < host->num_slots; i++) {
-               dev_dbg(&host->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);
        }
@@ -2136,7 +2326,7 @@ void dw_mci_remove(struct dw_mci *host)
 
        free_irq(host->irq, host);
        destroy_workqueue(host->card_workqueue);
-       dma_free_coherent(&host->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);
@@ -2146,6 +2336,12 @@ void dw_mci_remove(struct dw_mci *host)
                regulator_put(host->vmmc);
        }
 
+       if (!IS_ERR(host->ciu_clk))
+               clk_disable_unprepare(host->ciu_clk);
+       if (!IS_ERR(host->biu_clk))
+               clk_disable_unprepare(host->biu_clk);
+       clk_put(host->ciu_clk);
+       clk_put(host->biu_clk);
 }
 EXPORT_SYMBOL(dw_mci_remove);
 
@@ -2188,7 +2384,7 @@ int dw_mci_resume(struct dw_mci *host)
        if (host->vmmc)
                regulator_enable(host->vmmc);
 
-       if (!mci_wait_reset(&host->dev, host)) {
+       if (!mci_wait_reset(host->dev, host)) {
                ret = -ENODEV;
                return ret;
        }
index 15c27e17c23fad303e83368a6d2f8fac93ae9fe2..53b8fd987e47ba09721980fe4773db4b3cedcc0b 100644 (file)
@@ -182,4 +182,28 @@ extern int dw_mci_suspend(struct dw_mci *host);
 extern int dw_mci_resume(struct dw_mci *host);
 #endif
 
+/**
+ * dw_mci driver data - dw-mshc implementation specific driver data.
+ * @caps: mmc subsystem specified capabilities of the controller(s).
+ * @init: early implementation specific initialization.
+ * @setup_clock: implementation specific clock configuration.
+ * @prepare_command: handle CMD register extensions.
+ * @set_ios: handle bus specific extensions.
+ * @parse_dt: parse implementation specific device tree properties.
+ * @setup_bus: initialize io-interface
+ *
+ * Provide controller implementation specific extensions. The usage of this
+ * data structure is fully optional and usage of each member in this structure
+ * is optional as well.
+ */
+struct dw_mci_drv_data {
+       unsigned long   *caps;
+       int             (*init)(struct dw_mci *host);
+       int             (*setup_clock)(struct dw_mci *host);
+       void            (*prepare_command)(struct dw_mci *host, u32 *cmdr);
+       void            (*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
+       int             (*parse_dt)(struct dw_mci *host);
+       int             (*setup_bus)(struct dw_mci *host,
+                               struct device_node *slot_np, u8 bus_width);
+};
 #endif /* _DW_MMC_H_ */
index 273306c68d58e916d8a588fffb8fd73385c405f2..a600eabbd6c30671a4b3d318974dc9f8af728590 100644 (file)
@@ -1532,20 +1532,7 @@ static struct spi_driver mmc_spi_driver = {
        .remove =       __devexit_p(mmc_spi_remove),
 };
 
-
-static int __init mmc_spi_init(void)
-{
-       return spi_register_driver(&mmc_spi_driver);
-}
-module_init(mmc_spi_init);
-
-
-static void __exit mmc_spi_exit(void)
-{
-       spi_unregister_driver(&mmc_spi_driver);
-}
-module_exit(mmc_spi_exit);
-
+module_spi_driver(mmc_spi_driver);
 
 MODULE_AUTHOR("Mike Lavender, David Brownell, "
                "Hans-Peter Nilsson, Jan Nikitenko");
index 50ff19a6236829b3143174b1372e141b86fb58fa..edc3e9baf0e7bea7be23841c11692968ad2a344b 100644 (file)
@@ -1309,14 +1309,10 @@ static int __devinit mmci_probe(struct amba_device *dev,
                goto host_free;
        }
 
-       ret = clk_prepare(host->clk);
+       ret = clk_prepare_enable(host->clk);
        if (ret)
                goto clk_free;
 
-       ret = clk_enable(host->clk);
-       if (ret)
-               goto clk_unprep;
-
        host->plat = plat;
        host->variant = variant;
        host->mclk = clk_get_rate(host->clk);
@@ -1515,9 +1511,7 @@ static int __devinit mmci_probe(struct amba_device *dev,
  err_gpio_cd:
        iounmap(host->base);
  clk_disable:
-       clk_disable(host->clk);
- clk_unprep:
-       clk_unprepare(host->clk);
+       clk_disable_unprepare(host->clk);
  clk_free:
        clk_put(host->clk);
  host_free:
@@ -1564,8 +1558,7 @@ static int __devexit mmci_remove(struct amba_device *dev)
                        gpio_free(host->gpio_cd);
 
                iounmap(host->base);
-               clk_disable(host->clk);
-               clk_unprepare(host->clk);
+               clk_disable_unprepare(host->clk);
                clk_put(host->clk);
 
                if (host->vcc)
index 7b1161de01d60b0b68e26f2b7e6d9e41f79de82e..565c2e4fac75cecd8890ec2d9885ffb50cc23060 100644 (file)
@@ -44,6 +44,7 @@
 #include <mach/hardware.h>
 
 #define DRIVER_NAME "mxc-mmc"
+#define MXCMCI_TIMEOUT_MS 10000
 
 #define MMC_REG_STR_STP_CLK            0x00
 #define MMC_REG_STATUS                 0x04
@@ -150,6 +151,8 @@ struct mxcmci_host {
        int                     dmareq;
        struct dma_slave_config dma_slave_config;
        struct imx_dma_data     dma_data;
+
+       struct timer_list       watchdog;
 };
 
 static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
@@ -271,9 +274,32 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
        dmaengine_submit(host->desc);
        dma_async_issue_pending(host->dma);
 
+       mod_timer(&host->watchdog, jiffies + msecs_to_jiffies(MXCMCI_TIMEOUT_MS));
+
        return 0;
 }
 
+static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat);
+static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat);
+
+static void mxcmci_dma_callback(void *data)
+{
+       struct mxcmci_host *host = data;
+       u32 stat;
+
+       del_timer(&host->watchdog);
+
+       stat = readl(host->base + MMC_REG_STATUS);
+       writel(stat & ~STATUS_DATA_TRANS_DONE, host->base + MMC_REG_STATUS);
+
+       dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat);
+
+       if (stat & STATUS_READ_OP_DONE)
+               writel(STATUS_READ_OP_DONE, host->base + MMC_REG_STATUS);
+
+       mxcmci_data_done(host, stat);
+}
+
 static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
                unsigned int cmdat)
 {
@@ -305,8 +331,14 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
 
        int_cntr = INT_END_CMD_RES_EN;
 
-       if (mxcmci_use_dma(host))
-               int_cntr |= INT_READ_OP_EN | INT_WRITE_OP_DONE_EN;
+       if (mxcmci_use_dma(host)) {
+               if (host->dma_dir == DMA_FROM_DEVICE) {
+                       host->desc->callback = mxcmci_dma_callback;
+                       host->desc->callback_param = host;
+               } else {
+                       int_cntr |= INT_WRITE_OP_DONE_EN;
+               }
+       }
 
        spin_lock_irqsave(&host->lock, flags);
        if (host->use_sdio)
@@ -345,11 +377,9 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat)
        struct mmc_data *data = host->data;
        int data_error;
 
-       if (mxcmci_use_dma(host)) {
-               dmaengine_terminate_all(host->dma);
+       if (mxcmci_use_dma(host))
                dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
                                host->dma_dir);
-       }
 
        if (stat & STATUS_ERR_MASK) {
                dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",
@@ -624,8 +654,10 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
                mxcmci_cmd_done(host, stat);
 
        if (mxcmci_use_dma(host) &&
-                 (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE)))
+                 (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) {
+               del_timer(&host->watchdog);
                mxcmci_data_done(host, stat);
+       }
 
        if (host->default_irq_mask &&
                  (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL)))
@@ -836,6 +868,34 @@ static bool filter(struct dma_chan *chan, void *param)
        return true;
 }
 
+static void mxcmci_watchdog(unsigned long data)
+{
+       struct mmc_host *mmc = (struct mmc_host *)data;
+       struct mxcmci_host *host = mmc_priv(mmc);
+       struct mmc_request *req = host->req;
+       unsigned int stat = readl(host->base + MMC_REG_STATUS);
+
+       if (host->dma_dir == DMA_FROM_DEVICE) {
+               dmaengine_terminate_all(host->dma);
+               dev_err(mmc_dev(host->mmc),
+                       "%s: read time out (status = 0x%08x)\n",
+                       __func__, stat);
+       } else {
+               dev_err(mmc_dev(host->mmc),
+                       "%s: write time out (status = 0x%08x)\n",
+                       __func__, stat);
+               mxcmci_softreset(host);
+       }
+
+       /* Mark transfer as erroneus and inform the upper layers */
+
+       host->data->error = -ETIMEDOUT;
+       host->req = NULL;
+       host->cmd = NULL;
+       host->data = NULL;
+       mmc_request_done(host->mmc, req);
+}
+
 static const struct mmc_host_ops mxcmci_ops = {
        .request                = mxcmci_request,
        .set_ios                = mxcmci_set_ios,
@@ -968,6 +1028,10 @@ static int mxcmci_probe(struct platform_device *pdev)
 
        mmc_add_host(mmc);
 
+       init_timer(&host->watchdog);
+       host->watchdog.function = &mxcmci_watchdog;
+       host->watchdog.data = (unsigned long)mmc;
+
        return 0;
 
 out_free_irq:
index bb4c2bf04d094f60cbbffc6a7be34e43effd38e0..80d1e6d4b0ae2272588b8860f91527d02358dbf4 100644 (file)
@@ -525,7 +525,7 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
                writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
                       ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
                writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
-                      host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET);
+                      ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_SET);
        } else {
                writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
                       ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
index c6259a8295441a8a6cc81fb8bd828dd052398570..48ad361613efb2ebaca728ac53f87a147e8beb45 100644 (file)
 #include <linux/mmc/card.h>
 #include <linux/clk.h>
 #include <linux/scatterlist.h>
-#include <linux/i2c/tps65010.h>
 #include <linux/slab.h>
 
-#include <asm/io.h>
-#include <asm/irq.h>
-
 #include <plat/mmc.h>
-#include <asm/gpio.h>
 #include <plat/dma.h>
-#include <plat/fpga.h>
 
 #define        OMAP_MMC_REG_CMD        0x00
 #define        OMAP_MMC_REG_ARGL       0x01
@@ -105,7 +99,6 @@ struct mmc_omap_slot {
        u16                     saved_con;
        u16                     bus_mode;
        unsigned int            fclk_freq;
-       unsigned                powered:1;
 
        struct tasklet_struct   cover_tasklet;
        struct timer_list       cover_timer;
@@ -137,7 +130,6 @@ struct mmc_omap_host {
        unsigned int            phys_base;
        int                     irq;
        unsigned char           bus_mode;
-       unsigned char           hw_bus_mode;
        unsigned int            reg_shift;
 
        struct work_struct      cmd_abort_work;
@@ -695,22 +687,29 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
        host->buffer += nwords;
 }
 
-static inline void mmc_omap_report_irq(u16 status)
+#ifdef CONFIG_MMC_DEBUG
+static void mmc_omap_report_irq(struct mmc_omap_host *host, u16 status)
 {
        static const char *mmc_omap_status_bits[] = {
                "EOC", "CD", "CB", "BRS", "EOFB", "DTO", "DCRC", "CTO",
                "CCRC", "CRW", "AF", "AE", "OCRB", "CIRQ", "CERR"
        };
-       int i, c = 0;
+       int i;
+       char res[64], *buf = res;
+
+       buf += sprintf(buf, "MMC IRQ 0x%x:", status);
 
        for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++)
-               if (status & (1 << i)) {
-                       if (c)
-                               printk(" ");
-                       printk("%s", mmc_omap_status_bits[i]);
-                       c++;
-               }
+               if (status & (1 << i))
+                       buf += sprintf(buf, " %s", mmc_omap_status_bits[i]);
+       dev_vdbg(mmc_dev(host->mmc), "%s\n", res);
 }
+#else
+static void mmc_omap_report_irq(struct mmc_omap_host *host, u16 status)
+{
+}
+#endif
+
 
 static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 {
@@ -744,12 +743,10 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                        cmd = host->cmd->opcode;
                else
                        cmd = -1;
-#ifdef CONFIG_MMC_DEBUG
                dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ",
                        status, cmd);
-               mmc_omap_report_irq(status);
-               printk("\n");
-#endif
+               mmc_omap_report_irq(host, status);
+
                if (host->total_bytes_left) {
                        if ((status & OMAP_MMC_STAT_A_FULL) ||
                            (status & OMAP_MMC_STAT_END_OF_DATA))
index 38adc330c00704024f3390fa185c3b1f401b61db..54bfd0cc106b92280cd75818310d81aa56c48ccb 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/mmc/core.h>
 #include <linux/mmc/mmc.h>
 #include <linux/io.h>
-#include <linux/semaphore.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
@@ -44,7 +43,6 @@
 #include <plat/cpu.h>
 
 /* OMAP HSMMC Host Controller Registers */
-#define OMAP_HSMMC_SYSCONFIG   0x0010
 #define OMAP_HSMMC_SYSSTATUS   0x0014
 #define OMAP_HSMMC_CON         0x002C
 #define OMAP_HSMMC_BLK         0x0104
@@ -161,8 +159,6 @@ struct omap_hsmmc_host {
        unsigned int            dma_sg_idx;
        unsigned char           bus_mode;
        unsigned char           power_mode;
-       u32                     *buffer;
-       u32                     bytesleft;
        int                     suspended;
        int                     irq;
        int                     use_dma, dma_ch;
@@ -171,7 +167,6 @@ struct omap_hsmmc_host {
        int                     slot_id;
        int                     response_busy;
        int                     context_loss;
-       int                     vdd;
        int                     protect_card;
        int                     reqs_blocked;
        int                     use_reg;
@@ -300,12 +295,12 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
        struct regulator *reg;
        int ocr_value = 0;
 
-       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");
+               return PTR_ERR(reg);
        } else {
+               mmc_slot(host).set_power = omap_hsmmc_set_power;
                host->vcc = reg;
                ocr_value = mmc_regulator_get_ocrmask(reg);
                if (!mmc_slot(host).ocr_mask) {
@@ -495,7 +490,7 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
        unsigned long regval;
        unsigned long timeout;
 
-       dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock);
+       dev_vdbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock);
 
        omap_hsmmc_stop_clock(host);
 
@@ -579,21 +574,8 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
        if (host->context_loss == context_loss)
                return 1;
 
-       /* Wait for hardware reset */
-       timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
-       while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE
-               && time_before(jiffies, timeout))
-               ;
-
-       /* Do software reset */
-       OMAP_HSMMC_WRITE(host->base, SYSCONFIG, SOFTRESET);
-       timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
-       while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE
-               && time_before(jiffies, timeout))
-               ;
-
-       OMAP_HSMMC_WRITE(host->base, SYSCONFIG,
-                       OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE);
+       if (!OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE)
+               return 1;
 
        if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) {
                if (host->power_mode != MMC_POWER_OFF &&
@@ -745,7 +727,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
 {
        int cmdreg = 0, resptype = 0, cmdtype = 0;
 
-       dev_dbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n",
+       dev_vdbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n",
                mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
        host->cmd = cmd;
 
@@ -934,7 +916,7 @@ static void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, u32 status)
                        buf += len;
                }
 
-       dev_dbg(mmc_dev(host->mmc), "%s\n", res);
+       dev_vdbg(mmc_dev(host->mmc), "%s\n", res);
 }
 #else
 static inline void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host,
@@ -981,72 +963,40 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
                        __func__);
 }
 
+static void hsmmc_command_incomplete(struct omap_hsmmc_host *host, int err)
+{
+       omap_hsmmc_reset_controller_fsm(host, SRC);
+       host->cmd->error = err;
+
+       if (host->data) {
+               omap_hsmmc_reset_controller_fsm(host, SRD);
+               omap_hsmmc_dma_cleanup(host, err);
+       }
+
+}
+
 static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
 {
        struct mmc_data *data;
        int end_cmd = 0, end_trans = 0;
 
-       if (!host->req_in_progress) {
-               do {
-                       OMAP_HSMMC_WRITE(host->base, STAT, status);
-                       /* Flush posted write */
-                       status = OMAP_HSMMC_READ(host->base, STAT);
-               } while (status & INT_EN_MASK);
-               return;
-       }
-
        data = host->data;
-       dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
+       dev_vdbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
 
        if (status & ERR) {
                omap_hsmmc_dbg_report_irq(host, status);
-               if ((status & CMD_TIMEOUT) ||
-                       (status & CMD_CRC)) {
-                       if (host->cmd) {
-                               if (status & CMD_TIMEOUT) {
-                                       omap_hsmmc_reset_controller_fsm(host,
-                                                                       SRC);
-                                       host->cmd->error = -ETIMEDOUT;
-                               } else {
-                                       host->cmd->error = -EILSEQ;
-                               }
-                               end_cmd = 1;
-                       }
-                       if (host->data || host->response_busy) {
-                               if (host->data)
-                                       omap_hsmmc_dma_cleanup(host,
-                                                               -ETIMEDOUT);
-                               host->response_busy = 0;
-                               omap_hsmmc_reset_controller_fsm(host, SRD);
-                       }
-               }
-               if ((status & DATA_TIMEOUT) ||
-                       (status & DATA_CRC)) {
-                       if (host->data || host->response_busy) {
-                               int err = (status & DATA_TIMEOUT) ?
-                                               -ETIMEDOUT : -EILSEQ;
-
-                               if (host->data)
-                                       omap_hsmmc_dma_cleanup(host, err);
-                               else
-                                       host->mrq->cmd->error = err;
-                               host->response_busy = 0;
-                               omap_hsmmc_reset_controller_fsm(host, SRD);
-                               end_trans = 1;
-                       }
-               }
-               if (status & CARD_ERR) {
-                       dev_dbg(mmc_dev(host->mmc),
-                               "Ignoring card err CMD%d\n", host->cmd->opcode);
-                       if (host->cmd)
-                               end_cmd = 1;
-                       if (host->data)
-                               end_trans = 1;
+               if (status & (CMD_TIMEOUT | DATA_TIMEOUT))
+                       hsmmc_command_incomplete(host, -ETIMEDOUT);
+               else if (status & (CMD_CRC | DATA_CRC))
+                       hsmmc_command_incomplete(host, -EILSEQ);
+
+               end_cmd = 1;
+               if (host->data || host->response_busy) {
+                       end_trans = 1;
+                       host->response_busy = 0;
                }
        }
 
-       OMAP_HSMMC_WRITE(host->base, STAT, status);
-
        if (end_cmd || ((status & CC) && host->cmd))
                omap_hsmmc_cmd_done(host, host->cmd);
        if ((end_trans || (status & TC)) && host->mrq)
@@ -1062,11 +1012,13 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
        int status;
 
        status = OMAP_HSMMC_READ(host->base, STAT);
-       do {
+       while (status & INT_EN_MASK && host->req_in_progress) {
                omap_hsmmc_do_irq(host, status);
+
                /* Flush posted write */
+               OMAP_HSMMC_WRITE(host->base, STAT, status);
                status = OMAP_HSMMC_READ(host->base, STAT);
-       } while (status & INT_EN_MASK);
+       }
 
        return IRQ_HANDLED;
 }
@@ -1501,12 +1453,10 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                case MMC_POWER_OFF:
                        mmc_slot(host).set_power(host->dev, host->slot_id,
                                                 0, 0);
-                       host->vdd = 0;
                        break;
                case MMC_POWER_UP:
                        mmc_slot(host).set_power(host->dev, host->slot_id,
                                                 1, ios->vdd);
-                       host->vdd = ios->vdd;
                        break;
                case MMC_POWER_ON:
                        do_send_init_stream = 1;
@@ -1598,10 +1548,6 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
        value = OMAP_HSMMC_READ(host->base, CAPA);
        OMAP_HSMMC_WRITE(host->base, CAPA, value | capa);
 
-       /* Set the controller to AUTO IDLE mode */
-       value = OMAP_HSMMC_READ(host->base, SYSCONFIG);
-       OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE);
-
        /* Set SD bus power bit */
        set_sd_bus_power(host);
 }
@@ -1659,8 +1605,6 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data)
 
        pm_runtime_get_sync(host->dev);
 
-       seq_printf(s, "SYSCONFIG:\t0x%08x\n",
-                       OMAP_HSMMC_READ(host->base, SYSCONFIG));
        seq_printf(s, "CON:\t\t0x%08x\n",
                        OMAP_HSMMC_READ(host->base, CON));
        seq_printf(s, "HCTL:\t\t0x%08x\n",
@@ -2105,8 +2049,7 @@ static int omap_hsmmc_suspend(struct device *dev)
        if (ret) {
                host->suspended = 0;
                if (host->pdata->resume) {
-                       ret = host->pdata->resume(dev, host->slot_id);
-                       if (ret)
+                       if (host->pdata->resume(dev, host->slot_id))
                                dev_dbg(dev, "Unmask interrupt failed\n");
                }
                goto err;
index ca3915dac03ddad90fe6d17314278754feac69b1..3f9d6d577a9194fba302faf817e11194f8eb0ce6 100644 (file)
@@ -30,6 +30,9 @@
 #include <linux/regulator/consumer.h>
 #include <linux/gpio.h>
 #include <linux/gfp.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
 
 #include <asm/sizes.h>
 
@@ -573,6 +576,50 @@ static irqreturn_t pxamci_detect_irq(int irq, void *devid)
        return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id pxa_mmc_dt_ids[] = {
+        { .compatible = "marvell,pxa-mmc" },
+        { }
+};
+
+MODULE_DEVICE_TABLE(of, pxa_mmc_dt_ids);
+
+static int __devinit pxamci_of_init(struct platform_device *pdev)
+{
+        struct device_node *np = pdev->dev.of_node;
+        struct pxamci_platform_data *pdata;
+        u32 tmp;
+
+        if (!np)
+                return 0;
+
+        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+        if (!pdata)
+                return -ENOMEM;
+
+       pdata->gpio_card_detect =
+               of_get_named_gpio(np, "cd-gpios", 0);
+       pdata->gpio_card_ro =
+               of_get_named_gpio(np, "wp-gpios", 0);
+
+       /* pxa-mmc specific */
+       pdata->gpio_power =
+               of_get_named_gpio(np, "pxa-mmc,gpio-power", 0);
+
+       if (of_property_read_u32(np, "pxa-mmc,detect-delay-ms", &tmp) == 0)
+               pdata->detect_delay_ms = tmp;
+
+        pdev->dev.platform_data = pdata;
+
+        return 0;
+}
+#else
+static int __devinit pxamci_of_init(struct platform_device *pdev)
+{
+        return 0;
+}
+#endif
+
 static int pxamci_probe(struct platform_device *pdev)
 {
        struct mmc_host *mmc;
@@ -580,6 +627,10 @@ static int pxamci_probe(struct platform_device *pdev)
        struct resource *r, *dmarx, *dmatx;
        int ret, irq, gpio_cd = -1, gpio_ro = -1, gpio_power = -1;
 
+       ret = pxamci_of_init(pdev);
+       if (ret)
+               return ret;
+
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq = platform_get_irq(pdev, 0);
        if (!r || irq < 0)
@@ -866,6 +917,7 @@ static struct platform_driver pxamci_driver = {
        .driver         = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(pxa_mmc_dt_ids),
 #ifdef CONFIG_PM
                .pm     = &pxamci_pm_ops,
 #endif
index a6e53a1ebb0888639a49d75c72f562f45b48e4f1..90140eb03e36a2766ffc40470271a0e63be34845 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/mmc/host.h>
+#include <linux/of.h>
 
 #include "sdhci-pltfm.h"
 
@@ -126,11 +127,18 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev)
        return sdhci_pltfm_unregister(pdev);
 }
 
+static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = {
+       { .compatible = "marvell,dove-sdhci", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, sdhci_dove_of_match_table);
+
 static struct platform_driver sdhci_dove_driver = {
        .driver         = {
                .name   = "sdhci-dove",
                .owner  = THIS_MODULE,
                .pm     = SDHCI_PLTFM_PMOPS,
+               .of_match_table = of_match_ptr(sdhci_dove_of_match_table),
        },
        .probe          = sdhci_dove_probe,
        .remove         = __devexit_p(sdhci_dove_remove),
index f8eb1fb0c9219283c9624f3f0a8adde251bcd5e9..ae5fcbfa1eef5986ec832616ed1ad350106e64ef 100644 (file)
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
 
+#define VENDOR_V_22    0x12
+static u32 esdhc_readl(struct sdhci_host *host, int reg)
+{
+       u32 ret;
+
+       ret = in_be32(host->ioaddr + reg);
+       /*
+        * The bit of ADMA flag in eSDHC is not compatible with standard
+        * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is
+        * supported by eSDHC.
+        * And for many FSL eSDHC controller, the reset value of field
+        * SDHCI_CAN_DO_ADMA1 is one, but some of them can't support ADMA,
+        * only these vendor version is greater than 2.2/0x12 support ADMA.
+        * For FSL eSDHC, must aligned 4-byte, so use 0xFC to read the
+        * the verdor version number, oxFE is SDHCI_HOST_VERSION.
+        */
+       if ((reg == SDHCI_CAPABILITIES) && (ret & SDHCI_CAN_DO_ADMA1)) {
+               u32 tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+               tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
+               if (tmp > VENDOR_V_22)
+                       ret |= SDHCI_CAN_DO_ADMA2;
+       }
+
+       return ret;
+}
+
 static u16 esdhc_readw(struct sdhci_host *host, int reg)
 {
        u16 ret;
@@ -144,7 +170,7 @@ static void esdhc_of_resume(struct sdhci_host *host)
 #endif
 
 static struct sdhci_ops sdhci_esdhc_ops = {
-       .read_l = sdhci_be32bs_readl,
+       .read_l = esdhc_readl,
        .read_w = esdhc_readw,
        .read_b = esdhc_readb,
        .write_l = sdhci_be32bs_writel,
@@ -161,9 +187,13 @@ static struct sdhci_ops sdhci_esdhc_ops = {
 };
 
 static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
-       /* card detection could be handled via GPIO */
+       /*
+        * card detection could be handled via GPIO
+        * eSDHC cannot support End Attribute in NOP ADMA descriptor
+        */
        .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
-               | SDHCI_QUIRK_NO_CARD_NO_RESET,
+               | SDHCI_QUIRK_NO_CARD_NO_RESET
+               | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
        .ops = &sdhci_esdhc_ops,
 };
 
index 9722d43d61407d85b45a64ae1cf9a05a7196d231..4bb74b042a06483cb3cea750dac26f56c4ab68cd 100644 (file)
@@ -1476,24 +1476,7 @@ static struct pci_driver sdhci_driver = {
        },
 };
 
-/*****************************************************************************\
- *                                                                           *
- * Driver init/exit                                                          *
- *                                                                           *
-\*****************************************************************************/
-
-static int __init sdhci_drv_init(void)
-{
-       return pci_register_driver(&sdhci_driver);
-}
-
-static void __exit sdhci_drv_exit(void)
-{
-       pci_unregister_driver(&sdhci_driver);
-}
-
-module_init(sdhci_drv_init);
-module_exit(sdhci_drv_exit);
+module_pci_driver(sdhci_driver);
 
 MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>");
 MODULE_DESCRIPTION("Secure Digital Host Controller Interface PCI driver");
index d9a4ef4f1ed0e8b65cc212ce44a014093f5bf8fd..65551a9709ccc86e893be96dfead3fe2919677e3 100644 (file)
@@ -75,6 +75,9 @@ void sdhci_get_of_property(struct platform_device *pdev)
                if (sdhci_of_wp_inverted(np))
                        host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
 
+               if (of_get_property(np, "broken-cd", NULL))
+                       host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+
                if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc"))
                        host->quirks |= SDHCI_QUIRK_BROKEN_DMA;
 
index b6ee8857e226fc163d53c1a66d52eda26121735d..8e63a9c04e3176fd9f8950caa2c461636b6cce47 100644 (file)
@@ -197,7 +197,7 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
                goto err_clk_get;
        }
        pltfm_host->clk = clk;
-       clk_enable(clk);
+       clk_prepare_enable(clk);
 
        host->quirks = SDHCI_QUIRK_BROKEN_ADMA
                | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
@@ -239,7 +239,7 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
        return 0;
 
 err_add_host:
-       clk_disable(clk);
+       clk_disable_unprepare(clk);
        clk_put(clk);
 err_clk_get:
        sdhci_pltfm_free(pdev);
@@ -255,7 +255,7 @@ static int __devexit sdhci_pxav2_remove(struct platform_device *pdev)
 
        sdhci_remove_host(host, 1);
 
-       clk_disable(pltfm_host->clk);
+       clk_disable_unprepare(pltfm_host->clk);
        clk_put(pltfm_host->clk);
        sdhci_pltfm_free(pdev);
        kfree(pxa);
index 07fe3834fe0b224119d0591672de48949dd18105..e918a2bb3af1aa99a0f51f97ce0c10f1bd33b3dd 100644 (file)
 #include <linux/gpio.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/slot-gpio.h>
 #include <linux/platform_data/pxa_sdhci.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
 
 #include "sdhci.h"
 #include "sdhci-pltfm.h"
@@ -182,6 +184,7 @@ static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
        struct device_node *np = dev->of_node;
        u32 bus_width;
        u32 clk_delay_cycles;
+       enum of_gpio_flags gpio_flags;
 
        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
@@ -198,6 +201,10 @@ static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
        if (clk_delay_cycles > 0)
                pdata->clk_delay_cycles = clk_delay_cycles;
 
+       pdata->ext_cd_gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, &gpio_flags);
+       if (gpio_flags != OF_GPIO_ACTIVE_LOW)
+               pdata->host_caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
+
        return pdata;
 }
 #else
@@ -231,14 +238,14 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
        pltfm_host = sdhci_priv(host);
        pltfm_host->priv = pxa;
 
-       clk = clk_get(dev, "PXA-SDHCLK");
+       clk = clk_get(dev, NULL);
        if (IS_ERR(clk)) {
                dev_err(dev, "failed to get io clock\n");
                ret = PTR_ERR(clk);
                goto err_clk_get;
        }
        pltfm_host->clk = clk;
-       clk_enable(clk);
+       clk_prepare_enable(clk);
 
        host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
                | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
@@ -266,12 +273,25 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
                        host->quirks |= pdata->quirks;
                if (pdata->host_caps)
                        host->mmc->caps |= pdata->host_caps;
+               if (pdata->host_caps2)
+                       host->mmc->caps2 |= pdata->host_caps2;
                if (pdata->pm_caps)
                        host->mmc->pm_caps |= pdata->pm_caps;
+
+               if (gpio_is_valid(pdata->ext_cd_gpio)) {
+                       ret = mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio);
+                       if (ret) {
+                               dev_err(mmc_dev(host->mmc),
+                                       "failed to allocate card detect gpio\n");
+                               goto err_cd_req;
+                       }
+               }
        }
 
        host->ops = &pxav3_sdhci_ops;
 
+       sdhci_get_of_property(pdev);
+
        ret = sdhci_add_host(host);
        if (ret) {
                dev_err(&pdev->dev, "failed to add host\n");
@@ -283,8 +303,10 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
        return 0;
 
 err_add_host:
-       clk_disable(clk);
+       clk_disable_unprepare(clk);
        clk_put(clk);
+       mmc_gpio_free_cd(host->mmc);
+err_cd_req:
 err_clk_get:
        sdhci_pltfm_free(pdev);
        kfree(pxa);
@@ -296,11 +318,16 @@ static int __devexit sdhci_pxav3_remove(struct platform_device *pdev)
        struct sdhci_host *host = platform_get_drvdata(pdev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct sdhci_pxa *pxa = pltfm_host->priv;
+       struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
 
        sdhci_remove_host(host, 1);
 
-       clk_disable(pltfm_host->clk);
+       clk_disable_unprepare(pltfm_host->clk);
        clk_put(pltfm_host->clk);
+
+       if (gpio_is_valid(pdata->ext_cd_gpio))
+               mmc_gpio_free_cd(host->mmc);
+
        sdhci_pltfm_free(pdev);
        kfree(pxa);
 
index a50c205ea2085f3266ee906b673d062e3a9aaf10..2903949594c6a1d3168d5a021c82ebec795ed138 100644 (file)
@@ -34,6 +34,9 @@
 
 #define MAX_BUS_CLK    (4)
 
+/* Number of gpio's used is max data bus width + command and clock lines */
+#define NUM_GPIOS(x)   (x + 2)
+
 /**
  * struct sdhci_s3c - S3C SDHCI instance
  * @host: The SDHCI host created
@@ -41,6 +44,7 @@
  * @ioarea: The resource created when we claimed the IO area.
  * @pdata: The platform data for this controller.
  * @cur_clk: The index of the current bus clock.
+ * @gpios: List of gpio numbers parsed from device tree.
  * @clk_io: The clock for the internal bus interface.
  * @clk_bus: The clocks that are available for the SD/MMC bus clock.
  */
@@ -52,6 +56,7 @@ struct sdhci_s3c {
        unsigned int            cur_clk;
        int                     ext_cd_irq;
        int                     ext_cd_gpio;
+       int                     *gpios;
 
        struct clk              *clk_io;
        struct clk              *clk_bus[MAX_BUS_CLK];
@@ -166,7 +171,7 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
        dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n",
                src, rate, wanted, rate / div);
 
-       return (wanted - (rate / div));
+       return wanted - (rate / div);
 }
 
 /**
@@ -203,10 +208,12 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
                 best_src, clock, best);
 
        /* select the new clock source */
-
        if (ourhost->cur_clk != best_src) {
                struct clk *clk = ourhost->clk_bus[best_src];
 
+               clk_enable(clk);
+               clk_disable(ourhost->clk_bus[ourhost->cur_clk]);
+
                /* turn clock off to card before changing clock source */
                writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
 
@@ -288,6 +295,7 @@ static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host)
 static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
 {
        struct sdhci_s3c *ourhost = to_s3c(host);
+       struct device *dev = &ourhost->pdev->dev;
        unsigned long timeout;
        u16 clk = 0;
 
@@ -309,8 +317,8 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
        while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
                & SDHCI_CLOCK_INT_STABLE)) {
                if (timeout == 0) {
-                       printk(KERN_ERR "%s: Internal clock never "
-                               "stabilised.\n", mmc_hostname(host->mmc));
+                       dev_err(dev, "%s: Internal clock never stabilised.\n",
+                               mmc_hostname(host->mmc));
                        return;
                }
                timeout--;
@@ -404,7 +412,9 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
                if (sc->ext_cd_irq &&
                    request_threaded_irq(sc->ext_cd_irq, NULL,
                                         sdhci_s3c_gpio_card_detect_thread,
-                                        IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                        IRQF_TRIGGER_RISING |
+                                        IRQF_TRIGGER_FALLING |
+                                        IRQF_ONESHOT,
                                         dev_name(dev), sc) == 0) {
                        int status = gpio_get_value(sc->ext_cd_gpio);
                        if (pdata->ext_cd_gpio_invert)
@@ -419,9 +429,121 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
        }
 }
 
+#ifdef CONFIG_OF
+static int __devinit sdhci_s3c_parse_dt(struct device *dev,
+               struct sdhci_host *host, struct s3c_sdhci_platdata *pdata)
+{
+       struct device_node *node = dev->of_node;
+       struct sdhci_s3c *ourhost = to_s3c(host);
+       u32 max_width;
+       int gpio, cnt, ret;
+
+       /* if the bus-width property is not specified, assume width as 1 */
+       if (of_property_read_u32(node, "bus-width", &max_width))
+               max_width = 1;
+       pdata->max_width = max_width;
+
+       ourhost->gpios = devm_kzalloc(dev, NUM_GPIOS(pdata->max_width) *
+                               sizeof(int), GFP_KERNEL);
+       if (!ourhost->gpios)
+               return -ENOMEM;
+
+       /* get the card detection method */
+       if (of_get_property(node, "broken-cd", 0)) {
+               pdata->cd_type = S3C_SDHCI_CD_NONE;
+               goto setup_bus;
+       }
+
+       if (of_get_property(node, "non-removable", 0)) {
+               pdata->cd_type = S3C_SDHCI_CD_PERMANENT;
+               goto setup_bus;
+       }
+
+       gpio = of_get_named_gpio(node, "cd-gpios", 0);
+       if (gpio_is_valid(gpio)) {
+               pdata->cd_type = S3C_SDHCI_CD_GPIO;
+               goto found_cd;
+       } else if (gpio != -ENOENT) {
+               dev_err(dev, "invalid card detect gpio specified\n");
+               return -EINVAL;
+       }
+
+       gpio = of_get_named_gpio(node, "samsung,cd-pinmux-gpio", 0);
+       if (gpio_is_valid(gpio)) {
+               pdata->cd_type = S3C_SDHCI_CD_INTERNAL;
+               goto found_cd;
+       } else if (gpio != -ENOENT) {
+               dev_err(dev, "invalid card detect gpio specified\n");
+               return -EINVAL;
+       }
+
+       dev_info(dev, "assuming no card detect line available\n");
+       pdata->cd_type = S3C_SDHCI_CD_NONE;
+
+ found_cd:
+       if (pdata->cd_type == S3C_SDHCI_CD_GPIO) {
+               pdata->ext_cd_gpio = gpio;
+               ourhost->ext_cd_gpio = -1;
+               if (of_get_property(node, "cd-inverted", NULL))
+                       pdata->ext_cd_gpio_invert = 1;
+       } else if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+               ret = gpio_request(gpio, "sdhci-cd");
+               if (ret) {
+                       dev_err(dev, "card detect gpio request failed\n");
+                       return -EINVAL;
+               }
+               ourhost->ext_cd_gpio = gpio;
+       }
+
+ setup_bus:
+       /* get the gpios for command, clock and data lines */
+       for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) {
+               gpio = of_get_gpio(node, cnt);
+               if (!gpio_is_valid(gpio)) {
+                       dev_err(dev, "invalid gpio[%d]\n", cnt);
+                       goto err_free_dt_cd_gpio;
+               }
+               ourhost->gpios[cnt] = gpio;
+       }
+
+       for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) {
+               ret = gpio_request(ourhost->gpios[cnt], "sdhci-gpio");
+               if (ret) {
+                       dev_err(dev, "gpio[%d] request failed\n", cnt);
+                       goto err_free_dt_gpios;
+               }
+       }
+
+       return 0;
+
+ err_free_dt_gpios:
+       while (--cnt >= 0)
+               gpio_free(ourhost->gpios[cnt]);
+ err_free_dt_cd_gpio:
+       if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL)
+               gpio_free(ourhost->ext_cd_gpio);
+       return -EINVAL;
+}
+#else
+static int __devinit sdhci_s3c_parse_dt(struct device *dev,
+               struct sdhci_host *host, struct s3c_sdhci_platdata *pdata)
+{
+       return -EINVAL;
+}
+#endif
+
+static const struct of_device_id sdhci_s3c_dt_match[];
+
 static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(
                        struct platform_device *pdev)
 {
+#ifdef CONFIG_OF
+       if (pdev->dev.of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(sdhci_s3c_dt_match, pdev->dev.of_node);
+               return (struct sdhci_s3c_drv_data *)match->data;
+       }
+#endif
        return (struct sdhci_s3c_drv_data *)
                        platform_get_device_id(pdev)->driver_data;
 }
@@ -436,7 +558,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        struct resource *res;
        int ret, irq, ptr, clks;
 
-       if (!pdev->dev.platform_data) {
+       if (!pdev->dev.platform_data && !pdev->dev.of_node) {
                dev_err(dev, "no device data specified\n");
                return -ENOENT;
        }
@@ -452,21 +574,28 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
                dev_err(dev, "sdhci_alloc_host() failed\n");
                return PTR_ERR(host);
        }
+       sc = sdhci_priv(host);
 
        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata) {
                ret = -ENOMEM;
-               goto err_io_clk;
+               goto err_pdata;
+       }
+
+       if (pdev->dev.of_node) {
+               ret = sdhci_s3c_parse_dt(&pdev->dev, host, pdata);
+               if (ret)
+                       goto err_pdata;
+       } else {
+               memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
+               sc->ext_cd_gpio = -1; /* invalid gpio number */
        }
-       memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
 
        drv_data = sdhci_s3c_get_driver_data(pdev);
-       sc = sdhci_priv(host);
 
        sc->host = host;
        sc->pdev = pdev;
        sc->pdata = pdata;
-       sc->ext_cd_gpio = -1; /* invalid gpio number */
 
        platform_set_drvdata(pdev, host);
 
@@ -486,9 +615,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
 
                snprintf(name, 14, "mmc_busclk.%d", ptr);
                clk = clk_get(dev, name);
-               if (IS_ERR(clk)) {
+               if (IS_ERR(clk))
                        continue;
-               }
 
                clks++;
                sc->clk_bus[ptr] = clk;
@@ -499,8 +627,6 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
                 */
                sc->cur_clk = ptr;
 
-               clk_enable(clk);
-
                dev_info(dev, "clock source %d: %s (%ld Hz)\n",
                         ptr, name, clk_get_rate(clk));
        }
@@ -511,6 +637,10 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
                goto err_no_busclks;
        }
 
+#ifndef CONFIG_PM_RUNTIME
+       clk_enable(sc->clk_bus[sc->cur_clk]);
+#endif
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        host->ioaddr = devm_request_and_ioremap(&pdev->dev, res);
        if (!host->ioaddr) {
@@ -616,12 +746,17 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
            gpio_is_valid(pdata->ext_cd_gpio))
                sdhci_s3c_setup_card_detect_gpio(sc);
 
+#ifdef CONFIG_PM_RUNTIME
+       clk_disable(sc->clk_io);
+#endif
        return 0;
 
  err_req_regs:
+#ifndef CONFIG_PM_RUNTIME
+       clk_disable(sc->clk_bus[sc->cur_clk]);
+#endif
        for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
                if (sc->clk_bus[ptr]) {
-                       clk_disable(sc->clk_bus[ptr]);
                        clk_put(sc->clk_bus[ptr]);
                }
        }
@@ -631,6 +766,12 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        clk_put(sc->clk_io);
 
  err_io_clk:
+       for (ptr = 0; ptr < NUM_GPIOS(sc->pdata->max_width); ptr++)
+               gpio_free(sc->gpios[ptr]);
+       if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL)
+               gpio_free(sc->ext_cd_gpio);
+
+ err_pdata:
        sdhci_free_host(host);
 
        return ret;
@@ -638,9 +779,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
 
 static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
 {
-       struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
        struct sdhci_host *host =  platform_get_drvdata(pdev);
        struct sdhci_s3c *sc = sdhci_priv(host);
+       struct s3c_sdhci_platdata *pdata = sc->pdata;
        int ptr;
 
        if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup)
@@ -652,19 +793,30 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
        if (gpio_is_valid(sc->ext_cd_gpio))
                gpio_free(sc->ext_cd_gpio);
 
+#ifdef CONFIG_PM_RUNTIME
+       clk_enable(sc->clk_io);
+#endif
        sdhci_remove_host(host, 1);
 
+       pm_runtime_dont_use_autosuspend(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
 
-       for (ptr = 0; ptr < 3; ptr++) {
+#ifndef CONFIG_PM_RUNTIME
+       clk_disable(sc->clk_bus[sc->cur_clk]);
+#endif
+       for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
                if (sc->clk_bus[ptr]) {
-                       clk_disable(sc->clk_bus[ptr]);
                        clk_put(sc->clk_bus[ptr]);
                }
        }
        clk_disable(sc->clk_io);
        clk_put(sc->clk_io);
 
+       if (pdev->dev.of_node) {
+               for (ptr = 0; ptr < NUM_GPIOS(sc->pdata->max_width); ptr++)
+                       gpio_free(sc->gpios[ptr]);
+       }
+
        sdhci_free_host(host);
        platform_set_drvdata(pdev, NULL);
 
@@ -691,15 +843,28 @@ static int sdhci_s3c_resume(struct device *dev)
 static int sdhci_s3c_runtime_suspend(struct device *dev)
 {
        struct sdhci_host *host = dev_get_drvdata(dev);
+       struct sdhci_s3c *ourhost = to_s3c(host);
+       struct clk *busclk = ourhost->clk_io;
+       int ret;
+
+       ret = sdhci_runtime_suspend_host(host);
 
-       return sdhci_runtime_suspend_host(host);
+       clk_disable(ourhost->clk_bus[ourhost->cur_clk]);
+       clk_disable(busclk);
+       return ret;
 }
 
 static int sdhci_s3c_runtime_resume(struct device *dev)
 {
        struct sdhci_host *host = dev_get_drvdata(dev);
+       struct sdhci_s3c *ourhost = to_s3c(host);
+       struct clk *busclk = ourhost->clk_io;
+       int ret;
 
-       return sdhci_runtime_resume_host(host);
+       clk_enable(busclk);
+       clk_enable(ourhost->clk_bus[ourhost->cur_clk]);
+       ret = sdhci_runtime_resume_host(host);
+       return ret;
 }
 #endif
 
@@ -737,6 +902,16 @@ static struct platform_device_id sdhci_s3c_driver_ids[] = {
 };
 MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids);
 
+#ifdef CONFIG_OF
+static const struct of_device_id sdhci_s3c_dt_match[] = {
+       { .compatible = "samsung,s3c6410-sdhci", },
+       { .compatible = "samsung,exynos4210-sdhci",
+               .data = (void *)EXYNOS4_SDHCI_DRV_DATA },
+       {},
+};
+MODULE_DEVICE_TABLE(of, sdhci_s3c_dt_match);
+#endif
+
 static struct platform_driver sdhci_s3c_driver = {
        .probe          = sdhci_s3c_probe,
        .remove         = __devexit_p(sdhci_s3c_remove),
@@ -744,6 +919,7 @@ static struct platform_driver sdhci_s3c_driver = {
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "s3c-sdhci",
+               .of_match_table = of_match_ptr(sdhci_s3c_dt_match),
                .pm     = SDHCI_S3C_PMOPS,
        },
 };
index 423da8194cd84e5597c169316311a5ff9629b845..6be89c032debe32f16ad978730b70695a2512aab 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
@@ -68,8 +70,42 @@ static irqreturn_t sdhci_gpio_irq(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_OF
+static struct sdhci_plat_data * __devinit
+sdhci_probe_config_dt(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct sdhci_plat_data *pdata = NULL;
+       int cd_gpio;
+
+       cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
+       if (!gpio_is_valid(cd_gpio))
+               cd_gpio = -1;
+
+       /* If pdata is required */
+       if (cd_gpio != -1) {
+               pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+               if (!pdata) {
+                       dev_err(&pdev->dev, "DT: kzalloc failed\n");
+                       return ERR_PTR(-ENOMEM);
+               }
+       }
+
+       pdata->card_int_gpio = cd_gpio;
+
+       return pdata;
+}
+#else
+static struct sdhci_plat_data * __devinit
+sdhci_probe_config_dt(struct platform_device *pdev)
+{
+       return ERR_PTR(-ENOSYS);
+}
+#endif
+
 static int __devinit sdhci_probe(struct platform_device *pdev)
 {
+       struct device_node *np = pdev->dev.of_node;
        struct sdhci_host *host;
        struct resource *iomem;
        struct spear_sdhci *sdhci;
@@ -104,14 +140,22 @@ static int __devinit sdhci_probe(struct platform_device *pdev)
                goto err;
        }
 
-       ret = clk_enable(sdhci->clk);
+       ret = clk_prepare_enable(sdhci->clk);
        if (ret) {
                dev_dbg(&pdev->dev, "Error enabling clock\n");
                goto put_clk;
        }
 
-       /* overwrite platform_data */
-       sdhci->data = dev_get_platdata(&pdev->dev);
+       if (np) {
+               sdhci->data = sdhci_probe_config_dt(pdev);
+               if (IS_ERR(sdhci->data)) {
+                       dev_err(&pdev->dev, "DT: Failed to get pdata\n");
+                       return -ENODEV;
+               }
+       } else {
+               sdhci->data = dev_get_platdata(&pdev->dev);
+       }
+
        pdev->dev.platform_data = sdhci;
 
        if (pdev->dev.parent)
@@ -216,7 +260,7 @@ set_drvdata:
 free_host:
        sdhci_free_host(host);
 disable_clk:
-       clk_disable(sdhci->clk);
+       clk_disable_unprepare(sdhci->clk);
 put_clk:
        clk_put(sdhci->clk);
 err:
@@ -238,7 +282,7 @@ static int __devexit sdhci_remove(struct platform_device *pdev)
 
        sdhci_remove_host(host, dead);
        sdhci_free_host(host);
-       clk_disable(sdhci->clk);
+       clk_disable_unprepare(sdhci->clk);
        clk_put(sdhci->clk);
 
        return 0;
@@ -253,7 +297,7 @@ static int sdhci_suspend(struct device *dev)
 
        ret = sdhci_suspend_host(host);
        if (!ret)
-               clk_disable(sdhci->clk);
+               clk_disable_unprepare(sdhci->clk);
 
        return ret;
 }
@@ -264,7 +308,7 @@ static int sdhci_resume(struct device *dev)
        struct spear_sdhci *sdhci = dev_get_platdata(dev);
        int ret;
 
-       ret = clk_enable(sdhci->clk);
+       ret = clk_prepare_enable(sdhci->clk);
        if (ret) {
                dev_dbg(dev, "Resume: Error enabling clock\n");
                return ret;
@@ -276,11 +320,20 @@ static int sdhci_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(sdhci_pm_ops, sdhci_suspend, sdhci_resume);
 
+#ifdef CONFIG_OF
+static const struct of_device_id sdhci_spear_id_table[] = {
+       { .compatible = "st,spear300-sdhci" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, sdhci_spear_id_table);
+#endif
+
 static struct platform_driver sdhci_driver = {
        .driver = {
                .name   = "sdhci",
                .owner  = THIS_MODULE,
                .pm     = &sdhci_pm_ops,
+               .of_match_table = of_match_ptr(sdhci_spear_id_table),
        },
        .probe          = sdhci_probe,
        .remove         = __devexit_p(sdhci_remove),
index d43e7462941fbd24bdecdb1063b8b4501a53bee8..f9eb9162370178793c804917aa57042f594757a5 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <asm/gpio.h>
 
-#include <mach/gpio-tegra.h>
 #include <linux/platform_data/mmc-sdhci-tegra.h>
 
 #include "sdhci-pltfm.h"
@@ -257,10 +256,9 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
        int rc;
 
        match = of_match_device(sdhci_tegra_dt_match, &pdev->dev);
-       if (match)
-               soc_data = match->data;
-       else
-               soc_data = &soc_data_tegra20;
+       if (!match)
+               return -EINVAL;
+       soc_data = match->data;
 
        host = sdhci_pltfm_init(pdev, soc_data->pdata);
        if (IS_ERR(host))
index 9a11dc39921c06ebdf67a3ed602fbba79cc38b89..7922adb4238625c1b4c9e1d489dea04a3d0e2353 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
+#include <linux/mmc/slot-gpio.h>
 
 #include "sdhci.h"
 
@@ -1293,6 +1294,13 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
                present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
                                SDHCI_CARD_PRESENT;
 
+       /* If we're using a cd-gpio, testing the presence bit might fail. */
+       if (!present) {
+               int ret = mmc_gpio_get_cd(host->mmc);
+               if (ret > 0)
+                       present = true;
+       }
+
        if (!present || host->flags & SDHCI_DEVICE_DEAD) {
                host->mrq->cmd->error = -ENOMEDIUM;
                tasklet_schedule(&host->finish_tasklet);
@@ -1597,57 +1605,65 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
        spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
-                                               struct mmc_ios *ios)
+static int sdhci_do_3_3v_signal_voltage_switch(struct sdhci_host *host,
+                                               u16 ctrl)
 {
-       u8 pwr;
-       u16 clk, ctrl;
-       u32 present_state;
+       int ret;
 
-       /*
-        * Signal Voltage Switching is only applicable for Host Controllers
-        * v3.00 and above.
-        */
-       if (host->version < SDHCI_SPEC_300)
-               return 0;
+       /* Set 1.8V Signal Enable in the Host Control2 register to 0 */
+       ctrl &= ~SDHCI_CTRL_VDD_180;
+       sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
-       /*
-        * We first check whether the request is to set signalling voltage
-        * to 3.3V. If so, we change the voltage to 3.3V and return quickly.
-        */
+       if (host->vqmmc) {
+               ret = regulator_set_voltage(host->vqmmc, 3300000, 3300000);
+               if (ret) {
+                       pr_warning("%s: Switching to 3.3V signalling voltage "
+                                  " failed\n", mmc_hostname(host->mmc));
+                       return -EIO;
+               }
+       }
+       /* Wait for 5ms */
+       usleep_range(5000, 5500);
+
+       /* 3.3V regulator output should be stable within 5 ms */
        ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-       if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
-               /* Set 1.8V Signal Enable in the Host Control2 register to 0 */
-               ctrl &= ~SDHCI_CTRL_VDD_180;
-               sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+       if (!(ctrl & SDHCI_CTRL_VDD_180))
+               return 0;
 
-               /* Wait for 5ms */
-               usleep_range(5000, 5500);
+       pr_warning("%s: 3.3V regulator output did not became stable\n",
+                  mmc_hostname(host->mmc));
 
-               /* 3.3V regulator output should be stable within 5 ms */
-               ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-               if (!(ctrl & SDHCI_CTRL_VDD_180))
-                       return 0;
-               else {
-                       pr_info(DRIVER_NAME ": Switching to 3.3V "
-                               "signalling voltage failed\n");
-                       return -EIO;
-               }
-       } else if (!(ctrl & SDHCI_CTRL_VDD_180) &&
-                 (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)) {
-               /* Stop SDCLK */
-               clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-               clk &= ~SDHCI_CLOCK_CARD_EN;
-               sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+       return -EIO;
+}
 
-               /* Check whether DAT[3:0] is 0000 */
-               present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
-               if (!((present_state & SDHCI_DATA_LVL_MASK) >>
-                      SDHCI_DATA_LVL_SHIFT)) {
-                       /*
-                        * Enable 1.8V Signal Enable in the Host Control2
-                        * register
-                        */
+static int sdhci_do_1_8v_signal_voltage_switch(struct sdhci_host *host,
+                                               u16 ctrl)
+{
+       u8 pwr;
+       u16 clk;
+       u32 present_state;
+       int ret;
+
+       /* Stop SDCLK */
+       clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+       clk &= ~SDHCI_CLOCK_CARD_EN;
+       sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+       /* Check whether DAT[3:0] is 0000 */
+       present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
+       if (!((present_state & SDHCI_DATA_LVL_MASK) >>
+              SDHCI_DATA_LVL_SHIFT)) {
+               /*
+                * Enable 1.8V Signal Enable in the Host Control2
+                * register
+                */
+               if (host->vqmmc)
+                       ret = regulator_set_voltage(host->vqmmc,
+                               1800000, 1800000);
+               else
+                       ret = 0;
+
+               if (!ret) {
                        ctrl |= SDHCI_CTRL_VDD_180;
                        sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
@@ -1656,7 +1672,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
 
                        ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
                        if (ctrl & SDHCI_CTRL_VDD_180) {
-                               /* Provide SDCLK again and wait for 1ms*/
+                               /* Provide SDCLK again and wait for 1ms */
                                clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
                                clk |= SDHCI_CLOCK_CARD_EN;
                                sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
@@ -1673,29 +1689,55 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
                                        return 0;
                        }
                }
+       }
 
-               /*
-                * If we are here, that means the switch to 1.8V signaling
-                * failed. We power cycle the card, and retry initialization
-                * sequence by setting S18R to 0.
-                */
-               pwr = sdhci_readb(host, SDHCI_POWER_CONTROL);
-               pwr &= ~SDHCI_POWER_ON;
-               sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
-               if (host->vmmc)
-                       regulator_disable(host->vmmc);
+       /*
+        * If we are here, that means the switch to 1.8V signaling
+        * failed. We power cycle the card, and retry initialization
+        * sequence by setting S18R to 0.
+        */
+       pwr = sdhci_readb(host, SDHCI_POWER_CONTROL);
+       pwr &= ~SDHCI_POWER_ON;
+       sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+       if (host->vmmc)
+               regulator_disable(host->vmmc);
 
-               /* Wait for 1ms as per the spec */
-               usleep_range(1000, 1500);
-               pwr |= SDHCI_POWER_ON;
-               sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
-               if (host->vmmc)
-                       regulator_enable(host->vmmc);
+       /* Wait for 1ms as per the spec */
+       usleep_range(1000, 1500);
+       pwr |= SDHCI_POWER_ON;
+       sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+       if (host->vmmc)
+               regulator_enable(host->vmmc);
 
-               pr_info(DRIVER_NAME ": Switching to 1.8V signalling "
-                       "voltage failed, retrying with S18R set to 0\n");
-               return -EAGAIN;
-       } else
+       pr_warning("%s: Switching to 1.8V signalling voltage failed, "
+                  "retrying with S18R set to 0\n", mmc_hostname(host->mmc));
+
+       return -EAGAIN;
+}
+
+static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
+                                               struct mmc_ios *ios)
+{
+       u16 ctrl;
+
+       /*
+        * Signal Voltage Switching is only applicable for Host Controllers
+        * v3.00 and above.
+        */
+       if (host->version < SDHCI_SPEC_300)
+               return 0;
+
+       /*
+        * We first check whether the request is to set signalling voltage
+        * to 3.3V. If so, we change the voltage to 3.3V and return quickly.
+        */
+       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+       if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330)
+               return sdhci_do_3_3v_signal_voltage_switch(host, ctrl);
+       else if (!(ctrl & SDHCI_CTRL_VDD_180) &&
+                       (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180))
+               return sdhci_do_1_8v_signal_voltage_switch(host, ctrl);
+       else
                /* No signal voltage switch required */
                return 0;
 }
@@ -2802,6 +2844,18 @@ int sdhci_add_host(struct sdhci_host *host)
            !(host->mmc->caps & MMC_CAP_NONREMOVABLE))
                mmc->caps |= MMC_CAP_NEEDS_POLL;
 
+       /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
+       host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc");
+       if (IS_ERR(host->vqmmc)) {
+               pr_info("%s: no vqmmc regulator found\n", mmc_hostname(mmc));
+               host->vqmmc = NULL;
+       }
+       else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000))
+               regulator_enable(host->vqmmc);
+       else
+               caps[1] &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
+                      SDHCI_SUPPORT_DDR50);
+
        /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */
        if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
                       SDHCI_SUPPORT_DDR50))
@@ -2832,15 +2886,6 @@ int sdhci_add_host(struct sdhci_host *host)
        if (caps[1] & SDHCI_DRIVER_TYPE_D)
                mmc->caps |= MMC_CAP_DRIVER_TYPE_D;
 
-       /*
-        * If Power Off Notify capability is enabled by the host,
-        * set notify to short power off notify timeout value.
-        */
-       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;
-
        /* Initial value for re-tuning timer count */
        host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >>
                              SDHCI_RETUNING_TIMER_COUNT_SHIFT;
@@ -2862,7 +2907,8 @@ int sdhci_add_host(struct sdhci_host *host)
        if (IS_ERR(host->vmmc)) {
                pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
                host->vmmc = NULL;
-       }
+       } else
+               regulator_enable(host->vmmc);
 
 #ifdef CONFIG_REGULATOR
        if (host->vmmc) {
@@ -3119,8 +3165,15 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
        tasklet_kill(&host->card_tasklet);
        tasklet_kill(&host->finish_tasklet);
 
-       if (host->vmmc)
+       if (host->vmmc) {
+               regulator_disable(host->vmmc);
                regulator_put(host->vmmc);
+       }
+
+       if (host->vqmmc) {
+               regulator_disable(host->vqmmc);
+               regulator_put(host->vqmmc);
+       }
 
        kfree(host->adma_desc);
        kfree(host->align_buffer);
index 5d8142773fac073b75cf56db111ecde2d398717d..11d2bc3b51d578a357fd9b857084db1a89a91741 100644 (file)
@@ -1213,7 +1213,9 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
                sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFRE);
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
        } else if (state & INT_DTRANE) {
-               sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_DTRANE);
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT,
+                       ~(INT_CMD12DRE | INT_CMD12RBE |
+                         INT_CMD12CRE | INT_DTRANE));
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
        } else if (state & INT_CMD12RBE) {
                sh_mmcif_writel(host->addr, MMCIF_CE_INT,
@@ -1229,6 +1231,10 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
                host->sd_error = true;
                dev_dbg(&host->pd->dev, "int err state = %08x\n", state);
        }
+       if (host->state == STATE_IDLE) {
+               dev_info(&host->pd->dev, "Spurious IRQ status 0x%x", state);
+               return IRQ_HANDLED;
+       }
        if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) {
                if (!host->dma_active)
                        return IRQ_WAKE_THREAD;
index 4b83c43f950d4634498ae809cbd40e827eec0339..f18becef156d391519cfb6d211bf2b0efa66a372 100644 (file)
@@ -1337,21 +1337,7 @@ static struct pci_driver via_sd_driver = {
        .resume = via_sd_resume,
 };
 
-static int __init via_sd_drv_init(void)
-{
-       pr_info(DRV_NAME ": VIA SD/MMC Card Reader driver "
-               "(C) 2008 VIA Technologies, Inc.\n");
-
-       return pci_register_driver(&via_sd_driver);
-}
-
-static void __exit via_sd_drv_exit(void)
-{
-       pci_unregister_driver(&via_sd_driver);
-}
-
-module_init(via_sd_drv_init);
-module_exit(via_sd_drv_exit);
+module_pci_driver(via_sd_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("VIA Technologies Inc.");
index 58eab9ac1d01dfc6f46bd6147a2cf6dac305e707..d5655a63eda4909f647185621cfe8837c380398d 100644 (file)
@@ -2358,9 +2358,9 @@ error5:
         * which is contained at the end of struct mmc
         */
 error4:
-       usb_free_urb(command_out_urb);
-error1:
        usb_free_urb(command_res_urb);
+error1:
+       usb_free_urb(command_out_urb);
 error0:
        return retval;
 }
index 27143e042af5b2dfec767a1d1cf61762fcf2734b..73fcbbeb78d05ff2dc3b695dd1aad00064783fcd 100644 (file)
@@ -148,6 +148,13 @@ config MTD_BCM63XX_PARTS
          This provides partions parsing for BCM63xx devices with CFE
          bootloaders.
 
+config MTD_BCM47XX_PARTS
+       tristate "BCM47XX partitioning support"
+       depends on BCM47XX
+       help
+         This provides partitions parser for devices based on BCM47xx
+         boards.
+
 comment "User Modules And Translation Layers"
 
 config MTD_CHAR
index f90135429dc7568e6446d9ac350837ed2ba648fc..18a38e55b2f0fec9cc3eb7466cf51568862e7d70 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_AFS_PARTS)    += afs.o
 obj-$(CONFIG_MTD_AR7_PARTS)    += ar7part.o
 obj-$(CONFIG_MTD_BCM63XX_PARTS)        += bcm63xxpart.o
+obj-$(CONFIG_MTD_BCM47XX_PARTS)        += bcm47xxpart.o
 
 # 'Users' - code which presents functionality to userspace.
 obj-$(CONFIG_MTD_CHAR)         += mtdchar.o
diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c
new file mode 100644 (file)
index 0000000..e06d782
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * BCM47XX MTD partitioning
+ *
+ * Copyright Â© 2012 RafaÅ‚ MiÅ‚ecki <zajec5@gmail.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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <asm/mach-bcm47xx/nvram.h>
+
+/* 10 parts were found on sflash on Netgear WNDR4500 */
+#define BCM47XXPART_MAX_PARTS          12
+
+/*
+ * Amount of bytes we read when analyzing each block of flash memory.
+ * Set it big enough to allow detecting partition and reading important data.
+ */
+#define BCM47XXPART_BYTES_TO_READ      0x404
+
+/* Magics */
+#define BOARD_DATA_MAGIC               0x5246504D      /* MPFR */
+#define POT_MAGIC1                     0x54544f50      /* POTT */
+#define POT_MAGIC2                     0x504f          /* OP */
+#define ML_MAGIC1                      0x39685a42
+#define ML_MAGIC2                      0x26594131
+#define TRX_MAGIC                      0x30524448
+
+struct trx_header {
+       uint32_t magic;
+       uint32_t length;
+       uint32_t crc32;
+       uint16_t flags;
+       uint16_t version;
+       uint32_t offset[3];
+} __packed;
+
+static void bcm47xxpart_add_part(struct mtd_partition *part, char *name,
+                                u64 offset, uint32_t mask_flags)
+{
+       part->name = name;
+       part->offset = offset;
+       part->mask_flags = mask_flags;
+}
+
+static int bcm47xxpart_parse(struct mtd_info *master,
+                            struct mtd_partition **pparts,
+                            struct mtd_part_parser_data *data)
+{
+       struct mtd_partition *parts;
+       uint8_t i, curr_part = 0;
+       uint32_t *buf;
+       size_t bytes_read;
+       uint32_t offset;
+       uint32_t blocksize = 0x10000;
+       struct trx_header *trx;
+
+       /* Alloc */
+       parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS,
+                       GFP_KERNEL);
+       buf = kzalloc(BCM47XXPART_BYTES_TO_READ, GFP_KERNEL);
+
+       /* Parse block by block looking for magics */
+       for (offset = 0; offset <= master->size - blocksize;
+            offset += blocksize) {
+               /* Nothing more in higher memory */
+               if (offset >= 0x2000000)
+                       break;
+
+               if (curr_part > BCM47XXPART_MAX_PARTS) {
+                       pr_warn("Reached maximum number of partitions, scanning stopped!\n");
+                       break;
+               }
+
+               /* Read beginning of the block */
+               if (mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ,
+                            &bytes_read, (uint8_t *)buf) < 0) {
+                       pr_err("mtd_read error while parsing (offset: 0x%X)!\n",
+                              offset);
+                       continue;
+               }
+
+               /* CFE has small NVRAM at 0x400 */
+               if (buf[0x400 / 4] == NVRAM_HEADER) {
+                       bcm47xxpart_add_part(&parts[curr_part++], "boot",
+                                            offset, MTD_WRITEABLE);
+                       continue;
+               }
+
+               /* Standard NVRAM */
+               if (buf[0x000 / 4] == NVRAM_HEADER) {
+                       bcm47xxpart_add_part(&parts[curr_part++], "nvram",
+                                            offset, 0);
+                       continue;
+               }
+
+               /*
+                * board_data starts with board_id which differs across boards,
+                * but we can use 'MPFR' (hopefully) magic at 0x100
+                */
+               if (buf[0x100 / 4] == BOARD_DATA_MAGIC) {
+                       bcm47xxpart_add_part(&parts[curr_part++], "board_data",
+                                            offset, MTD_WRITEABLE);
+                       continue;
+               }
+
+               /* POT(TOP) */
+               if (buf[0x000 / 4] == POT_MAGIC1 &&
+                   (buf[0x004 / 4] & 0xFFFF) == POT_MAGIC2) {
+                       bcm47xxpart_add_part(&parts[curr_part++], "POT", offset,
+                                            MTD_WRITEABLE);
+                       continue;
+               }
+
+               /* ML */
+               if (buf[0x010 / 4] == ML_MAGIC1 &&
+                   buf[0x014 / 4] == ML_MAGIC2) {
+                       bcm47xxpart_add_part(&parts[curr_part++], "ML", offset,
+                                            MTD_WRITEABLE);
+                       continue;
+               }
+
+               /* TRX */
+               if (buf[0x000 / 4] == TRX_MAGIC) {
+                       trx = (struct trx_header *)buf;
+
+                       i = 0;
+                       /* We have LZMA loader if offset[2] points to sth */
+                       if (trx->offset[2]) {
+                               bcm47xxpart_add_part(&parts[curr_part++],
+                                                    "loader",
+                                                    offset + trx->offset[i],
+                                                    0);
+                               i++;
+                       }
+
+                       bcm47xxpart_add_part(&parts[curr_part++], "linux",
+                                            offset + trx->offset[i], 0);
+                       i++;
+
+                       /*
+                        * Pure rootfs size is known and can be calculated as:
+                        * trx->length - trx->offset[i]. We don't fill it as
+                        * we want to have jffs2 (overlay) in the same mtd.
+                        */
+                       bcm47xxpart_add_part(&parts[curr_part++], "rootfs",
+                                            offset + trx->offset[i], 0);
+                       i++;
+
+                       /*
+                        * We have whole TRX scanned, skip to the next part. Use
+                        * roundown (not roundup), as the loop will increase
+                        * offset in next step.
+                        */
+                       offset = rounddown(offset + trx->length, blocksize);
+                       continue;
+               }
+       }
+       kfree(buf);
+
+       /*
+        * Assume that partitions end at the beginning of the one they are
+        * followed by.
+        */
+       for (i = 0; i < curr_part - 1; i++)
+               parts[i].size = parts[i + 1].offset - parts[i].offset;
+       if (curr_part > 0)
+               parts[curr_part - 1].size =
+                               master->size - parts[curr_part - 1].offset;
+
+       *pparts = parts;
+       return curr_part;
+};
+
+static struct mtd_part_parser bcm47xxpart_mtd_parser = {
+       .owner = THIS_MODULE,
+       .parse_fn = bcm47xxpart_parse,
+       .name = "bcm47xxpart",
+};
+
+static int __init bcm47xxpart_init(void)
+{
+       return register_mtd_parser(&bcm47xxpart_mtd_parser);
+}
+
+static void __exit bcm47xxpart_exit(void)
+{
+       deregister_mtd_parser(&bcm47xxpart_mtd_parser);
+}
+
+module_init(bcm47xxpart_init);
+module_exit(bcm47xxpart_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MTD partitioning for BCM47XX flash memories");
index b1e3c26edd6dad3953cfc11203de1497b25887aa..e469b01d40d26960594380602b67e1baefcab4d2 100644 (file)
@@ -43,9 +43,6 @@ choice
        prompt "Flash cmd/query data swapping"
        depends on MTD_CFI_ADV_OPTIONS
        default MTD_CFI_NOSWAP
-
-config MTD_CFI_NOSWAP
-       bool "NO"
        ---help---
          This option defines the way in which the CPU attempts to arrange
          data bits when writing the 'magic' commands to the chips. Saying
@@ -55,12 +52,8 @@ config MTD_CFI_NOSWAP
          Specific arrangements are possible with the BIG_ENDIAN_BYTE and
          LITTLE_ENDIAN_BYTE, if the bytes are reversed.
 
-         If you have a LART, on which the data (and address) lines were
-         connected in a fashion which ensured that the nets were as short
-         as possible, resulting in a bit-shuffling which seems utterly
-         random to the untrained eye, you need the LART_ENDIAN_BYTE option.
-
-         Yes, there really exists something sicker than PDP-endian :)
+config MTD_CFI_NOSWAP
+       bool "NO"
 
 config MTD_CFI_BE_BYTE_SWAP
        bool "BIG_ENDIAN_BYTE"
index dbbd2edfb812805e96c95ea7530aa229c821d78c..77514430f1fe57d7156862ac0ef06b45d8fa35ba 100644 (file)
@@ -2043,7 +2043,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
 {
        struct cfi_private *cfi = map->fldrv_priv;
        struct cfi_pri_intelext *extp = cfi->cmdset_priv;
-       int udelay;
+       int mdelay;
        int ret;
 
        adr += chip->start;
@@ -2072,9 +2072,17 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
         * If Instant Individual Block Locking supported then no need
         * to delay.
         */
-       udelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1000000/HZ : 0;
+       /*
+        * Unlocking may take up to 1.4 seconds on some Intel flashes. So
+        * lets use a max of 1.5 seconds (1500ms) as timeout.
+        *
+        * See "Clear Block Lock-Bits Time" on page 40 in
+        * "3 Volt Intel StrataFlash Memory" 28F128J3,28F640J3,28F320J3 manual
+        * from February 2003
+        */
+       mdelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1500 : 0;
 
-       ret = WAIT_TIMEOUT(map, chip, adr, udelay, udelay * 100);
+       ret = WAIT_TIMEOUT(map, chip, adr, mdelay, mdelay * 1000);
        if (ret) {
                map_write(map, CMD(0x70), adr);
                chip->state = FL_STATUS;
index 22d0493a026ff7adfe07b62bf7e11555e9f67982..5ff5c4a16943c16dfefca20def28300b398ad6b6 100644 (file)
@@ -431,6 +431,68 @@ static void cfi_fixup_major_minor(struct cfi_private *cfi,
        }
 }
 
+static int is_m29ew(struct cfi_private *cfi)
+{
+       if (cfi->mfr == CFI_MFR_INTEL &&
+           ((cfi->device_type == CFI_DEVICETYPE_X8 && (cfi->id & 0xff) == 0x7e) ||
+            (cfi->device_type == CFI_DEVICETYPE_X16 && cfi->id == 0x227e)))
+               return 1;
+       return 0;
+}
+
+/*
+ * From TN-13-07: Patching the Linux Kernel and U-Boot for M29 Flash, page 20:
+ * Some revisions of the M29EW suffer from erase suspend hang ups. In
+ * particular, it can occur when the sequence
+ * Erase Confirm -> Suspend -> Program -> Resume
+ * causes a lockup due to internal timing issues. The consequence is that the
+ * erase cannot be resumed without inserting a dummy command after programming
+ * and prior to resuming. [...] The work-around is to issue a dummy write cycle
+ * that writes an F0 command code before the RESUME command.
+ */
+static void cfi_fixup_m29ew_erase_suspend(struct map_info *map,
+                                         unsigned long adr)
+{
+       struct cfi_private *cfi = map->fldrv_priv;
+       /* before resume, insert a dummy 0xF0 cycle for Micron M29EW devices */
+       if (is_m29ew(cfi))
+               map_write(map, CMD(0xF0), adr);
+}
+
+/*
+ * From TN-13-07: Patching the Linux Kernel and U-Boot for M29 Flash, page 22:
+ *
+ * Some revisions of the M29EW (for example, A1 and A2 step revisions)
+ * are affected by a problem that could cause a hang up when an ERASE SUSPEND
+ * command is issued after an ERASE RESUME operation without waiting for a
+ * minimum delay.  The result is that once the ERASE seems to be completed
+ * (no bits are toggling), the contents of the Flash memory block on which
+ * the erase was ongoing could be inconsistent with the expected values
+ * (typically, the array value is stuck to the 0xC0, 0xC4, 0x80, or 0x84
+ * values), causing a consequent failure of the ERASE operation.
+ * The occurrence of this issue could be high, especially when file system
+ * operations on the Flash are intensive.  As a result, it is recommended
+ * that a patch be applied.  Intensive file system operations can cause many
+ * calls to the garbage routine to free Flash space (also by erasing physical
+ * Flash blocks) and as a result, many consecutive SUSPEND and RESUME
+ * commands can occur.  The problem disappears when a delay is inserted after
+ * the RESUME command by using the udelay() function available in Linux.
+ * The DELAY value must be tuned based on the customer's platform.
+ * The maximum value that fixes the problem in all cases is 500us.
+ * But, in our experience, a delay of 30 Âµs to 50 Âµs is sufficient
+ * in most cases.
+ * We have chosen 500µs because this latency is acceptable.
+ */
+static void cfi_fixup_m29ew_delay_after_resume(struct cfi_private *cfi)
+{
+       /*
+        * Resolving the Delay After Resume Issue see Micron TN-13-07
+        * Worst case delay must be 500µs but 30-50µs should be ok as well
+        */
+       if (is_m29ew(cfi))
+               cfi_udelay(500);
+}
+
 struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
 {
        struct cfi_private *cfi = map->fldrv_priv;
@@ -776,7 +838,10 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
 
        switch(chip->oldstate) {
        case FL_ERASING:
+               cfi_fixup_m29ew_erase_suspend(map,
+                       chip->in_progress_block_addr);
                map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr);
+               cfi_fixup_m29ew_delay_after_resume(cfi);
                chip->oldstate = FL_READY;
                chip->state = FL_ERASING;
                break;
@@ -916,6 +981,8 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
                        /* Disallow XIP again */
                        local_irq_disable();
 
+                       /* Correct Erase Suspend Hangups for M29EW */
+                       cfi_fixup_m29ew_erase_suspend(map, adr);
                        /* Resume the write or erase operation */
                        map_write(map, cfi->sector_erase_cmd, adr);
                        chip->state = oldstate;
index 4558e0f4d07f89b39a6ab7cce953ef5de701111b..aed1b8a63c9feee71caceccc93842b188349f349 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
-#include <linux/bootmem.h>
 #include <linux/module.h>
+#include <linux/err.h>
 
 /* error message prefix */
 #define ERRP "mtd: "
@@ -72,7 +71,7 @@ static struct cmdline_mtd_partition *partitions;
 
 /* the command line passed to mtdpart_setup() */
 static char *cmdline;
-static int cmdline_parsed = 0;
+static int cmdline_parsed;
 
 /*
  * Parse one partition definition for an MTD. Since there can be many
@@ -83,15 +82,14 @@ static int cmdline_parsed = 0;
  * syntax has been verified ok.
  */
 static struct mtd_partition * newpart(char *s,
-                                      char **retptr,
-                                      int *num_parts,
-                                      int this_part,
-                                      unsigned char **extra_mem_ptr,
-                                      int extra_mem_size)
+                                     char **retptr,
+                                     int *num_parts,
+                                     int this_part,
+                                     unsigned char **extra_mem_ptr,
+                                     int extra_mem_size)
 {
        struct mtd_partition *parts;
-       unsigned long size;
-       unsigned long offset = OFFSET_CONTINUOUS;
+       unsigned long size, offset = OFFSET_CONTINUOUS;
        char *name;
        int name_len;
        unsigned char *extra_mem;
@@ -99,124 +97,106 @@ static struct mtd_partition * newpart(char *s,
        unsigned int mask_flags;
 
        /* fetch the partition size */
-       if (*s == '-')
-       {       /* assign all remaining space to this partition */
+       if (*s == '-') {
+               /* assign all remaining space to this partition */
                size = SIZE_REMAINING;
                s++;
-       }
-       else
-       {
+       } else {
                size = memparse(s, &s);
-               if (size < PAGE_SIZE)
-               {
+               if (size < PAGE_SIZE) {
                        printk(KERN_ERR ERRP "partition size too small (%lx)\n", size);
-                       return NULL;
+                       return ERR_PTR(-EINVAL);
                }
        }
 
        /* fetch partition name and flags */
        mask_flags = 0; /* this is going to be a regular partition */
        delim = 0;
-        /* check for offset */
-        if (*s == '@')
-       {
-                s++;
-                offset = memparse(s, &s);
-        }
-        /* now look for name */
+
+       /* check for offset */
+       if (*s == '@') {
+               s++;
+               offset = memparse(s, &s);
+       }
+
+       /* now look for name */
        if (*s == '(')
-       {
                delim = ')';
-       }
 
-       if (delim)
-       {
+       if (delim) {
                char *p;
 
-               name = ++s;
+               name = ++s;
                p = strchr(name, delim);
-               if (!p)
-               {
+               if (!p) {
                        printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim);
-                       return NULL;
+                       return ERR_PTR(-EINVAL);
                }
                name_len = p - name;
                s = p + 1;
-       }
-       else
-       {
-               name = NULL;
+       } else {
+               name = NULL;
                name_len = 13; /* Partition_000 */
        }
 
        /* record name length for memory allocation later */
        extra_mem_size += name_len + 1;
 
-        /* test for options */
-        if (strncmp(s, "ro", 2) == 0)
-       {
+       /* test for options */
+       if (strncmp(s, "ro", 2) == 0) {
                mask_flags |= MTD_WRITEABLE;
                s += 2;
-        }
+       }
 
-        /* if lk is found do NOT unlock the MTD partition*/
-        if (strncmp(s, "lk", 2) == 0)
-       {
+       /* if lk is found do NOT unlock the MTD partition*/
+       if (strncmp(s, "lk", 2) == 0) {
                mask_flags |= MTD_POWERUP_LOCK;
                s += 2;
-        }
+       }
 
        /* test if more partitions are following */
-       if (*s == ',')
-       {
-               if (size == SIZE_REMAINING)
-               {
+       if (*s == ',') {
+               if (size == SIZE_REMAINING) {
                        printk(KERN_ERR ERRP "no partitions allowed after a fill-up partition\n");
-                       return NULL;
+                       return ERR_PTR(-EINVAL);
                }
                /* more partitions follow, parse them */
                parts = newpart(s + 1, &s, num_parts, this_part + 1,
                                &extra_mem, extra_mem_size);
-               if (!parts)
-                       return NULL;
-       }
-       else
-       {       /* this is the last partition: allocate space for all */
+               if (IS_ERR(parts))
+                       return parts;
+       } else {
+               /* this is the last partition: allocate space for all */
                int alloc_size;
 
                *num_parts = this_part + 1;
                alloc_size = *num_parts * sizeof(struct mtd_partition) +
                             extra_mem_size;
+
                parts = kzalloc(alloc_size, GFP_KERNEL);
                if (!parts)
-                       return NULL;
+                       return ERR_PTR(-ENOMEM);
                extra_mem = (unsigned char *)(parts + *num_parts);
        }
+
        /* enter this partition (offset will be calculated later if it is zero at this point) */
        parts[this_part].size = size;
        parts[this_part].offset = offset;
        parts[this_part].mask_flags = mask_flags;
        if (name)
-       {
                strlcpy(extra_mem, name, name_len + 1);
-       }
        else
-       {
                sprintf(extra_mem, "Partition_%03d", this_part);
-       }
        parts[this_part].name = extra_mem;
        extra_mem += name_len + 1;
 
        dbg(("partition %d: name <%s>, offset %llx, size %llx, mask flags %x\n",
-            this_part,
-            parts[this_part].name,
-            parts[this_part].offset,
-            parts[this_part].size,
-            parts[this_part].mask_flags));
+            this_part, parts[this_part].name, parts[this_part].offset,
+            parts[this_part].size, parts[this_part].mask_flags));
 
        /* return (updated) pointer to extra_mem memory */
        if (extra_mem_ptr)
-         *extra_mem_ptr = extra_mem;
+               *extra_mem_ptr = extra_mem;
 
        /* return (updated) pointer command line string */
        *retptr = s;
@@ -236,16 +216,16 @@ static int mtdpart_setup_real(char *s)
        {
                struct cmdline_mtd_partition *this_mtd;
                struct mtd_partition *parts;
-               int mtd_id_len;
-               int num_parts;
+               int mtd_id_len, num_parts;
                char *p, *mtd_id;
 
-               mtd_id = s;
+               mtd_id = s;
+
                /* fetch <mtd-id> */
-               if (!(p = strchr(s, ':')))
-               {
+               p = strchr(s, ':');
+               if (!p) {
                        printk(KERN_ERR ERRP "no mtd-id\n");
-                       return 0;
+                       return -EINVAL;
                }
                mtd_id_len = p - mtd_id;
 
@@ -262,8 +242,7 @@ static int mtdpart_setup_real(char *s)
                                (unsigned char**)&this_mtd, /* out: extra mem */
                                mtd_id_len + 1 + sizeof(*this_mtd) +
                                sizeof(void*)-1 /*alignment*/);
-               if(!parts)
-               {
+               if (IS_ERR(parts)) {
                        /*
                         * An error occurred. We're either:
                         * a) out of memory, or
@@ -271,12 +250,12 @@ static int mtdpart_setup_real(char *s)
                         * Either way, this mtd is hosed and we're
                         * unlikely to succeed in parsing any more
                         */
-                        return 0;
+                        return PTR_ERR(parts);
                 }
 
                /* align this_mtd */
                this_mtd = (struct cmdline_mtd_partition *)
-                       ALIGN((unsigned long)this_mtd, sizeof(void*));
+                               ALIGN((unsigned long)this_mtd, sizeof(void *));
                /* enter results */
                this_mtd->parts = parts;
                this_mtd->num_parts = num_parts;
@@ -296,14 +275,14 @@ static int mtdpart_setup_real(char *s)
                        break;
 
                /* does another spec follow? */
-               if (*s != ';')
-               {
+               if (*s != ';') {
                        printk(KERN_ERR ERRP "bad character after partition (%c)\n", *s);
-                       return 0;
+                       return -EINVAL;
                }
                s++;
        }
-       return 1;
+
+       return 0;
 }
 
 /*
@@ -318,44 +297,58 @@ static int parse_cmdline_partitions(struct mtd_info *master,
                                    struct mtd_part_parser_data *data)
 {
        unsigned long offset;
-       int i;
+       int i, err;
        struct cmdline_mtd_partition *part;
        const char *mtd_id = master->name;
 
        /* parse command line */
-       if (!cmdline_parsed)
-               mtdpart_setup_real(cmdline);
+       if (!cmdline_parsed) {
+               err = mtdpart_setup_real(cmdline);
+               if (err)
+                       return err;
+       }
 
-       for(part = partitions; part; part = part->next)
-       {
-               if ((!mtd_id) || (!strcmp(part->mtd_id, mtd_id)))
-               {
-                       for(i = 0, offset = 0; i < part->num_parts; i++)
-                       {
+       for (part = partitions; part; part = part->next) {
+               if ((!mtd_id) || (!strcmp(part->mtd_id, mtd_id))) {
+                       for (i = 0, offset = 0; i < part->num_parts; i++) {
                                if (part->parts[i].offset == OFFSET_CONTINUOUS)
-                                 part->parts[i].offset = offset;
+                                       part->parts[i].offset = offset;
                                else
-                                 offset = part->parts[i].offset;
+                                       offset = part->parts[i].offset;
+
                                if (part->parts[i].size == SIZE_REMAINING)
-                                 part->parts[i].size = master->size - offset;
-                               if (offset + part->parts[i].size > master->size)
-                               {
+                                       part->parts[i].size = master->size - offset;
+
+                               if (part->parts[i].size == 0) {
+                                       printk(KERN_WARNING ERRP
+                                              "%s: skipping zero sized partition\n",
+                                              part->mtd_id);
+                                       part->num_parts--;
+                                       memmove(&part->parts[i],
+                                               &part->parts[i + 1],
+                                               sizeof(*part->parts) * (part->num_parts - i));
+                                       continue;
+                               }
+
+                               if (offset + part->parts[i].size > master->size) {
                                        printk(KERN_WARNING ERRP
                                               "%s: partitioning exceeds flash size, truncating\n",
                                               part->mtd_id);
                                        part->parts[i].size = master->size - offset;
-                                       part->num_parts = i;
                                }
                                offset += part->parts[i].size;
                        }
+
                        *pparts = kmemdup(part->parts,
                                        sizeof(*part->parts) * part->num_parts,
                                        GFP_KERNEL);
                        if (!*pparts)
                                return -ENOMEM;
+
                        return part->num_parts;
                }
        }
+
        return 0;
 }
 
index 4cdb2af7bf44e74dbb72bab223d39beabd7c265a..27f80cd8aef3770ee1d5c67c030088407c0967ba 100644 (file)
@@ -97,7 +97,7 @@ config MTD_M25P80
          doesn't support the JEDEC ID instruction.
 
 config M25PXX_USE_FAST_READ
-       bool "Use FAST_READ OPCode allowing SPI CLK <= 50MHz"
+       bool "Use FAST_READ OPCode allowing SPI CLK >= 50MHz"
        depends on MTD_M25P80
        default y
        help
@@ -120,6 +120,14 @@ config MTD_SST25L
          Set up your spi devices with the right board-specific platform data,
          if you want to specify device partitioning.
 
+config MTD_BCM47XXSFLASH
+       tristate "R/O support for serial flash on BCMA bus"
+       depends on BCMA_SFLASH
+       help
+         BCMA bus can have various flash memories attached, they are
+         registered by bcma as platform devices. This enables driver for
+         serial flash memories (only read-only mode is implemented).
+
 config MTD_SLRAM
        tristate "Uncached system RAM"
        help
index a4dd1d822b6c0db81a2bafd7c9ed6b790ca4ac2e..395733a30ef44e7c483e79768db3c7b5e46e68ba 100644 (file)
@@ -19,5 +19,6 @@ obj-$(CONFIG_MTD_DATAFLASH)   += mtd_dataflash.o
 obj-$(CONFIG_MTD_M25P80)       += m25p80.o
 obj-$(CONFIG_MTD_SPEAR_SMI)    += spear_smi.o
 obj-$(CONFIG_MTD_SST25L)       += sst25l.o
+obj-$(CONFIG_MTD_BCM47XXSFLASH)        += bcm47xxsflash.o
 
 CFLAGS_docg3.o                 += -I$(src)
\ No newline at end of file
diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c
new file mode 100644 (file)
index 0000000..2dc5a6f
--- /dev/null
@@ -0,0 +1,105 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
+#include <linux/platform_device.h>
+#include <linux/bcma/bcma.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Serial flash driver for BCMA bus");
+
+static const char *probes[] = { "bcm47xxpart", NULL };
+
+static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
+                             size_t *retlen, u_char *buf)
+{
+       struct bcma_sflash *sflash = mtd->priv;
+
+       /* Check address range */
+       if ((from + len) > mtd->size)
+               return -EINVAL;
+
+       memcpy_fromio(buf, (void __iomem *)KSEG0ADDR(sflash->window + from),
+                     len);
+
+       return len;
+}
+
+static void bcm47xxsflash_fill_mtd(struct bcma_sflash *sflash,
+                                  struct mtd_info *mtd)
+{
+       mtd->priv = sflash;
+       mtd->name = "bcm47xxsflash";
+       mtd->owner = THIS_MODULE;
+       mtd->type = MTD_ROM;
+       mtd->size = sflash->size;
+       mtd->_read = bcm47xxsflash_read;
+
+       /* TODO: implement writing support and verify/change following code */
+       mtd->flags = MTD_CAP_ROM;
+       mtd->writebufsize = mtd->writesize = 1;
+}
+
+static int bcm47xxsflash_probe(struct platform_device *pdev)
+{
+       struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev);
+       int err;
+
+       sflash->mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
+       if (!sflash->mtd) {
+               err = -ENOMEM;
+               goto out;
+       }
+       bcm47xxsflash_fill_mtd(sflash, sflash->mtd);
+
+       err = mtd_device_parse_register(sflash->mtd, probes, NULL, NULL, 0);
+       if (err) {
+               pr_err("Failed to register MTD device: %d\n", err);
+               goto err_dev_reg;
+       }
+
+       return 0;
+
+err_dev_reg:
+       kfree(sflash->mtd);
+out:
+       return err;
+}
+
+static int __devexit bcm47xxsflash_remove(struct platform_device *pdev)
+{
+       struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev);
+
+       mtd_device_unregister(sflash->mtd);
+       kfree(sflash->mtd);
+
+       return 0;
+}
+
+static struct platform_driver bcma_sflash_driver = {
+       .remove = __devexit_p(bcm47xxsflash_remove),
+       .driver = {
+               .name = "bcma_sflash",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init bcm47xxsflash_init(void)
+{
+       int err;
+
+       err = platform_driver_probe(&bcma_sflash_driver, bcm47xxsflash_probe);
+       if (err)
+               pr_err("Failed to register BCMA serial flash driver: %d\n",
+                      err);
+
+       return err;
+}
+
+static void __exit bcm47xxsflash_exit(void)
+{
+       platform_driver_unregister(&bcma_sflash_driver);
+}
+
+module_init(bcm47xxsflash_init);
+module_exit(bcm47xxsflash_exit);
index 04eb2e4aa50f1bdfd0aaae18de0b8700aef00483..4f2220ad89244a1c68bd8add2188385b9cced5b0 100644 (file)
@@ -659,23 +659,15 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
 #ifdef ECC_DEBUG
                        printk("%s(%d): Millennium Plus ECC error (from=0x%x:\n",
                                __FILE__, __LINE__, (int)from);
-                       printk("        syndrome= %02x:%02x:%02x:%02x:%02x:"
-                               "%02x\n",
-                               syndrome[0], syndrome[1], syndrome[2],
-                               syndrome[3], syndrome[4], syndrome[5]);
-                       printk("          eccbuf= %02x:%02x:%02x:%02x:%02x:"
-                               "%02x\n",
-                               eccbuf[0], eccbuf[1], eccbuf[2],
-                               eccbuf[3], eccbuf[4], eccbuf[5]);
+                       printk("        syndrome= %*phC\n", 6, syndrome);
+                       printk("        eccbuf= %*phC\n", 6, eccbuf);
 #endif
                                ret = -EIO;
                }
        }
 
 #ifdef PSYCHO_DEBUG
-       printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
-              (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
-              eccbuf[4], eccbuf[5]);
+       printk("ECC DATA at %lx: %*ph\n", (long)from, 6, eccbuf);
 #endif
        /* disable the ECC engine */
        WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf);
index f70854d728fe04f3ea7ae2507efd9f458358bc24..d34d83b8f9c22347da339e52b9071b5c1b8f9e2c 100644 (file)
@@ -919,19 +919,13 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from,
                eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1);
 
                if (nboob >= DOC_LAYOUT_OOB_SIZE) {
-                       doc_dbg("OOB - INFO: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
-                               oobbuf[0], oobbuf[1], oobbuf[2], oobbuf[3],
-                               oobbuf[4], oobbuf[5], oobbuf[6]);
+                       doc_dbg("OOB - INFO: %*phC\n", 7, oobbuf);
                        doc_dbg("OOB - HAMMING: %02x\n", oobbuf[7]);
-                       doc_dbg("OOB - BCH_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
-                               oobbuf[8], oobbuf[9], oobbuf[10], oobbuf[11],
-                               oobbuf[12], oobbuf[13], oobbuf[14]);
+                       doc_dbg("OOB - BCH_ECC: %*phC\n", 7, oobbuf + 8);
                        doc_dbg("OOB - UNUSED: %02x\n", oobbuf[15]);
                }
                doc_dbg("ECC checks: ECCConf1=%x\n", eccconf1);
-               doc_dbg("ECC HW_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
-                       hwecc[0], hwecc[1], hwecc[2], hwecc[3], hwecc[4],
-                       hwecc[5], hwecc[6]);
+               doc_dbg("ECC HW_ECC: %*phC\n", 7, hwecc);
 
                ret = -EIO;
                if (is_prot_seq_error(docg3))
index 5d0d68c3fe27a79a097d64fa03246c276510ad3b..03838bab1f594e01bce9554d292a2ffdd4ef600c 100644 (file)
@@ -633,11 +633,14 @@ static const struct spi_device_id m25p_ids[] = {
        { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
        { "at26df321",  INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) },
 
+       { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) },
+
        /* EON -- en25xxx */
        { "en25f32", INFO(0x1c3116, 0, 64 * 1024,  64, SECT_4K) },
        { "en25p32", INFO(0x1c2016, 0, 64 * 1024,  64, 0) },
        { "en25q32b", INFO(0x1c3016, 0, 64 * 1024,  64, 0) },
        { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
+       { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
 
        /* Everspin */
        { "mr25h256", CAT25_INFO(  32 * 1024, 1, 256, 2) },
@@ -646,6 +649,7 @@ static const struct spi_device_id m25p_ids[] = {
        { "160s33b",  INFO(0x898911, 0, 64 * 1024,  32, 0) },
        { "320s33b",  INFO(0x898912, 0, 64 * 1024,  64, 0) },
        { "640s33b",  INFO(0x898913, 0, 64 * 1024, 128, 0) },
+       { "n25q064",  INFO(0x20ba17, 0, 64 * 1024, 128, 0) },
 
        /* Macronix */
        { "mx25l2005a",  INFO(0xc22012, 0, 64 * 1024,   4, SECT_4K) },
@@ -659,15 +663,15 @@ static const struct spi_device_id m25p_ids[] = {
        { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
        { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
 
+       /* Micron */
+       { "n25q128",  INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
+       { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
+
        /* Spansion -- single (large) sector size only, at least
         * for the chips listed here (without boot sectors).
         */
-       { "s25sl004a",  INFO(0x010212,      0,  64 * 1024,   8, 0) },
-       { "s25sl008a",  INFO(0x010213,      0,  64 * 1024,  16, 0) },
-       { "s25sl016a",  INFO(0x010214,      0,  64 * 1024,  32, 0) },
-       { "s25sl032a",  INFO(0x010215,      0,  64 * 1024,  64, 0) },
-       { "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, SECT_4K) },
-       { "s25sl064a",  INFO(0x010216,      0,  64 * 1024, 128, 0) },
+       { "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, 0) },
+       { "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128, 0) },
        { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
        { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, 0) },
        { "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, 0) },
@@ -676,6 +680,11 @@ static const struct spi_device_id m25p_ids[] = {
        { "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, 0) },
        { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024,  64, 0) },
        { "s25fl129p1", INFO(0x012018, 0x4d01,  64 * 1024, 256, 0) },
+       { "s25sl004a",  INFO(0x010212,      0,  64 * 1024,   8, 0) },
+       { "s25sl008a",  INFO(0x010213,      0,  64 * 1024,  16, 0) },
+       { "s25sl016a",  INFO(0x010214,      0,  64 * 1024,  32, 0) },
+       { "s25sl032a",  INFO(0x010215,      0,  64 * 1024,  64, 0) },
+       { "s25sl064a",  INFO(0x010216,      0,  64 * 1024, 128, 0) },
        { "s25fl016k",  INFO(0xef4015,      0,  64 * 1024,  32, SECT_4K) },
        { "s25fl064k",  INFO(0xef4017,      0,  64 * 1024, 128, SECT_4K) },
 
@@ -699,6 +708,7 @@ static const struct spi_device_id m25p_ids[] = {
        { "m25p32",  INFO(0x202016,  0,  64 * 1024,  64, 0) },
        { "m25p64",  INFO(0x202017,  0,  64 * 1024, 128, 0) },
        { "m25p128", INFO(0x202018,  0, 256 * 1024,  64, 0) },
+       { "n25q032", INFO(0x20ba16,  0,  64 * 1024,  64, 0) },
 
        { "m25p05-nonjedec",  INFO(0, 0,  32 * 1024,   2, 0) },
        { "m25p10-nonjedec",  INFO(0, 0,  32 * 1024,   4, 0) },
@@ -714,6 +724,7 @@ static const struct spi_device_id m25p_ids[] = {
        { "m45pe80", INFO(0x204014,  0, 64 * 1024,   16, 0) },
        { "m45pe16", INFO(0x204015,  0, 64 * 1024,   32, 0) },
 
+       { "m25pe20", INFO(0x208012,  0, 64 * 1024,  4,       0) },
        { "m25pe80", INFO(0x208014,  0, 64 * 1024, 16,       0) },
        { "m25pe16", INFO(0x208015,  0, 64 * 1024, 32, SECT_4K) },
 
@@ -730,6 +741,7 @@ static const struct spi_device_id m25p_ids[] = {
        { "w25x16", INFO(0xef3015, 0, 64 * 1024,  32, SECT_4K) },
        { "w25x32", INFO(0xef3016, 0, 64 * 1024,  64, SECT_4K) },
        { "w25q32", INFO(0xef4016, 0, 64 * 1024,  64, SECT_4K) },
+       { "w25q32dw", INFO(0xef6016, 0, 64 * 1024,  64, SECT_4K) },
        { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
        { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
        { "w25q80", INFO(0xef5014, 0, 64 * 1024,  16, SECT_4K) },
index 67960362681e7f7a72933aaf87b5ffa515c36cfa..dcc3c9511530c064e93d91f941e90023a81fc3d3 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/param.h>
 #include <linux/platform_device.h>
+#include <linux/pm.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/spear_smi.h>
@@ -240,8 +241,8 @@ static int spear_smi_read_sr(struct spear_smi *dev, u32 bank)
        /* copy dev->status (lower 16 bits) in order to release lock */
        if (ret > 0)
                ret = dev->status & 0xffff;
-       else
-               ret = -EIO;
+       else if (ret == 0)
+               ret = -ETIMEDOUT;
 
        /* restore the ctrl regs state */
        writel(ctrlreg1, dev->io_base + SMI_CR1);
@@ -269,16 +270,19 @@ static int spear_smi_wait_till_ready(struct spear_smi *dev, u32 bank,
        finish = jiffies + timeout;
        do {
                status = spear_smi_read_sr(dev, bank);
-               if (status < 0)
-                       continue; /* try till timeout */
-               else if (!(status & SR_WIP))
+               if (status < 0) {
+                       if (status == -ETIMEDOUT)
+                               continue; /* try till finish */
+                       return status;
+               } else if (!(status & SR_WIP)) {
                        return 0;
+               }
 
                cond_resched();
        } while (!time_after_eq(jiffies, finish));
 
        dev_err(&dev->pdev->dev, "smi controller is busy, timeout\n");
-       return status;
+       return -EBUSY;
 }
 
 /**
@@ -335,6 +339,9 @@ static void spear_smi_hw_init(struct spear_smi *dev)
        val = HOLD1 | BANK_EN | DSEL_TIME | (prescale << 8);
 
        mutex_lock(&dev->lock);
+       /* clear all interrupt conditions */
+       writel(0, dev->io_base + SMI_SR);
+
        writel(val, dev->io_base + SMI_CR1);
        mutex_unlock(&dev->lock);
 }
@@ -391,11 +398,11 @@ static int spear_smi_write_enable(struct spear_smi *dev, u32 bank)
        writel(ctrlreg1, dev->io_base + SMI_CR1);
        writel(0, dev->io_base + SMI_CR2);
 
-       if (ret <= 0) {
+       if (ret == 0) {
                ret = -EIO;
                dev_err(&dev->pdev->dev,
                        "smi controller failed on write enable\n");
-       } else {
+       } else if (ret > 0) {
                /* check whether write mode status is set for required bank */
                if (dev->status & (1 << (bank + WM_SHIFT)))
                        ret = 0;
@@ -462,10 +469,10 @@ static int spear_smi_erase_sector(struct spear_smi *dev,
        ret = wait_event_interruptible_timeout(dev->cmd_complete,
                        dev->status & TFF, SMI_CMD_TIMEOUT);
 
-       if (ret <= 0) {
+       if (ret == 0) {
                ret = -EIO;
                dev_err(&dev->pdev->dev, "sector erase failed\n");
-       } else
+       } else if (ret > 0)
                ret = 0; /* success */
 
        /* restore ctrl regs */
@@ -820,7 +827,7 @@ static int spear_smi_setup_banks(struct platform_device *pdev,
        if (!flash_info)
                return -ENODEV;
 
-       flash = kzalloc(sizeof(*flash), GFP_ATOMIC);
+       flash = devm_kzalloc(&pdev->dev, sizeof(*flash), GFP_ATOMIC);
        if (!flash)
                return -ENOMEM;
        flash->bank = bank;
@@ -831,15 +838,13 @@ static int spear_smi_setup_banks(struct platform_device *pdev,
        flash_index = spear_smi_probe_flash(dev, bank);
        if (flash_index < 0) {
                dev_info(&dev->pdev->dev, "smi-nor%d not found\n", bank);
-               ret = flash_index;
-               goto err_probe;
+               return flash_index;
        }
        /* map the memory for nor flash chip */
-       flash->base_addr = ioremap(flash_info->mem_base, flash_info->size);
-       if (!flash->base_addr) {
-               ret = -EIO;
-               goto err_probe;
-       }
+       flash->base_addr = devm_ioremap(&pdev->dev, flash_info->mem_base,
+                                       flash_info->size);
+       if (!flash->base_addr)
+               return -EIO;
 
        dev->flash[bank] = flash;
        flash->mtd.priv = dev;
@@ -881,17 +886,10 @@ static int spear_smi_setup_banks(struct platform_device *pdev,
                                        count);
        if (ret) {
                dev_err(&dev->pdev->dev, "Err MTD partition=%d\n", ret);
-               goto err_map;
+               return ret;
        }
 
        return 0;
-
-err_map:
-       iounmap(flash->base_addr);
-
-err_probe:
-       kfree(flash);
-       return ret;
 }
 
 /**
@@ -928,20 +926,13 @@ static int __devinit spear_smi_probe(struct platform_device *pdev)
                }
        } else {
                pdata = dev_get_platdata(&pdev->dev);
-               if (pdata < 0) {
+               if (!pdata) {
                        ret = -ENODEV;
                        dev_err(&pdev->dev, "no platform data\n");
                        goto err;
                }
        }
 
-       smi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!smi_base) {
-               ret = -ENODEV;
-               dev_err(&pdev->dev, "invalid smi base address\n");
-               goto err;
-       }
-
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                ret = -ENODEV;
@@ -949,32 +940,26 @@ static int __devinit spear_smi_probe(struct platform_device *pdev)
                goto err;
        }
 
-       dev = kzalloc(sizeof(*dev), GFP_ATOMIC);
+       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_ATOMIC);
        if (!dev) {
                ret = -ENOMEM;
                dev_err(&pdev->dev, "mem alloc fail\n");
                goto err;
        }
 
-       smi_base = request_mem_region(smi_base->start, resource_size(smi_base),
-                       pdev->name);
-       if (!smi_base) {
-               ret = -EBUSY;
-               dev_err(&pdev->dev, "request mem region fail\n");
-               goto err_mem;
-       }
+       smi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-       dev->io_base = ioremap(smi_base->start, resource_size(smi_base));
+       dev->io_base = devm_request_and_ioremap(&pdev->dev, smi_base);
        if (!dev->io_base) {
                ret = -EIO;
-               dev_err(&pdev->dev, "ioremap fail\n");
-               goto err_ioremap;
+               dev_err(&pdev->dev, "devm_request_and_ioremap fail\n");
+               goto err;
        }
 
        dev->pdev = pdev;
        dev->clk_rate = pdata->clk_rate;
 
-       if (dev->clk_rate < 0 || dev->clk_rate > SMI_MAX_CLOCK_FREQ)
+       if (dev->clk_rate > SMI_MAX_CLOCK_FREQ)
                dev->clk_rate = SMI_MAX_CLOCK_FREQ;
 
        dev->num_flashes = pdata->num_flashes;
@@ -984,17 +969,18 @@ static int __devinit spear_smi_probe(struct platform_device *pdev)
                dev->num_flashes = MAX_NUM_FLASH_CHIP;
        }
 
-       dev->clk = clk_get(&pdev->dev, NULL);
+       dev->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(dev->clk)) {
                ret = PTR_ERR(dev->clk);
-               goto err_clk;
+               goto err;
        }
 
        ret = clk_prepare_enable(dev->clk);
        if (ret)
-               goto err_clk_prepare_enable;
+               goto err;
 
-       ret = request_irq(irq, spear_smi_int_handler, 0, pdev->name, dev);
+       ret = devm_request_irq(&pdev->dev, irq, spear_smi_int_handler, 0,
+                              pdev->name, dev);
        if (ret) {
                dev_err(&dev->pdev->dev, "SMI IRQ allocation failed\n");
                goto err_irq;
@@ -1017,18 +1003,9 @@ static int __devinit spear_smi_probe(struct platform_device *pdev)
        return 0;
 
 err_bank_setup:
-       free_irq(irq, dev);
        platform_set_drvdata(pdev, NULL);
 err_irq:
        clk_disable_unprepare(dev->clk);
-err_clk_prepare_enable:
-       clk_put(dev->clk);
-err_clk:
-       iounmap(dev->io_base);
-err_ioremap:
-       release_mem_region(smi_base->start, resource_size(smi_base));
-err_mem:
-       kfree(dev);
 err:
        return ret;
 }
@@ -1042,11 +1019,8 @@ err:
 static int __devexit spear_smi_remove(struct platform_device *pdev)
 {
        struct spear_smi *dev;
-       struct spear_smi_plat_data *pdata;
        struct spear_snor_flash *flash;
-       struct resource *smi_base;
-       int ret;
-       int i, irq;
+       int ret, i;
 
        dev = platform_get_drvdata(pdev);
        if (!dev) {
@@ -1054,8 +1028,6 @@ static int __devexit spear_smi_remove(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       pdata = dev_get_platdata(&pdev->dev);
-
        /* clean up for all nor flash */
        for (i = 0; i < dev->num_flashes; i++) {
                flash = dev->flash[i];
@@ -1066,49 +1038,41 @@ static int __devexit spear_smi_remove(struct platform_device *pdev)
                ret = mtd_device_unregister(&flash->mtd);
                if (ret)
                        dev_err(&pdev->dev, "error removing mtd\n");
-
-               iounmap(flash->base_addr);
-               kfree(flash);
        }
 
-       irq = platform_get_irq(pdev, 0);
-       free_irq(irq, dev);
-
        clk_disable_unprepare(dev->clk);
-       clk_put(dev->clk);
-       iounmap(dev->io_base);
-       kfree(dev);
-
-       smi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(smi_base->start, resource_size(smi_base));
        platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
 
-int spear_smi_suspend(struct platform_device *pdev, pm_message_t state)
+#ifdef CONFIG_PM
+static int spear_smi_suspend(struct device *dev)
 {
-       struct spear_smi *dev = platform_get_drvdata(pdev);
+       struct spear_smi *sdev = dev_get_drvdata(dev);
 
-       if (dev && dev->clk)
-               clk_disable_unprepare(dev->clk);
+       if (sdev && sdev->clk)
+               clk_disable_unprepare(sdev->clk);
 
        return 0;
 }
 
-int spear_smi_resume(struct platform_device *pdev)
+static int spear_smi_resume(struct device *dev)
 {
-       struct spear_smi *dev = platform_get_drvdata(pdev);
+       struct spear_smi *sdev = dev_get_drvdata(dev);
        int ret = -EPERM;
 
-       if (dev && dev->clk)
-               ret = clk_prepare_enable(dev->clk);
+       if (sdev && sdev->clk)
+               ret = clk_prepare_enable(sdev->clk);
 
        if (!ret)
-               spear_smi_hw_init(dev);
+               spear_smi_hw_init(sdev);
        return ret;
 }
 
+static SIMPLE_DEV_PM_OPS(spear_smi_pm_ops, spear_smi_suspend, spear_smi_resume);
+#endif
+
 #ifdef CONFIG_OF
 static const struct of_device_id spear_smi_id_table[] = {
        { .compatible = "st,spear600-smi" },
@@ -1123,11 +1087,12 @@ static struct platform_driver spear_smi_driver = {
                .bus = &platform_bus_type,
                .owner = THIS_MODULE,
                .of_match_table = of_match_ptr(spear_smi_id_table),
+#ifdef CONFIG_PM
+               .pm = &spear_smi_pm_ops,
+#endif
        },
        .probe = spear_smi_probe,
        .remove = __devexit_p(spear_smi_remove),
-       .suspend = spear_smi_suspend,
-       .resume = spear_smi_resume,
 };
 
 static int spear_smi_init(void)
index 5ba2458e799ac4e3db5d8d78b7c9b4814bec5a09..2e47c2ed0a2da80778d1653d9d072a4b1170d26e 100644 (file)
@@ -373,7 +373,7 @@ config MTD_FORTUNET
          have such a board, say 'Y'.
 
 config MTD_AUTCPU12
-       tristate "NV-RAM mapping AUTCPU12 board"
+       bool "NV-RAM mapping AUTCPU12 board"
        depends on ARCH_AUTCPU12
        help
          This enables access to the NV-RAM on autronix autcpu12 board.
@@ -443,22 +443,10 @@ config MTD_GPIO_ADDR
 
 config MTD_UCLINUX
        bool "Generic uClinux RAM/ROM filesystem support"
-       depends on MTD_RAM=y && !MMU
+       depends on MTD_RAM=y && (!MMU || COLDFIRE)
        help
          Map driver to support image based filesystems for uClinux.
 
-config MTD_WRSBC8260
-       tristate "Map driver for WindRiver PowerQUICC II MPC82xx board"
-       depends on (SBC82xx || SBC8560)
-       select MTD_MAP_BANK_WIDTH_4
-       select MTD_MAP_BANK_WIDTH_1
-       select MTD_CFI_I1
-       select MTD_CFI_I4
-       help
-         Map driver for WindRiver PowerQUICC II MPC82xx board. Drives
-         all three flash regions on CS0, CS1 and CS6 if they are configured
-         correctly by the boot loader.
-
 config MTD_DMV182
         tristate "Map driver for Dy-4 SVME/DMV-182 board."
         depends on DMV182
index 68a9a91d344fbc65974e5978fb6ee4d6a7ee113e..deb43e9a1e7f1d929f13afb2d9a90f3299c3dddb 100644 (file)
@@ -47,7 +47,6 @@ obj-$(CONFIG_MTD_SCB2_FLASH)  += scb2_flash.o
 obj-$(CONFIG_MTD_H720X)                += h720x-flash.o
 obj-$(CONFIG_MTD_IXP4XX)       += ixp4xx.o
 obj-$(CONFIG_MTD_IXP2000)      += ixp2000.o
-obj-$(CONFIG_MTD_WRSBC8260)    += wr_sbc82xx_flash.o
 obj-$(CONFIG_MTD_DMV182)       += dmv182.o
 obj-$(CONFIG_MTD_PLATRAM)      += plat-ram.o
 obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o
index e5bfd0e093bb1e20e0336f84e69eb7058dc7a822..76fb594bb1d9cd2629c1b80d08a04e7d5b28a92b 100644 (file)
  * 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
- *
  */
+#include <linux/sizes.h>
 
-#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/ioport.h>
 #include <linux/init.h>
-#include <asm/io.h>
-#include <asm/sizes.h>
-#include <mach/hardware.h>
-#include <mach/autcpu12.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-
-static struct mtd_info *sram_mtd;
 
-struct map_info autcpu12_sram_map = {
-       .name = "SRAM",
-       .size = 32768,
-       .bankwidth = 4,
-       .phys = 0x12000000,
+struct autcpu12_nvram_priv {
+       struct mtd_info *mtd;
+       struct map_info map;
 };
 
-static int __init init_autcpu12_sram (void)
+static int __devinit autcpu12_nvram_probe(struct platform_device *pdev)
 {
-       int err, save0, save1;
+       map_word tmp, save0, save1;
+       struct resource *res;
+       struct autcpu12_nvram_priv *priv;
 
-       autcpu12_sram_map.virt = ioremap(0x12000000, SZ_128K);
-       if (!autcpu12_sram_map.virt) {
-               printk("Failed to ioremap autcpu12 NV-RAM space\n");
-               err = -EIO;
-               goto out;
+       priv = devm_kzalloc(&pdev->dev,
+                           sizeof(struct autcpu12_nvram_priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, priv);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "failed to get memory resource\n");
+               return -ENOENT;
+       }
+
+       priv->map.bankwidth     = 4;
+       priv->map.phys          = res->start;
+       priv->map.size          = resource_size(res);
+       priv->map.virt          = devm_request_and_ioremap(&pdev->dev, res);
+       strcpy((char *)priv->map.name, res->name);
+       if (!priv->map.virt) {
+               dev_err(&pdev->dev, "failed to remap mem resource\n");
+               return -EBUSY;
        }
-       simple_map_init(&autcpu_sram_map);
+
+       simple_map_init(&priv->map);
 
        /*
         * Check for 32K/128K
@@ -61,65 +72,59 @@ static int __init init_autcpu12_sram (void)
         * Read and check result on ofs 0x0
         * Restore contents
         */
-       save0 = map_read32(&autcpu12_sram_map,0);
-       save1 = map_read32(&autcpu12_sram_map,0x10000);
-       map_write32(&autcpu12_sram_map,~save0,0x10000);
-       /* if we find this pattern on 0x0, we have 32K size
-        * restore contents and exit
-        */
-       if ( map_read32(&autcpu12_sram_map,0) != save0) {
-               map_write32(&autcpu12_sram_map,save0,0x0);
-               goto map;
+       save0 = map_read(&priv->map, 0);
+       save1 = map_read(&priv->map, 0x10000);
+       tmp.x[0] = ~save0.x[0];
+       map_write(&priv->map, tmp, 0x10000);
+       tmp = map_read(&priv->map, 0);
+       /* if we find this pattern on 0x0, we have 32K size */
+       if (!map_word_equal(&priv->map, tmp, save0)) {
+               map_write(&priv->map, save0, 0x0);
+               priv->map.size = SZ_32K;
+       } else
+               map_write(&priv->map, save1, 0x10000);
+
+       priv->mtd = do_map_probe("map_ram", &priv->map);
+       if (!priv->mtd) {
+               dev_err(&pdev->dev, "probing failed\n");
+               return -ENXIO;
        }
-       /* We have a 128K found, restore 0x10000 and set size
-        * to 128K
-        */
-       map_write32(&autcpu12_sram_map,save1,0x10000);
-       autcpu12_sram_map.size = SZ_128K;
-
-map:
-       sram_mtd = do_map_probe("map_ram", &autcpu12_sram_map);
-       if (!sram_mtd) {
-               printk("NV-RAM probe failed\n");
-               err = -ENXIO;
-               goto out_ioremap;
-       }
-
-       sram_mtd->owner = THIS_MODULE;
-       sram_mtd->erasesize = 16;
 
-       if (mtd_device_register(sram_mtd, NULL, 0)) {
-               printk("NV-RAM device addition failed\n");
-               err = -ENOMEM;
-               goto out_probe;
+       priv->mtd->owner        = THIS_MODULE;
+       priv->mtd->erasesize    = 16;
+       priv->mtd->dev.parent   = &pdev->dev;
+       if (!mtd_device_register(priv->mtd, NULL, 0)) {
+               dev_info(&pdev->dev,
+                        "NV-RAM device size %ldKiB registered on AUTCPU12\n",
+                        priv->map.size / SZ_1K);
+               return 0;
        }
 
-       printk("NV-RAM device size %ldKiB registered on AUTCPU12\n",autcpu12_sram_map.size/SZ_1K);
-
-       return 0;
-
-out_probe:
-       map_destroy(sram_mtd);
-       sram_mtd = 0;
-
-out_ioremap:
-       iounmap((void *)autcpu12_sram_map.virt);
-out:
-       return err;
+       map_destroy(priv->mtd);
+       dev_err(&pdev->dev, "NV-RAM device addition failed\n");
+       return -ENOMEM;
 }
 
-static void __exit cleanup_autcpu12_maps(void)
+static int __devexit autcpu12_nvram_remove(struct platform_device *pdev)
 {
-       if (sram_mtd) {
-               mtd_device_unregister(sram_mtd);
-               map_destroy(sram_mtd);
-               iounmap((void *)autcpu12_sram_map.virt);
-       }
+       struct autcpu12_nvram_priv *priv = platform_get_drvdata(pdev);
+
+       mtd_device_unregister(priv->mtd);
+       map_destroy(priv->mtd);
+
+       return 0;
 }
 
-module_init(init_autcpu12_sram);
-module_exit(cleanup_autcpu12_maps);
+static struct platform_driver autcpu12_nvram_driver = {
+       .driver         = {
+               .name   = "autcpu12_nvram",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = autcpu12_nvram_probe,
+       .remove         = __devexit_p(autcpu12_nvram_remove),
+};
+module_platform_driver(autcpu12_nvram_driver);
 
 MODULE_AUTHOR("Thomas Gleixner");
-MODULE_DESCRIPTION("autcpu12 NV-RAM map driver");
+MODULE_DESCRIPTION("autcpu12 NVRAM map driver");
 MODULE_LICENSE("GPL");
index f14ce0af763f0dda66a831470319e23611152eb2..1c30c1a307f409dbf5ead47994bc7d0636958c42 100644 (file)
@@ -43,26 +43,14 @@ static map_word mtd_pci_read8(struct map_info *_map, unsigned long ofs)
        struct map_pci_info *map = (struct map_pci_info *)_map;
        map_word val;
        val.x[0]= readb(map->base + map->translate(map, ofs));
-//     printk("read8 : %08lx => %02x\n", ofs, val.x[0]);
        return val;
 }
 
-#if 0
-static map_word mtd_pci_read16(struct map_info *_map, unsigned long ofs)
-{
-       struct map_pci_info *map = (struct map_pci_info *)_map;
-       map_word val;
-       val.x[0] = readw(map->base + map->translate(map, ofs));
-//     printk("read16: %08lx => %04x\n", ofs, val.x[0]);
-       return val;
-}
-#endif
 static map_word mtd_pci_read32(struct map_info *_map, unsigned long ofs)
 {
        struct map_pci_info *map = (struct map_pci_info *)_map;
        map_word val;
        val.x[0] = readl(map->base + map->translate(map, ofs));
-//     printk("read32: %08lx => %08x\n", ofs, val.x[0]);
        return val;
 }
 
@@ -75,22 +63,12 @@ static void mtd_pci_copyfrom(struct map_info *_map, void *to, unsigned long from
 static void mtd_pci_write8(struct map_info *_map, map_word val, unsigned long ofs)
 {
        struct map_pci_info *map = (struct map_pci_info *)_map;
-//     printk("write8 : %08lx <= %02x\n", ofs, val.x[0]);
        writeb(val.x[0], map->base + map->translate(map, ofs));
 }
 
-#if 0
-static void mtd_pci_write16(struct map_info *_map, map_word val, unsigned long ofs)
-{
-       struct map_pci_info *map = (struct map_pci_info *)_map;
-//     printk("write16: %08lx <= %04x\n", ofs, val.x[0]);
-       writew(val.x[0], map->base + map->translate(map, ofs));
-}
-#endif
 static void mtd_pci_write32(struct map_info *_map, map_word val, unsigned long ofs)
 {
        struct map_pci_info *map = (struct map_pci_info *)_map;
-//     printk("write32: %08lx <= %08x\n", ofs, val.x[0]);
        writel(val.x[0], map->base + map->translate(map, ofs));
 }
 
@@ -358,4 +336,3 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
 MODULE_DESCRIPTION("Generic PCI map driver");
 MODULE_DEVICE_TABLE(pci, mtd_pci_ids);
-
index 2e6fb6831d553802400862b3ed0356e864405ab9..6f19acadb06c97a521c29735de6813080bf626ed 100644 (file)
@@ -169,6 +169,7 @@ static int __devinit of_flash_probe(struct platform_device *dev)
        struct mtd_info **mtd_list = NULL;
        resource_size_t res_size;
        struct mtd_part_parser_data ppdata;
+       bool map_indirect;
 
        match = of_match_device(of_flash_match, &dev->dev);
        if (!match)
@@ -192,6 +193,8 @@ static int __devinit of_flash_probe(struct platform_device *dev)
        }
        count /= reg_tuple_size;
 
+       map_indirect = of_property_read_bool(dp, "no-unaligned-direct-access");
+
        err = -ENOMEM;
        info = kzalloc(sizeof(struct of_flash) +
                       sizeof(struct of_flash_list) * count, GFP_KERNEL);
@@ -247,6 +250,17 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 
                simple_map_init(&info->list[i].map);
 
+               /*
+                * On some platforms (e.g. MPC5200) a direct 1:1 mapping
+                * may cause problems with JFFS2 usage, as the local bus (LPB)
+                * doesn't support unaligned accesses as implemented in the
+                * JFFS2 code via memcpy(). By setting NO_XIP, the
+                * flash will not be exposed directly to the MTD users
+                * (e.g. JFFS2) any more.
+                */
+               if (map_indirect)
+                       info->list[i].map.phys = NO_XIP;
+
                if (probe_type) {
                        info->list[i].mtd = do_map_probe(probe_type,
                                                         &info->list[i].map);
index 6f52e1f288b674074f3045667c35678a09cb6f98..49c3fe715eee155cfc7519f5327e5f03640bd3be 100644 (file)
@@ -100,8 +100,6 @@ static int rbtx4939_flash_probe(struct platform_device *dev)
                goto err_out;
        }
        info->mtd->owner = THIS_MODULE;
-       if (err)
-               goto err_out;
        err = mtd_device_parse_register(info->mtd, NULL, NULL, pdata->parts,
                                        pdata->nr_parts);
 
index c3bb304eca076ffab133b7cd1e6a363a0763dfaa..299bf88a6f4112220c0fda6766878646c5ad0143 100644 (file)
@@ -67,10 +67,16 @@ static int __init uclinux_mtd_init(void)
        printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
                (int) mapp->phys, (int) mapp->size);
 
-       mapp->virt = ioremap_nocache(mapp->phys, mapp->size);
+       /*
+        * The filesystem is guaranteed to be in direct mapped memory. It is
+        * directly following the kernels own bss region. Following the same
+        * mechanism used by architectures setting up traditional initrds we
+        * use phys_to_virt to get the virtual address of its start.
+        */
+       mapp->virt = phys_to_virt(mapp->phys);
 
        if (mapp->virt == 0) {
-               printk("uclinux[mtd]: ioremap_nocache() failed\n");
+               printk("uclinux[mtd]: no virtual mapping?\n");
                return(-EIO);
        }
 
@@ -79,7 +85,6 @@ static int __init uclinux_mtd_init(void)
        mtd = do_map_probe("map_ram", mapp);
        if (!mtd) {
                printk("uclinux[mtd]: failed to find a mapping?\n");
-               iounmap(mapp->virt);
                return(-ENXIO);
        }
 
@@ -102,10 +107,8 @@ static void __exit uclinux_mtd_cleanup(void)
                map_destroy(uclinux_ram_mtdinfo);
                uclinux_ram_mtdinfo = NULL;
        }
-       if (uclinux_ram_map.virt) {
-               iounmap((void *) uclinux_ram_map.virt);
+       if (uclinux_ram_map.virt)
                uclinux_ram_map.virt = 0;
-       }
 }
 
 /****************************************************************************/
diff --git a/drivers/mtd/maps/wr_sbc82xx_flash.c b/drivers/mtd/maps/wr_sbc82xx_flash.c
deleted file mode 100644 (file)
index e7534c8..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Map for flash chips on Wind River PowerQUICC II SBC82xx board.
- *
- * Copyright (C) 2004 Red Hat, Inc.
- *
- * Author: David Woodhouse <dwmw2@infradead.org>
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/immap_cpm2.h>
-
-static struct mtd_info *sbcmtd[3];
-
-struct map_info sbc82xx_flash_map[3] = {
-       {.name = "Boot flash"},
-       {.name = "Alternate boot flash"},
-       {.name = "User flash"}
-};
-
-static struct mtd_partition smallflash_parts[] = {
-       {
-               .name =         "space",
-               .size =         0x100000,
-               .offset =       0,
-       }, {
-               .name =         "bootloader",
-               .size =         MTDPART_SIZ_FULL,
-               .offset =       MTDPART_OFS_APPEND,
-       }
-};
-
-static struct mtd_partition bigflash_parts[] = {
-       {
-               .name =         "bootloader",
-               .size =         0x00100000,
-               .offset =       0,
-       }, {
-               .name =         "file system",
-               .size =         0x01f00000,
-               .offset =       MTDPART_OFS_APPEND,
-       }, {
-               .name =         "boot config",
-               .size =         0x00100000,
-               .offset =       MTDPART_OFS_APPEND,
-       }, {
-               .name =         "space",
-               .size =         0x01f00000,
-               .offset =       MTDPART_OFS_APPEND,
-       }
-};
-
-static const char *part_probes[] __initconst = {"cmdlinepart", "RedBoot", NULL};
-
-#define init_sbc82xx_one_flash(map, br, or)                    \
-do {                                                           \
-       (map).phys = (br & 1) ? (br & 0xffff8000) : 0;          \
-       (map).size = (br & 1) ? (~(or & 0xffff8000) + 1) : 0;   \
-       switch (br & 0x00001800) {                              \
-       case 0x00000000:                                        \
-       case 0x00000800:        (map).bankwidth = 1;    break;  \
-       case 0x00001000:        (map).bankwidth = 2;    break;  \
-       case 0x00001800:        (map).bankwidth = 4;    break;  \
-       }                                                       \
-} while (0);
-
-static int __init init_sbc82xx_flash(void)
-{
-       volatile memctl_cpm2_t *mc = &cpm2_immr->im_memctl;
-       int bigflash;
-       int i;
-
-#ifdef CONFIG_SBC8560
-       mc = ioremap(0xff700000 + 0x5000, sizeof(memctl_cpm2_t));
-#else
-       mc = &cpm2_immr->im_memctl;
-#endif
-
-       bigflash = 1;
-       if ((mc->memc_br0 & 0x00001800) == 0x00001800)
-               bigflash = 0;
-
-       init_sbc82xx_one_flash(sbc82xx_flash_map[0], mc->memc_br0, mc->memc_or0);
-       init_sbc82xx_one_flash(sbc82xx_flash_map[1], mc->memc_br6, mc->memc_or6);
-       init_sbc82xx_one_flash(sbc82xx_flash_map[2], mc->memc_br1, mc->memc_or1);
-
-#ifdef CONFIG_SBC8560
-       iounmap((void *) mc);
-#endif
-
-       for (i=0; i<3; i++) {
-               int8_t flashcs[3] = { 0, 6, 1 };
-               int nr_parts;
-               struct mtd_partition *defparts;
-
-               printk(KERN_NOTICE "PowerQUICC II %s (%ld MiB on CS%d",
-                      sbc82xx_flash_map[i].name,
-                      (sbc82xx_flash_map[i].size >> 20),
-                      flashcs[i]);
-               if (!sbc82xx_flash_map[i].phys) {
-                       /* We know it can't be at zero. */
-                       printk("): disabled by bootloader.\n");
-                       continue;
-               }
-               printk(" at %08lx)\n",  sbc82xx_flash_map[i].phys);
-
-               sbc82xx_flash_map[i].virt = ioremap(sbc82xx_flash_map[i].phys,
-                                                   sbc82xx_flash_map[i].size);
-
-               if (!sbc82xx_flash_map[i].virt) {
-                       printk("Failed to ioremap\n");
-                       continue;
-               }
-
-               simple_map_init(&sbc82xx_flash_map[i]);
-
-               sbcmtd[i] = do_map_probe("cfi_probe", &sbc82xx_flash_map[i]);
-
-               if (!sbcmtd[i])
-                       continue;
-
-               sbcmtd[i]->owner = THIS_MODULE;
-
-               /* No partitioning detected. Use default */
-               if (i == 2) {
-                       defparts = NULL;
-                       nr_parts = 0;
-               } else if (i == bigflash) {
-                       defparts = bigflash_parts;
-                       nr_parts = ARRAY_SIZE(bigflash_parts);
-               } else {
-                       defparts = smallflash_parts;
-                       nr_parts = ARRAY_SIZE(smallflash_parts);
-               }
-
-               mtd_device_parse_register(sbcmtd[i], part_probes, NULL,
-                                         defparts, nr_parts);
-       }
-       return 0;
-}
-
-static void __exit cleanup_sbc82xx_flash(void)
-{
-       int i;
-
-       for (i=0; i<3; i++) {
-               if (!sbcmtd[i])
-                       continue;
-
-               mtd_device_unregister(sbcmtd[i]);
-
-               map_destroy(sbcmtd[i]);
-
-               iounmap((void *)sbc82xx_flash_map[i].virt);
-               sbc82xx_flash_map[i].virt = 0;
-       }
-}
-
-module_init(init_sbc82xx_flash);
-module_exit(cleanup_sbc82xx_flash);
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
-MODULE_DESCRIPTION("Flash map driver for WindRiver PowerQUICC II");
index 73ae81a629f274b0a81af26e0f32cd328a95a55a..82c06165d3d27351f3cebf9966b513b6669e96bf 100644 (file)
@@ -1162,7 +1162,11 @@ static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma)
        resource_size_t start, off;
        unsigned long len, vma_len;
 
-       if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) {
+        /* This is broken because it assumes the MTD device is map-based
+          and that mtd->priv is a valid struct map_info.  It should be
+          replaced with something that uses the mtd_get_unmapped_area()
+          operation properly. */
+       if (0 /*mtd->type == MTD_RAM || mtd->type == MTD_ROM*/) {
                off = get_vm_offset(vma);
                start = map->phys;
                len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size);
index b9adff543f5f1a755729958a2d490be1690ffa76..374c46dff7dd65d3aea7eef69b22a332d727ad0f 100644 (file)
@@ -858,6 +858,27 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 }
 EXPORT_SYMBOL_GPL(mtd_panic_write);
 
+int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
+{
+       int ret_code;
+       ops->retlen = ops->oobretlen = 0;
+       if (!mtd->_read_oob)
+               return -EOPNOTSUPP;
+       /*
+        * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics
+        * similar to mtd->_read(), returning a non-negative integer
+        * representing max bitflips. In other cases, mtd->_read_oob() may
+        * return -EUCLEAN. In all cases, perform similar logic to mtd_read().
+        */
+       ret_code = mtd->_read_oob(mtd, from, ops);
+       if (unlikely(ret_code < 0))
+               return ret_code;
+       if (mtd->ecc_strength == 0)
+               return 0;       /* device lacks ecc */
+       return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0;
+}
+EXPORT_SYMBOL_GPL(mtd_read_oob);
+
 /*
  * Method to access the protection register area, present in some flash
  * devices. The user data is one time programmable but the factory data is read
index 438737a1f59a3c882c5c6db3fade53696b341cd5..f5b3f91fa1cc4d8b885228e995b49ba4073629e9 100644 (file)
@@ -169,14 +169,7 @@ static void mtdoops_workfunc_erase(struct work_struct *work)
                        cxt->nextpage = 0;
        }
 
-       while (1) {
-               ret = mtd_block_isbad(mtd, cxt->nextpage * record_size);
-               if (!ret)
-                       break;
-               if (ret < 0) {
-                       printk(KERN_ERR "mtdoops: block_isbad failed, aborting\n");
-                       return;
-               }
+       while ((ret = mtd_block_isbad(mtd, cxt->nextpage * record_size)) > 0) {
 badblock:
                printk(KERN_WARNING "mtdoops: bad block at %08lx\n",
                       cxt->nextpage * record_size);
@@ -190,6 +183,11 @@ badblock:
                }
        }
 
+       if (ret < 0) {
+               printk(KERN_ERR "mtdoops: mtd_block_isbad failed, aborting\n");
+               return;
+       }
+
        for (j = 0, ret = -1; (j < 3) && (ret < 0); j++)
                ret = mtdoops_erase_block(cxt, cxt->nextpage * record_size);
 
index 3a49e6de5e603e2641acc86acb50025bde9b69a6..70fa70a8318f4584c473a7fabd35a7bc4fad6027 100644 (file)
@@ -711,6 +711,8 @@ static const char *default_mtd_part_types[] = {
  * partition parsers, specified in @types. However, if @types is %NULL, then
  * the default list of parsers is used. The default list contains only the
  * "cmdlinepart" and "ofpart" parsers ATM.
+ * Note: If there are more then one parser in @types, the kernel only takes the
+ * partitions parsed out by the first parser.
  *
  * This function may return:
  * o a negative error code in case of failure
@@ -735,11 +737,12 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
                if (!parser)
                        continue;
                ret = (*parser->parse_fn)(master, pparts, data);
+               put_partition_parser(parser);
                if (ret > 0) {
                        printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
                               ret, parser->name, master->name);
+                       break;
                }
-               put_partition_parser(parser);
        }
        return ret;
 }
index 598cd0a3adeeabf7953344bc95dc7898b0559abe..4883139460be90ba7385b059651f1a52bab608c5 100644 (file)
@@ -22,15 +22,6 @@ menuconfig MTD_NAND
 
 if MTD_NAND
 
-config MTD_NAND_VERIFY_WRITE
-       bool "Verify NAND page writes"
-       help
-         This adds an extra check when data is written to the flash. The
-         NAND flash device internally checks only bits transitioning
-         from 1 to 0. There is a rare possibility that even though the
-         device thinks the write was successful, a bit could have been
-         flipped accidentally due to device wear or something else.
-
 config MTD_NAND_BCH
        tristate
        select BCH
@@ -267,22 +258,6 @@ config MTD_NAND_S3C2410_CLKSTOP
          when the is NAND chip selected or released, but will save
          approximately 5mA of power when there is nothing happening.
 
-config MTD_NAND_BCM_UMI
-       tristate "NAND Flash support for BCM Reference Boards"
-       depends on ARCH_BCMRING
-       help
-         This enables the NAND flash controller on the BCM UMI block.
-
-         No board specific support is done by this driver, each board
-         must advertise a platform_device for the driver to attach.
-
-config MTD_NAND_BCM_UMI_HWCS
-       bool "BCM UMI NAND Hardware CS"
-       depends on MTD_NAND_BCM_UMI
-       help
-         Enable the use of the BCM UMI block's internal CS using NAND.
-         This should only be used if you know the external NAND CS can toggle.
-
 config MTD_NAND_DISKONCHIP
        tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)"
        depends on EXPERIMENTAL
@@ -356,7 +331,7 @@ config MTD_NAND_DISKONCHIP_BBTWRITE
 
 config MTD_NAND_DOCG4
        tristate "Support for DiskOnChip G4 (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       depends on EXPERIMENTAL && HAS_IOMEM
        select BCH
        select BITREVERSE
        help
@@ -414,6 +389,28 @@ config MTD_NAND_PXA3xx
          This enables the driver for the NAND flash device found on
          PXA3xx processors
 
+config MTD_NAND_SLC_LPC32XX
+       tristate "NXP LPC32xx SLC Controller"
+       depends on ARCH_LPC32XX
+       help
+         Enables support for NXP's LPC32XX SLC (i.e. for Single Level Cell
+         chips) NAND controller. This is the default for the PHYTEC 3250
+         reference board which contains a NAND256R3A2CZA6 chip.
+
+         Please check the actual NAND chip connected and its support
+         by the SLC NAND controller.
+
+config MTD_NAND_MLC_LPC32XX
+       tristate "NXP LPC32xx MLC Controller"
+       depends on ARCH_LPC32XX
+       help
+         Uses the LPC32XX MLC (i.e. for Multi Level Cell chips) NAND
+         controller. This is the default for the WORK92105 controller
+         board.
+
+         Please check the actual NAND chip connected and its support
+         by the MLC NAND controller.
+
 config MTD_NAND_CM_X270
        tristate "Support for NAND Flash on CM-X270 modules"
        depends on MACH_ARMCORE
@@ -439,10 +436,10 @@ config MTD_NAND_NANDSIM
          MTD nand layer.
 
 config MTD_NAND_GPMI_NAND
-        bool "GPMI NAND Flash Controller driver"
+        tristate "GPMI NAND Flash Controller driver"
         depends on MTD_NAND && MXS_DMA
         help
-        Enables NAND Flash support for IMX23 or IMX28.
+        Enables NAND Flash support for IMX23, IMX28 or IMX6.
         The GPMI controller is very powerful, with the help of BCH
         module, it can do the hardware ECC. The GPMI supports several
         NAND flashs at the same time. The GPMI may conflicts with other
@@ -510,7 +507,7 @@ config MTD_NAND_MPC5121_NFC
 
 config MTD_NAND_MXC
        tristate "MXC NAND support"
-       depends on IMX_HAVE_PLATFORM_MXC_NAND
+       depends on ARCH_MXC
        help
          This enables the driver for the NAND flash controller on the
          MXC processors.
@@ -567,4 +564,12 @@ config MTD_NAND_FSMC
          Enables support for NAND Flash chips on the ST Microelectronics
          Flexible Static Memory Controller (FSMC)
 
+config MTD_NAND_XWAY
+       tristate "Support for NAND on Lantiq XWAY SoC"
+       depends on LANTIQ && SOC_TYPE_XWAY
+       select MTD_NAND_PLATFORM
+       help
+         Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached
+         to the External Bus Unit (EBU).
+
 endif # MTD_NAND
index d4b4d8739bd8e88584e4b8f425d7cc9234b3e304..2cbd0916b733e67f5981541d0c29c6336a6b1678 100644 (file)
@@ -40,16 +40,18 @@ obj-$(CONFIG_MTD_NAND_ORION)                += orion_nand.o
 obj-$(CONFIG_MTD_NAND_FSL_ELBC)                += fsl_elbc_nand.o
 obj-$(CONFIG_MTD_NAND_FSL_IFC)         += fsl_ifc_nand.o
 obj-$(CONFIG_MTD_NAND_FSL_UPM)         += fsl_upm.o
+obj-$(CONFIG_MTD_NAND_SLC_LPC32XX)      += lpc32xx_slc.o
+obj-$(CONFIG_MTD_NAND_MLC_LPC32XX)      += lpc32xx_mlc.o
 obj-$(CONFIG_MTD_NAND_SH_FLCTL)                += sh_flctl.o
 obj-$(CONFIG_MTD_NAND_MXC)             += mxc_nand.o
 obj-$(CONFIG_MTD_NAND_SOCRATES)                += socrates_nand.o
 obj-$(CONFIG_MTD_NAND_TXX9NDFMC)       += txx9ndfmc.o
 obj-$(CONFIG_MTD_NAND_NUC900)          += nuc900_nand.o
 obj-$(CONFIG_MTD_NAND_NOMADIK)         += nomadik_nand.o
-obj-$(CONFIG_MTD_NAND_BCM_UMI)         += bcm_umi_nand.o nand_bcm_umi.o
 obj-$(CONFIG_MTD_NAND_MPC5121_NFC)     += mpc5121_nfc.o
 obj-$(CONFIG_MTD_NAND_RICOH)           += r852.o
 obj-$(CONFIG_MTD_NAND_JZ4740)          += jz4740_nand.o
 obj-$(CONFIG_MTD_NAND_GPMI_NAND)       += gpmi-nand/
+obj-$(CONFIG_MTD_NAND_XWAY)            += xway_nand.o
 
 nand-objs := nand_base.o nand_bbt.o
index a7040af08536746742c4705531a1f7122077330c..9e7723aa7acc0ea137d83e410ca27a52a0715aaf 100644 (file)
@@ -107,18 +107,6 @@ static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len)
                buf[i] = ams_delta_read_byte(mtd);
 }
 
-static int ams_delta_verify_buf(struct mtd_info *mtd, const u_char *buf,
-                               int len)
-{
-       int i;
-
-       for (i=0; i<len; i++)
-               if (buf[i] != ams_delta_read_byte(mtd))
-                       return -EFAULT;
-
-       return 0;
-}
-
 /*
  * Command control function
  *
@@ -237,7 +225,6 @@ static int __devinit ams_delta_init(struct platform_device *pdev)
        this->read_byte = ams_delta_read_byte;
        this->write_buf = ams_delta_write_buf;
        this->read_buf = ams_delta_read_buf;
-       this->verify_buf = ams_delta_verify_buf;
        this->cmd_ctrl = ams_delta_hwcontrol;
        if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) {
                this->dev_ready = ams_delta_nand_ready;
index 97ac6712bb1926c6ff8e31292cc3c362d4d53d9d..9144557833027ad4cf1eeae236239bfc4a0a1c3b 100644 (file)
@@ -1,20 +1,22 @@
 /*
- *  Copyright (C) 2003 Rick Bronson
+ *  Copyright Â© 2003 Rick Bronson
  *
  *  Derived from drivers/mtd/nand/autcpu12.c
- *      Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
+ *      Copyright Â© 2001 Thomas Gleixner (gleixner@autronix.de)
  *
  *  Derived from drivers/mtd/spia.c
- *      Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
+ *      Copyright Â© 2000 Steven J. Hill (sjhill@cotw.com)
  *
  *
  *  Add Hardware ECC support for AT91SAM9260 / AT91SAM9263
- *     Richard Genoud (richard.genoud@gmail.com), Adeneo Copyright (C) 2007
+ *     Richard Genoud (richard.genoud@gmail.com), Adeneo Copyright Â© 2007
  *
  *     Derived from Das U-Boot source code
  *                     (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c)
- *     (C) Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
+ *     Â© Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
  *
+ *  Add Programmable Multibit ECC support for various AT91 SoC
+ *     Â© Copyright 2012 ATMEL, Hong Xu
  *
  * 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
@@ -93,8 +95,36 @@ struct atmel_nand_host {
 
        struct completion       comp;
        struct dma_chan         *dma_chan;
+
+       bool                    has_pmecc;
+       u8                      pmecc_corr_cap;
+       u16                     pmecc_sector_size;
+       u32                     pmecc_lookup_table_offset;
+
+       int                     pmecc_bytes_per_sector;
+       int                     pmecc_sector_number;
+       int                     pmecc_degree;   /* Degree of remainders */
+       int                     pmecc_cw_len;   /* Length of codeword */
+
+       void __iomem            *pmerrloc_base;
+       void __iomem            *pmecc_rom_base;
+
+       /* lookup table for alpha_to and index_of */
+       void __iomem            *pmecc_alpha_to;
+       void __iomem            *pmecc_index_of;
+
+       /* data for pmecc computation */
+       int16_t                 *pmecc_partial_syn;
+       int16_t                 *pmecc_si;
+       int16_t                 *pmecc_smu;     /* Sigma table */
+       int16_t                 *pmecc_lmu;     /* polynomal order */
+       int                     *pmecc_mu;
+       int                     *pmecc_dmu;
+       int                     *pmecc_delta;
 };
 
+static struct nand_ecclayout atmel_pmecc_oobinfo;
+
 static int cpu_has_dma(void)
 {
        return cpu_is_at91sam9rl() || cpu_is_at91sam9g45();
@@ -287,6 +317,703 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
                atmel_write_buf8(mtd, buf, len);
 }
 
+/*
+ * Return number of ecc bytes per sector according to sector size and
+ * correction capability
+ *
+ * Following table shows what at91 PMECC supported:
+ * Correction Capability       Sector_512_bytes        Sector_1024_bytes
+ * =====================       ================        =================
+ *                2-bits                 4-bytes                  4-bytes
+ *                4-bits                 7-bytes                  7-bytes
+ *                8-bits                13-bytes                 14-bytes
+ *               12-bits                20-bytes                 21-bytes
+ *               24-bits                39-bytes                 42-bytes
+ */
+static int __devinit pmecc_get_ecc_bytes(int cap, int sector_size)
+{
+       int m = 12 + sector_size / 512;
+       return (m * cap + 7) / 8;
+}
+
+static void __devinit pmecc_config_ecc_layout(struct nand_ecclayout *layout,
+       int oobsize, int ecc_len)
+{
+       int i;
+
+       layout->eccbytes = ecc_len;
+
+       /* ECC will occupy the last ecc_len bytes continuously */
+       for (i = 0; i < ecc_len; i++)
+               layout->eccpos[i] = oobsize - ecc_len + i;
+
+       layout->oobfree[0].offset = 2;
+       layout->oobfree[0].length =
+               oobsize - ecc_len - layout->oobfree[0].offset;
+}
+
+static void __devinit __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host)
+{
+       int table_size;
+
+       table_size = host->pmecc_sector_size == 512 ?
+               PMECC_LOOKUP_TABLE_SIZE_512 : PMECC_LOOKUP_TABLE_SIZE_1024;
+
+       return host->pmecc_rom_base + host->pmecc_lookup_table_offset +
+                       table_size * sizeof(int16_t);
+}
+
+static void pmecc_data_free(struct atmel_nand_host *host)
+{
+       kfree(host->pmecc_partial_syn);
+       kfree(host->pmecc_si);
+       kfree(host->pmecc_lmu);
+       kfree(host->pmecc_smu);
+       kfree(host->pmecc_mu);
+       kfree(host->pmecc_dmu);
+       kfree(host->pmecc_delta);
+}
+
+static int __devinit pmecc_data_alloc(struct atmel_nand_host *host)
+{
+       const int cap = host->pmecc_corr_cap;
+
+       host->pmecc_partial_syn = kzalloc((2 * cap + 1) * sizeof(int16_t),
+                                       GFP_KERNEL);
+       host->pmecc_si = kzalloc((2 * cap + 1) * sizeof(int16_t), GFP_KERNEL);
+       host->pmecc_lmu = kzalloc((cap + 1) * sizeof(int16_t), GFP_KERNEL);
+       host->pmecc_smu = kzalloc((cap + 2) * (2 * cap + 1) * sizeof(int16_t),
+                                       GFP_KERNEL);
+       host->pmecc_mu = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL);
+       host->pmecc_dmu = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL);
+       host->pmecc_delta = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL);
+
+       if (host->pmecc_partial_syn &&
+                       host->pmecc_si &&
+                       host->pmecc_lmu &&
+                       host->pmecc_smu &&
+                       host->pmecc_mu &&
+                       host->pmecc_dmu &&
+                       host->pmecc_delta)
+               return 0;
+
+       /* error happened */
+       pmecc_data_free(host);
+       return -ENOMEM;
+}
+
+static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct atmel_nand_host *host = nand_chip->priv;
+       int i;
+       uint32_t value;
+
+       /* Fill odd syndromes */
+       for (i = 0; i < host->pmecc_corr_cap; i++) {
+               value = pmecc_readl_rem_relaxed(host->ecc, sector, i / 2);
+               if (i & 1)
+                       value >>= 16;
+               value &= 0xffff;
+               host->pmecc_partial_syn[(2 * i) + 1] = (int16_t)value;
+       }
+}
+
+static void pmecc_substitute(struct mtd_info *mtd)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct atmel_nand_host *host = nand_chip->priv;
+       int16_t __iomem *alpha_to = host->pmecc_alpha_to;
+       int16_t __iomem *index_of = host->pmecc_index_of;
+       int16_t *partial_syn = host->pmecc_partial_syn;
+       const int cap = host->pmecc_corr_cap;
+       int16_t *si;
+       int i, j;
+
+       /* si[] is a table that holds the current syndrome value,
+        * an element of that table belongs to the field
+        */
+       si = host->pmecc_si;
+
+       memset(&si[1], 0, sizeof(int16_t) * (2 * cap - 1));
+
+       /* Computation 2t syndromes based on S(x) */
+       /* Odd syndromes */
+       for (i = 1; i < 2 * cap; i += 2) {
+               for (j = 0; j < host->pmecc_degree; j++) {
+                       if (partial_syn[i] & ((unsigned short)0x1 << j))
+                               si[i] = readw_relaxed(alpha_to + i * j) ^ si[i];
+               }
+       }
+       /* Even syndrome = (Odd syndrome) ** 2 */
+       for (i = 2, j = 1; j <= cap; i = ++j << 1) {
+               if (si[j] == 0) {
+                       si[i] = 0;
+               } else {
+                       int16_t tmp;
+
+                       tmp = readw_relaxed(index_of + si[j]);
+                       tmp = (tmp * 2) % host->pmecc_cw_len;
+                       si[i] = readw_relaxed(alpha_to + tmp);
+               }
+       }
+
+       return;
+}
+
+static void pmecc_get_sigma(struct mtd_info *mtd)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct atmel_nand_host *host = nand_chip->priv;
+
+       int16_t *lmu = host->pmecc_lmu;
+       int16_t *si = host->pmecc_si;
+       int *mu = host->pmecc_mu;
+       int *dmu = host->pmecc_dmu;     /* Discrepancy */
+       int *delta = host->pmecc_delta; /* Delta order */
+       int cw_len = host->pmecc_cw_len;
+       const int16_t cap = host->pmecc_corr_cap;
+       const int num = 2 * cap + 1;
+       int16_t __iomem *index_of = host->pmecc_index_of;
+       int16_t __iomem *alpha_to = host->pmecc_alpha_to;
+       int i, j, k;
+       uint32_t dmu_0_count, tmp;
+       int16_t *smu = host->pmecc_smu;
+
+       /* index of largest delta */
+       int ro;
+       int largest;
+       int diff;
+
+       dmu_0_count = 0;
+
+       /* First Row */
+
+       /* Mu */
+       mu[0] = -1;
+
+       memset(smu, 0, sizeof(int16_t) * num);
+       smu[0] = 1;
+
+       /* discrepancy set to 1 */
+       dmu[0] = 1;
+       /* polynom order set to 0 */
+       lmu[0] = 0;
+       delta[0] = (mu[0] * 2 - lmu[0]) >> 1;
+
+       /* Second Row */
+
+       /* Mu */
+       mu[1] = 0;
+       /* Sigma(x) set to 1 */
+       memset(&smu[num], 0, sizeof(int16_t) * num);
+       smu[num] = 1;
+
+       /* discrepancy set to S1 */
+       dmu[1] = si[1];
+
+       /* polynom order set to 0 */
+       lmu[1] = 0;
+
+       delta[1] = (mu[1] * 2 - lmu[1]) >> 1;
+
+       /* Init the Sigma(x) last row */
+       memset(&smu[(cap + 1) * num], 0, sizeof(int16_t) * num);
+
+       for (i = 1; i <= cap; i++) {
+               mu[i + 1] = i << 1;
+               /* Begin Computing Sigma (Mu+1) and L(mu) */
+               /* check if discrepancy is set to 0 */
+               if (dmu[i] == 0) {
+                       dmu_0_count++;
+
+                       tmp = ((cap - (lmu[i] >> 1) - 1) / 2);
+                       if ((cap - (lmu[i] >> 1) - 1) & 0x1)
+                               tmp += 2;
+                       else
+                               tmp += 1;
+
+                       if (dmu_0_count == tmp) {
+                               for (j = 0; j <= (lmu[i] >> 1) + 1; j++)
+                                       smu[(cap + 1) * num + j] =
+                                                       smu[i * num + j];
+
+                               lmu[cap + 1] = lmu[i];
+                               return;
+                       }
+
+                       /* copy polynom */
+                       for (j = 0; j <= lmu[i] >> 1; j++)
+                               smu[(i + 1) * num + j] = smu[i * num + j];
+
+                       /* copy previous polynom order to the next */
+                       lmu[i + 1] = lmu[i];
+               } else {
+                       ro = 0;
+                       largest = -1;
+                       /* find largest delta with dmu != 0 */
+                       for (j = 0; j < i; j++) {
+                               if ((dmu[j]) && (delta[j] > largest)) {
+                                       largest = delta[j];
+                                       ro = j;
+                               }
+                       }
+
+                       /* compute difference */
+                       diff = (mu[i] - mu[ro]);
+
+                       /* Compute degree of the new smu polynomial */
+                       if ((lmu[i] >> 1) > ((lmu[ro] >> 1) + diff))
+                               lmu[i + 1] = lmu[i];
+                       else
+                               lmu[i + 1] = ((lmu[ro] >> 1) + diff) * 2;
+
+                       /* Init smu[i+1] with 0 */
+                       for (k = 0; k < num; k++)
+                               smu[(i + 1) * num + k] = 0;
+
+                       /* Compute smu[i+1] */
+                       for (k = 0; k <= lmu[ro] >> 1; k++) {
+                               int16_t a, b, c;
+
+                               if (!(smu[ro * num + k] && dmu[i]))
+                                       continue;
+                               a = readw_relaxed(index_of + dmu[i]);
+                               b = readw_relaxed(index_of + dmu[ro]);
+                               c = readw_relaxed(index_of + smu[ro * num + k]);
+                               tmp = a + (cw_len - b) + c;
+                               a = readw_relaxed(alpha_to + tmp % cw_len);
+                               smu[(i + 1) * num + (k + diff)] = a;
+                       }
+
+                       for (k = 0; k <= lmu[i] >> 1; k++)
+                               smu[(i + 1) * num + k] ^= smu[i * num + k];
+               }
+
+               /* End Computing Sigma (Mu+1) and L(mu) */
+               /* In either case compute delta */
+               delta[i + 1] = (mu[i + 1] * 2 - lmu[i + 1]) >> 1;
+
+               /* Do not compute discrepancy for the last iteration */
+               if (i >= cap)
+                       continue;
+
+               for (k = 0; k <= (lmu[i + 1] >> 1); k++) {
+                       tmp = 2 * (i - 1);
+                       if (k == 0) {
+                               dmu[i + 1] = si[tmp + 3];
+                       } else if (smu[(i + 1) * num + k] && si[tmp + 3 - k]) {
+                               int16_t a, b, c;
+                               a = readw_relaxed(index_of +
+                                               smu[(i + 1) * num + k]);
+                               b = si[2 * (i - 1) + 3 - k];
+                               c = readw_relaxed(index_of + b);
+                               tmp = a + c;
+                               tmp %= cw_len;
+                               dmu[i + 1] = readw_relaxed(alpha_to + tmp) ^
+                                       dmu[i + 1];
+                       }
+               }
+       }
+
+       return;
+}
+
+static int pmecc_err_location(struct mtd_info *mtd)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct atmel_nand_host *host = nand_chip->priv;
+       unsigned long end_time;
+       const int cap = host->pmecc_corr_cap;
+       const int num = 2 * cap + 1;
+       int sector_size = host->pmecc_sector_size;
+       int err_nbr = 0;        /* number of error */
+       int roots_nbr;          /* number of roots */
+       int i;
+       uint32_t val;
+       int16_t *smu = host->pmecc_smu;
+
+       pmerrloc_writel(host->pmerrloc_base, ELDIS, PMERRLOC_DISABLE);
+
+       for (i = 0; i <= host->pmecc_lmu[cap + 1] >> 1; i++) {
+               pmerrloc_writel_sigma_relaxed(host->pmerrloc_base, i,
+                                     smu[(cap + 1) * num + i]);
+               err_nbr++;
+       }
+
+       val = (err_nbr - 1) << 16;
+       if (sector_size == 1024)
+               val |= 1;
+
+       pmerrloc_writel(host->pmerrloc_base, ELCFG, val);
+       pmerrloc_writel(host->pmerrloc_base, ELEN,
+                       sector_size * 8 + host->pmecc_degree * cap);
+
+       end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS);
+       while (!(pmerrloc_readl_relaxed(host->pmerrloc_base, ELISR)
+                & PMERRLOC_CALC_DONE)) {
+               if (unlikely(time_after(jiffies, end_time))) {
+                       dev_err(host->dev, "PMECC: Timeout to calculate error location.\n");
+                       return -1;
+               }
+               cpu_relax();
+       }
+
+       roots_nbr = (pmerrloc_readl_relaxed(host->pmerrloc_base, ELISR)
+               & PMERRLOC_ERR_NUM_MASK) >> 8;
+       /* Number of roots == degree of smu hence <= cap */
+       if (roots_nbr == host->pmecc_lmu[cap + 1] >> 1)
+               return err_nbr - 1;
+
+       /* Number of roots does not match the degree of smu
+        * unable to correct error */
+       return -1;
+}
+
+static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
+               int sector_num, int extra_bytes, int err_nbr)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct atmel_nand_host *host = nand_chip->priv;
+       int i = 0;
+       int byte_pos, bit_pos, sector_size, pos;
+       uint32_t tmp;
+       uint8_t err_byte;
+
+       sector_size = host->pmecc_sector_size;
+
+       while (err_nbr) {
+               tmp = pmerrloc_readl_el_relaxed(host->pmerrloc_base, i) - 1;
+               byte_pos = tmp / 8;
+               bit_pos  = tmp % 8;
+
+               if (byte_pos >= (sector_size + extra_bytes))
+                       BUG();  /* should never happen */
+
+               if (byte_pos < sector_size) {
+                       err_byte = *(buf + byte_pos);
+                       *(buf + byte_pos) ^= (1 << bit_pos);
+
+                       pos = sector_num * host->pmecc_sector_size + byte_pos;
+                       dev_info(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
+                               pos, bit_pos, err_byte, *(buf + byte_pos));
+               } else {
+                       /* Bit flip in OOB area */
+                       tmp = sector_num * host->pmecc_bytes_per_sector
+                                       + (byte_pos - sector_size);
+                       err_byte = ecc[tmp];
+                       ecc[tmp] ^= (1 << bit_pos);
+
+                       pos = tmp + nand_chip->ecc.layout->eccpos[0];
+                       dev_info(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
+                               pos, bit_pos, err_byte, ecc[tmp]);
+               }
+
+               i++;
+               err_nbr--;
+       }
+
+       return;
+}
+
+static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf,
+       u8 *ecc)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct atmel_nand_host *host = nand_chip->priv;
+       int i, err_nbr, eccbytes;
+       uint8_t *buf_pos;
+
+       eccbytes = nand_chip->ecc.bytes;
+       for (i = 0; i < eccbytes; i++)
+               if (ecc[i] != 0xff)
+                       goto normal_check;
+       /* Erased page, return OK */
+       return 0;
+
+normal_check:
+       for (i = 0; i < host->pmecc_sector_number; i++) {
+               err_nbr = 0;
+               if (pmecc_stat & 0x1) {
+                       buf_pos = buf + i * host->pmecc_sector_size;
+
+                       pmecc_gen_syndrome(mtd, i);
+                       pmecc_substitute(mtd);
+                       pmecc_get_sigma(mtd);
+
+                       err_nbr = pmecc_err_location(mtd);
+                       if (err_nbr == -1) {
+                               dev_err(host->dev, "PMECC: Too many errors\n");
+                               mtd->ecc_stats.failed++;
+                               return -EIO;
+                       } else {
+                               pmecc_correct_data(mtd, buf_pos, ecc, i,
+                                       host->pmecc_bytes_per_sector, err_nbr);
+                               mtd->ecc_stats.corrected += err_nbr;
+                       }
+               }
+               pmecc_stat >>= 1;
+       }
+
+       return 0;
+}
+
+static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
+       struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
+{
+       struct atmel_nand_host *host = chip->priv;
+       int eccsize = chip->ecc.size;
+       uint8_t *oob = chip->oob_poi;
+       uint32_t *eccpos = chip->ecc.layout->eccpos;
+       uint32_t stat;
+       unsigned long end_time;
+
+       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
+       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
+       pmecc_writel(host->ecc, CFG, (pmecc_readl_relaxed(host->ecc, CFG)
+               & ~PMECC_CFG_WRITE_OP) | PMECC_CFG_AUTO_ENABLE);
+
+       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE);
+       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA);
+
+       chip->read_buf(mtd, buf, eccsize);
+       chip->read_buf(mtd, oob, mtd->oobsize);
+
+       end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS);
+       while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) {
+               if (unlikely(time_after(jiffies, end_time))) {
+                       dev_err(host->dev, "PMECC: Timeout to get error status.\n");
+                       return -EIO;
+               }
+               cpu_relax();
+       }
+
+       stat = pmecc_readl_relaxed(host->ecc, ISR);
+       if (stat != 0)
+               if (pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]) != 0)
+                       return -EIO;
+
+       return 0;
+}
+
+static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
+               struct nand_chip *chip, const uint8_t *buf, int oob_required)
+{
+       struct atmel_nand_host *host = chip->priv;
+       uint32_t *eccpos = chip->ecc.layout->eccpos;
+       int i, j;
+       unsigned long end_time;
+
+       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
+       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
+
+       pmecc_writel(host->ecc, CFG, (pmecc_readl_relaxed(host->ecc, CFG) |
+               PMECC_CFG_WRITE_OP) & ~PMECC_CFG_AUTO_ENABLE);
+
+       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE);
+       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA);
+
+       chip->write_buf(mtd, (u8 *)buf, mtd->writesize);
+
+       end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS);
+       while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) {
+               if (unlikely(time_after(jiffies, end_time))) {
+                       dev_err(host->dev, "PMECC: Timeout to get ECC value.\n");
+                       return -EIO;
+               }
+               cpu_relax();
+       }
+
+       for (i = 0; i < host->pmecc_sector_number; i++) {
+               for (j = 0; j < host->pmecc_bytes_per_sector; j++) {
+                       int pos;
+
+                       pos = i * host->pmecc_bytes_per_sector + j;
+                       chip->oob_poi[eccpos[pos]] =
+                               pmecc_readb_ecc_relaxed(host->ecc, i, j);
+               }
+       }
+       chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       return 0;
+}
+
+static void atmel_pmecc_core_init(struct mtd_info *mtd)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct atmel_nand_host *host = nand_chip->priv;
+       uint32_t val = 0;
+       struct nand_ecclayout *ecc_layout;
+
+       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
+       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
+
+       switch (host->pmecc_corr_cap) {
+       case 2:
+               val = PMECC_CFG_BCH_ERR2;
+               break;
+       case 4:
+               val = PMECC_CFG_BCH_ERR4;
+               break;
+       case 8:
+               val = PMECC_CFG_BCH_ERR8;
+               break;
+       case 12:
+               val = PMECC_CFG_BCH_ERR12;
+               break;
+       case 24:
+               val = PMECC_CFG_BCH_ERR24;
+               break;
+       }
+
+       if (host->pmecc_sector_size == 512)
+               val |= PMECC_CFG_SECTOR512;
+       else if (host->pmecc_sector_size == 1024)
+               val |= PMECC_CFG_SECTOR1024;
+
+       switch (host->pmecc_sector_number) {
+       case 1:
+               val |= PMECC_CFG_PAGE_1SECTOR;
+               break;
+       case 2:
+               val |= PMECC_CFG_PAGE_2SECTORS;
+               break;
+       case 4:
+               val |= PMECC_CFG_PAGE_4SECTORS;
+               break;
+       case 8:
+               val |= PMECC_CFG_PAGE_8SECTORS;
+               break;
+       }
+
+       val |= (PMECC_CFG_READ_OP | PMECC_CFG_SPARE_DISABLE
+               | PMECC_CFG_AUTO_DISABLE);
+       pmecc_writel(host->ecc, CFG, val);
+
+       ecc_layout = nand_chip->ecc.layout;
+       pmecc_writel(host->ecc, SAREA, mtd->oobsize - 1);
+       pmecc_writel(host->ecc, SADDR, ecc_layout->eccpos[0]);
+       pmecc_writel(host->ecc, EADDR,
+                       ecc_layout->eccpos[ecc_layout->eccbytes - 1]);
+       /* See datasheet about PMECC Clock Control Register */
+       pmecc_writel(host->ecc, CLK, 2);
+       pmecc_writel(host->ecc, IDR, 0xff);
+       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE);
+}
+
+static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev,
+                                        struct atmel_nand_host *host)
+{
+       struct mtd_info *mtd = &host->mtd;
+       struct nand_chip *nand_chip = &host->nand_chip;
+       struct resource *regs, *regs_pmerr, *regs_rom;
+       int cap, sector_size, err_no;
+
+       cap = host->pmecc_corr_cap;
+       sector_size = host->pmecc_sector_size;
+       dev_info(host->dev, "Initialize PMECC params, cap: %d, sector: %d\n",
+                cap, sector_size);
+
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (!regs) {
+               dev_warn(host->dev,
+                       "Can't get I/O resource regs for PMECC controller, rolling back on software ECC\n");
+               nand_chip->ecc.mode = NAND_ECC_SOFT;
+               return 0;
+       }
+
+       host->ecc = ioremap(regs->start, resource_size(regs));
+       if (host->ecc == NULL) {
+               dev_err(host->dev, "ioremap failed\n");
+               err_no = -EIO;
+               goto err_pmecc_ioremap;
+       }
+
+       regs_pmerr = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+       regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+       if (regs_pmerr && regs_rom) {
+               host->pmerrloc_base = ioremap(regs_pmerr->start,
+                       resource_size(regs_pmerr));
+               host->pmecc_rom_base = ioremap(regs_rom->start,
+                       resource_size(regs_rom));
+       }
+
+       if (!host->pmerrloc_base || !host->pmecc_rom_base) {
+               dev_err(host->dev,
+                       "Can not get I/O resource for PMECC ERRLOC controller or ROM!\n");
+               err_no = -EIO;
+               goto err_pmloc_ioremap;
+       }
+
+       /* ECC is calculated for the whole page (1 step) */
+       nand_chip->ecc.size = mtd->writesize;
+
+       /* set ECC page size and oob layout */
+       switch (mtd->writesize) {
+       case 2048:
+               host->pmecc_degree = PMECC_GF_DIMENSION_13;
+               host->pmecc_cw_len = (1 << host->pmecc_degree) - 1;
+               host->pmecc_sector_number = mtd->writesize / sector_size;
+               host->pmecc_bytes_per_sector = pmecc_get_ecc_bytes(
+                       cap, sector_size);
+               host->pmecc_alpha_to = pmecc_get_alpha_to(host);
+               host->pmecc_index_of = host->pmecc_rom_base +
+                       host->pmecc_lookup_table_offset;
+
+               nand_chip->ecc.steps = 1;
+               nand_chip->ecc.strength = cap;
+               nand_chip->ecc.bytes = host->pmecc_bytes_per_sector *
+                                      host->pmecc_sector_number;
+               if (nand_chip->ecc.bytes > mtd->oobsize - 2) {
+                       dev_err(host->dev, "No room for ECC bytes\n");
+                       err_no = -EINVAL;
+                       goto err_no_ecc_room;
+               }
+               pmecc_config_ecc_layout(&atmel_pmecc_oobinfo,
+                                       mtd->oobsize,
+                                       nand_chip->ecc.bytes);
+               nand_chip->ecc.layout = &atmel_pmecc_oobinfo;
+               break;
+       case 512:
+       case 1024:
+       case 4096:
+               /* TODO */
+               dev_warn(host->dev,
+                       "Unsupported page size for PMECC, use Software ECC\n");
+       default:
+               /* page size not handled by HW ECC */
+               /* switching back to soft ECC */
+               nand_chip->ecc.mode = NAND_ECC_SOFT;
+               return 0;
+       }
+
+       /* Allocate data for PMECC computation */
+       err_no = pmecc_data_alloc(host);
+       if (err_no) {
+               dev_err(host->dev,
+                               "Cannot allocate memory for PMECC computation!\n");
+               goto err_pmecc_data_alloc;
+       }
+
+       nand_chip->ecc.read_page = atmel_nand_pmecc_read_page;
+       nand_chip->ecc.write_page = atmel_nand_pmecc_write_page;
+
+       atmel_pmecc_core_init(mtd);
+
+       return 0;
+
+err_pmecc_data_alloc:
+err_no_ecc_room:
+err_pmloc_ioremap:
+       iounmap(host->ecc);
+       if (host->pmerrloc_base)
+               iounmap(host->pmerrloc_base);
+       if (host->pmecc_rom_base)
+               iounmap(host->pmecc_rom_base);
+err_pmecc_ioremap:
+       return err_no;
+}
+
 /*
  * Calculate HW ECC
  *
@@ -481,7 +1208,8 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
 static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
                                         struct device_node *np)
 {
-       u32 val;
+       u32 val, table_offset;
+       u32 offset[2];
        int ecc_mode;
        struct atmel_nand_data *board = &host->board;
        enum of_gpio_flags flags;
@@ -517,6 +1245,50 @@ static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
        board->enable_pin = of_get_gpio(np, 1);
        board->det_pin = of_get_gpio(np, 2);
 
+       host->has_pmecc = of_property_read_bool(np, "atmel,has-pmecc");
+
+       if (!(board->ecc_mode == NAND_ECC_HW) || !host->has_pmecc)
+               return 0;       /* Not using PMECC */
+
+       /* use PMECC, get correction capability, sector size and lookup
+        * table offset.
+        */
+       if (of_property_read_u32(np, "atmel,pmecc-cap", &val) != 0) {
+               dev_err(host->dev, "Cannot decide PMECC Capability\n");
+               return -EINVAL;
+       } else if ((val != 2) && (val != 4) && (val != 8) && (val != 12) &&
+           (val != 24)) {
+               dev_err(host->dev,
+                       "Unsupported PMECC correction capability: %d; should be 2, 4, 8, 12 or 24\n",
+                       val);
+               return -EINVAL;
+       }
+       host->pmecc_corr_cap = (u8)val;
+
+       if (of_property_read_u32(np, "atmel,pmecc-sector-size", &val) != 0) {
+               dev_err(host->dev, "Cannot decide PMECC Sector Size\n");
+               return -EINVAL;
+       } else if ((val != 512) && (val != 1024)) {
+               dev_err(host->dev,
+                       "Unsupported PMECC sector size: %d; should be 512 or 1024 bytes\n",
+                       val);
+               return -EINVAL;
+       }
+       host->pmecc_sector_size = (u16)val;
+
+       if (of_property_read_u32_array(np, "atmel,pmecc-lookup-table-offset",
+                       offset, 2) != 0) {
+               dev_err(host->dev, "Cannot get PMECC lookup table offset\n");
+               return -EINVAL;
+       }
+       table_offset = host->pmecc_sector_size == 512 ? offset[0] : offset[1];
+
+       if (!table_offset) {
+               dev_err(host->dev, "Invalid PMECC lookup table offset\n");
+               return -EINVAL;
+       }
+       host->pmecc_lookup_table_offset = table_offset;
+
        return 0;
 }
 #else
@@ -527,6 +1299,66 @@ static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
 }
 #endif
 
+static int __init atmel_hw_nand_init_params(struct platform_device *pdev,
+                                        struct atmel_nand_host *host)
+{
+       struct mtd_info *mtd = &host->mtd;
+       struct nand_chip *nand_chip = &host->nand_chip;
+       struct resource         *regs;
+
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (!regs) {
+               dev_err(host->dev,
+                       "Can't get I/O resource regs, use software ECC\n");
+               nand_chip->ecc.mode = NAND_ECC_SOFT;
+               return 0;
+       }
+
+       host->ecc = ioremap(regs->start, resource_size(regs));
+       if (host->ecc == NULL) {
+               dev_err(host->dev, "ioremap failed\n");
+               return -EIO;
+       }
+
+       /* ECC is calculated for the whole page (1 step) */
+       nand_chip->ecc.size = mtd->writesize;
+
+       /* set ECC page size and oob layout */
+       switch (mtd->writesize) {
+       case 512:
+               nand_chip->ecc.layout = &atmel_oobinfo_small;
+               ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
+               break;
+       case 1024:
+               nand_chip->ecc.layout = &atmel_oobinfo_large;
+               ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056);
+               break;
+       case 2048:
+               nand_chip->ecc.layout = &atmel_oobinfo_large;
+               ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112);
+               break;
+       case 4096:
+               nand_chip->ecc.layout = &atmel_oobinfo_large;
+               ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224);
+               break;
+       default:
+               /* page size not handled by HW ECC */
+               /* switching back to soft ECC */
+               nand_chip->ecc.mode = NAND_ECC_SOFT;
+               return 0;
+       }
+
+       /* set up for HW ECC */
+       nand_chip->ecc.calculate = atmel_nand_calculate;
+       nand_chip->ecc.correct = atmel_nand_correct;
+       nand_chip->ecc.hwctl = atmel_nand_hwctl;
+       nand_chip->ecc.read_page = atmel_nand_read_page;
+       nand_chip->ecc.bytes = 4;
+       nand_chip->ecc.strength = 1;
+
+       return 0;
+}
+
 /*
  * Probe for the NAND device.
  */
@@ -535,7 +1367,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
        struct atmel_nand_host *host;
        struct mtd_info *mtd;
        struct nand_chip *nand_chip;
-       struct resource *regs;
        struct resource *mem;
        struct mtd_part_parser_data ppdata = {};
        int res;
@@ -568,7 +1399,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
        if (pdev->dev.of_node) {
                res = atmel_of_init_port(host, pdev->dev.of_node);
                if (res)
-                       goto err_nand_ioremap;
+                       goto err_ecc_ioremap;
        } else {
                memcpy(&host->board, pdev->dev.platform_data,
                       sizeof(struct atmel_nand_data));
@@ -583,33 +1414,45 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
        nand_chip->IO_ADDR_W = host->io_base;
        nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
 
-       if (gpio_is_valid(host->board.rdy_pin))
-               nand_chip->dev_ready = atmel_nand_device_ready;
+       if (gpio_is_valid(host->board.rdy_pin)) {
+               res = gpio_request(host->board.rdy_pin, "nand_rdy");
+               if (res < 0) {
+                       dev_err(&pdev->dev,
+                               "can't request rdy gpio %d\n",
+                               host->board.rdy_pin);
+                       goto err_ecc_ioremap;
+               }
 
-       nand_chip->ecc.mode = host->board.ecc_mode;
+               res = gpio_direction_input(host->board.rdy_pin);
+               if (res < 0) {
+                       dev_err(&pdev->dev,
+                               "can't request input direction rdy gpio %d\n",
+                               host->board.rdy_pin);
+                       goto err_ecc_ioremap;
+               }
 
-       regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!regs && nand_chip->ecc.mode == NAND_ECC_HW) {
-               printk(KERN_ERR "atmel_nand: can't get I/O resource "
-                               "regs\nFalling back on software ECC\n");
-               nand_chip->ecc.mode = NAND_ECC_SOFT;
+               nand_chip->dev_ready = atmel_nand_device_ready;
        }
 
-       if (nand_chip->ecc.mode == NAND_ECC_HW) {
-               host->ecc = ioremap(regs->start, resource_size(regs));
-               if (host->ecc == NULL) {
-                       printk(KERN_ERR "atmel_nand: ioremap failed\n");
-                       res = -EIO;
+       if (gpio_is_valid(host->board.enable_pin)) {
+               res = gpio_request(host->board.enable_pin, "nand_enable");
+               if (res < 0) {
+                       dev_err(&pdev->dev,
+                               "can't request enable gpio %d\n",
+                               host->board.enable_pin);
+                       goto err_ecc_ioremap;
+               }
+
+               res = gpio_direction_output(host->board.enable_pin, 1);
+               if (res < 0) {
+                       dev_err(&pdev->dev,
+                               "can't request output direction enable gpio %d\n",
+                               host->board.enable_pin);
                        goto err_ecc_ioremap;
                }
-               nand_chip->ecc.calculate = atmel_nand_calculate;
-               nand_chip->ecc.correct = atmel_nand_correct;
-               nand_chip->ecc.hwctl = atmel_nand_hwctl;
-               nand_chip->ecc.read_page = atmel_nand_read_page;
-               nand_chip->ecc.bytes = 4;
-               nand_chip->ecc.strength = 1;
        }
 
+       nand_chip->ecc.mode = host->board.ecc_mode;
        nand_chip->chip_delay = 20;             /* 20us command delay time */
 
        if (host->board.bus_width_16)   /* 16-bit bus width */
@@ -622,6 +1465,22 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
        atmel_nand_enable(host);
 
        if (gpio_is_valid(host->board.det_pin)) {
+               res = gpio_request(host->board.det_pin, "nand_det");
+               if (res < 0) {
+                       dev_err(&pdev->dev,
+                               "can't request det gpio %d\n",
+                               host->board.det_pin);
+                       goto err_no_card;
+               }
+
+               res = gpio_direction_input(host->board.det_pin);
+               if (res < 0) {
+                       dev_err(&pdev->dev,
+                               "can't request input direction det gpio %d\n",
+                               host->board.det_pin);
+                       goto err_no_card;
+               }
+
                if (gpio_get_value(host->board.det_pin)) {
                        printk(KERN_INFO "No SmartMedia card inserted.\n");
                        res = -ENXIO;
@@ -661,40 +1520,13 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
        }
 
        if (nand_chip->ecc.mode == NAND_ECC_HW) {
-               /* ECC is calculated for the whole page (1 step) */
-               nand_chip->ecc.size = mtd->writesize;
-
-               /* set ECC page size and oob layout */
-               switch (mtd->writesize) {
-               case 512:
-                       nand_chip->ecc.layout = &atmel_oobinfo_small;
-                       ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
-                       break;
-               case 1024:
-                       nand_chip->ecc.layout = &atmel_oobinfo_large;
-                       ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056);
-                       break;
-               case 2048:
-                       nand_chip->ecc.layout = &atmel_oobinfo_large;
-                       ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112);
-                       break;
-               case 4096:
-                       nand_chip->ecc.layout = &atmel_oobinfo_large;
-                       ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224);
-                       break;
-               default:
-                       /* page size not handled by HW ECC */
-                       /* switching back to soft ECC */
-                       nand_chip->ecc.mode = NAND_ECC_SOFT;
-                       nand_chip->ecc.calculate = NULL;
-                       nand_chip->ecc.correct = NULL;
-                       nand_chip->ecc.hwctl = NULL;
-                       nand_chip->ecc.read_page = NULL;
-                       nand_chip->ecc.postpad = 0;
-                       nand_chip->ecc.prepad = 0;
-                       nand_chip->ecc.bytes = 0;
-                       break;
-               }
+               if (host->has_pmecc)
+                       res = atmel_pmecc_nand_init_params(pdev, host);
+               else
+                       res = atmel_hw_nand_init_params(pdev, host);
+
+               if (res != 0)
+                       goto err_hw_ecc;
        }
 
        /* second phase scan */
@@ -711,14 +1543,23 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
                return res;
 
 err_scan_tail:
+       if (host->has_pmecc && host->nand_chip.ecc.mode == NAND_ECC_HW) {
+               pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
+               pmecc_data_free(host);
+       }
+       if (host->ecc)
+               iounmap(host->ecc);
+       if (host->pmerrloc_base)
+               iounmap(host->pmerrloc_base);
+       if (host->pmecc_rom_base)
+               iounmap(host->pmecc_rom_base);
+err_hw_ecc:
 err_scan_ident:
 err_no_card:
        atmel_nand_disable(host);
        platform_set_drvdata(pdev, NULL);
        if (host->dma_chan)
                dma_release_channel(host->dma_chan);
-       if (host->ecc)
-               iounmap(host->ecc);
 err_ecc_ioremap:
        iounmap(host->io_base);
 err_nand_ioremap:
@@ -738,8 +1579,28 @@ static int __exit atmel_nand_remove(struct platform_device *pdev)
 
        atmel_nand_disable(host);
 
+       if (host->has_pmecc && host->nand_chip.ecc.mode == NAND_ECC_HW) {
+               pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
+               pmerrloc_writel(host->pmerrloc_base, ELDIS,
+                               PMERRLOC_DISABLE);
+               pmecc_data_free(host);
+       }
+
+       if (gpio_is_valid(host->board.det_pin))
+               gpio_free(host->board.det_pin);
+
+       if (gpio_is_valid(host->board.enable_pin))
+               gpio_free(host->board.enable_pin);
+
+       if (gpio_is_valid(host->board.rdy_pin))
+               gpio_free(host->board.rdy_pin);
+
        if (host->ecc)
                iounmap(host->ecc);
+       if (host->pmecc_rom_base)
+               iounmap(host->pmecc_rom_base);
+       if (host->pmerrloc_base)
+               iounmap(host->pmerrloc_base);
 
        if (host->dma_chan)
                dma_release_channel(host->dma_chan);
index 578c776e135632144c30fc20671c35becdb8b489..8a1e9a686759fb5f2796716e50db3877711c7389 100644 (file)
@@ -3,7 +3,7 @@
  * Based on AT91SAM9260 datasheet revision B.
  *
  * Copyright (C) 2007 Andrew Victor
- * Copyright (C) 2007 Atmel Corporation.
+ * Copyright (C) 2007 - 2012 Atmel 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
 #define ATMEL_ECC_NPR          0x10                    /* NParity register */
 #define                ATMEL_ECC_NPARITY       (0xffff << 0)           /* NParity */
 
+/* PMECC Register Definitions */
+#define ATMEL_PMECC_CFG                        0x000   /* Configuration Register */
+#define                PMECC_CFG_BCH_ERR2              (0 << 0)
+#define                PMECC_CFG_BCH_ERR4              (1 << 0)
+#define                PMECC_CFG_BCH_ERR8              (2 << 0)
+#define                PMECC_CFG_BCH_ERR12             (3 << 0)
+#define                PMECC_CFG_BCH_ERR24             (4 << 0)
+
+#define                PMECC_CFG_SECTOR512             (0 << 4)
+#define                PMECC_CFG_SECTOR1024            (1 << 4)
+
+#define                PMECC_CFG_PAGE_1SECTOR          (0 << 8)
+#define                PMECC_CFG_PAGE_2SECTORS         (1 << 8)
+#define                PMECC_CFG_PAGE_4SECTORS         (2 << 8)
+#define                PMECC_CFG_PAGE_8SECTORS         (3 << 8)
+
+#define                PMECC_CFG_READ_OP               (0 << 12)
+#define                PMECC_CFG_WRITE_OP              (1 << 12)
+
+#define                PMECC_CFG_SPARE_ENABLE          (1 << 16)
+#define                PMECC_CFG_SPARE_DISABLE         (0 << 16)
+
+#define                PMECC_CFG_AUTO_ENABLE           (1 << 20)
+#define                PMECC_CFG_AUTO_DISABLE          (0 << 20)
+
+#define ATMEL_PMECC_SAREA              0x004   /* Spare area size */
+#define ATMEL_PMECC_SADDR              0x008   /* PMECC starting address */
+#define ATMEL_PMECC_EADDR              0x00c   /* PMECC ending address */
+#define ATMEL_PMECC_CLK                        0x010   /* PMECC clock control */
+#define                PMECC_CLK_133MHZ                (2 << 0)
+
+#define ATMEL_PMECC_CTRL               0x014   /* PMECC control register */
+#define                PMECC_CTRL_RST                  (1 << 0)
+#define                PMECC_CTRL_DATA                 (1 << 1)
+#define                PMECC_CTRL_USER                 (1 << 2)
+#define                PMECC_CTRL_ENABLE               (1 << 4)
+#define                PMECC_CTRL_DISABLE              (1 << 5)
+
+#define ATMEL_PMECC_SR                 0x018   /* PMECC status register */
+#define                PMECC_SR_BUSY                   (1 << 0)
+#define                PMECC_SR_ENABLE                 (1 << 4)
+
+#define ATMEL_PMECC_IER                        0x01c   /* PMECC interrupt enable */
+#define                PMECC_IER_ENABLE                (1 << 0)
+#define ATMEL_PMECC_IDR                        0x020   /* PMECC interrupt disable */
+#define                PMECC_IER_DISABLE               (1 << 0)
+#define ATMEL_PMECC_IMR                        0x024   /* PMECC interrupt mask */
+#define                PMECC_IER_MASK                  (1 << 0)
+#define ATMEL_PMECC_ISR                        0x028   /* PMECC interrupt status */
+#define ATMEL_PMECC_ECCx               0x040   /* PMECC ECC x */
+#define ATMEL_PMECC_REMx               0x240   /* PMECC REM x */
+
+/* PMERRLOC Register Definitions */
+#define ATMEL_PMERRLOC_ELCFG           0x000   /* Error location config */
+#define                PMERRLOC_ELCFG_SECTOR_512       (0 << 0)
+#define                PMERRLOC_ELCFG_SECTOR_1024      (1 << 0)
+#define                PMERRLOC_ELCFG_NUM_ERRORS(n)    ((n) << 16)
+
+#define ATMEL_PMERRLOC_ELPRIM          0x004   /* Error location primitive */
+#define ATMEL_PMERRLOC_ELEN            0x008   /* Error location enable */
+#define ATMEL_PMERRLOC_ELDIS           0x00c   /* Error location disable */
+#define                PMERRLOC_DISABLE                (1 << 0)
+
+#define ATMEL_PMERRLOC_ELSR            0x010   /* Error location status */
+#define                PMERRLOC_ELSR_BUSY              (1 << 0)
+#define ATMEL_PMERRLOC_ELIER           0x014   /* Error location int enable */
+#define ATMEL_PMERRLOC_ELIDR           0x018   /* Error location int disable */
+#define ATMEL_PMERRLOC_ELIMR           0x01c   /* Error location int mask */
+#define ATMEL_PMERRLOC_ELISR           0x020   /* Error location int status */
+#define                PMERRLOC_ERR_NUM_MASK           (0x1f << 8)
+#define                PMERRLOC_CALC_DONE              (1 << 0)
+#define ATMEL_PMERRLOC_SIGMAx          0x028   /* Error location SIGMA x */
+#define ATMEL_PMERRLOC_ELx             0x08c   /* Error location x */
+
+/* Register access macros for PMECC */
+#define pmecc_readl_relaxed(addr, reg) \
+       readl_relaxed((addr) + ATMEL_PMECC_##reg)
+
+#define pmecc_writel(addr, reg, value) \
+       writel((value), (addr) + ATMEL_PMECC_##reg)
+
+#define pmecc_readb_ecc_relaxed(addr, sector, n) \
+       readb_relaxed((addr) + ATMEL_PMECC_ECCx + ((sector) * 0x40) + (n))
+
+#define pmecc_readl_rem_relaxed(addr, sector, n) \
+       readl_relaxed((addr) + ATMEL_PMECC_REMx + ((sector) * 0x40) + ((n) * 4))
+
+#define pmerrloc_readl_relaxed(addr, reg) \
+       readl_relaxed((addr) + ATMEL_PMERRLOC_##reg)
+
+#define pmerrloc_writel(addr, reg, value) \
+       writel((value), (addr) + ATMEL_PMERRLOC_##reg)
+
+#define pmerrloc_writel_sigma_relaxed(addr, n, value) \
+       writel_relaxed((value), (addr) + ATMEL_PMERRLOC_SIGMAx + ((n) * 4))
+
+#define pmerrloc_readl_sigma_relaxed(addr, n) \
+       readl_relaxed((addr) + ATMEL_PMERRLOC_SIGMAx + ((n) * 4))
+
+#define pmerrloc_readl_el_relaxed(addr, n) \
+       readl_relaxed((addr) + ATMEL_PMERRLOC_ELx + ((n) * 4))
+
+/* Galois field dimension */
+#define PMECC_GF_DIMENSION_13                  13
+#define PMECC_GF_DIMENSION_14                  14
+
+#define PMECC_LOOKUP_TABLE_SIZE_512            0x2000
+#define PMECC_LOOKUP_TABLE_SIZE_1024           0x4000
+
+/* Time out value for reading PMECC status register */
+#define PMECC_MAX_TIMEOUT_MS                   100
+
 #endif
index 9f609d2dcf62d3dc993358e4de817de00d154267..5c47b200045a3cbc22571b0eb76db23c8a627890 100644 (file)
@@ -140,28 +140,6 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
        }
 }
 
-/**
- * au_verify_buf -  Verify chip data against buffer
- * @mtd:       MTD device structure
- * @buf:       buffer containing the data to compare
- * @len:       number of bytes to compare
- *
- * verify function for 8bit buswidth
- */
-static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
-{
-       int i;
-       struct nand_chip *this = mtd->priv;
-
-       for (i = 0; i < len; i++) {
-               if (buf[i] != readb(this->IO_ADDR_R))
-                       return -EFAULT;
-               au_sync();
-       }
-
-       return 0;
-}
-
 /**
  * au_write_buf16 -  write buffer to chip
  * @mtd:       MTD device structure
@@ -205,29 +183,6 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
        }
 }
 
-/**
- * au_verify_buf16 -  Verify chip data against buffer
- * @mtd:       MTD device structure
- * @buf:       buffer containing the data to compare
- * @len:       number of bytes to compare
- *
- * verify function for 16bit buswidth
- */
-static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
-{
-       int i;
-       struct nand_chip *this = mtd->priv;
-       u16 *p = (u16 *) buf;
-       len >>= 1;
-
-       for (i = 0; i < len; i++) {
-               if (p[i] != readw(this->IO_ADDR_R))
-                       return -EFAULT;
-               au_sync();
-       }
-       return 0;
-}
-
 /* Select the chip by setting nCE to low */
 #define NAND_CTL_SETNCE                1
 /* Deselect the chip by setting nCE to high */
@@ -516,7 +471,6 @@ static int __devinit au1550nd_probe(struct platform_device *pdev)
        this->read_word = au_read_word;
        this->write_buf = (pd->devwidth) ? au_write_buf16 : au_write_buf;
        this->read_buf = (pd->devwidth) ? au_read_buf16 : au_read_buf;
-       this->verify_buf = (pd->devwidth) ? au_verify_buf16 : au_verify_buf;
 
        ret = nand_scan(&ctx->info, 1);
        if (ret) {
diff --git a/drivers/mtd/nand/bcm_umi_bch.c b/drivers/mtd/nand/bcm_umi_bch.c
deleted file mode 100644 (file)
index 5914bb3..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/*****************************************************************************
-* Copyright 2004 - 2009 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-/* ---- Include Files ---------------------------------------------------- */
-#include "nand_bcm_umi.h"
-
-/* ---- External Variable Declarations ----------------------------------- */
-/* ---- External Function Prototypes ------------------------------------- */
-/* ---- Public Variables ------------------------------------------------- */
-/* ---- Private Constants and Types -------------------------------------- */
-
-/* ---- Private Function Prototypes -------------------------------------- */
-static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
-       struct nand_chip *chip, uint8_t *buf, int oob_required, int page);
-static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd,
-       struct nand_chip *chip, const uint8_t *buf, int oob_required);
-
-/* ---- Private Variables ------------------------------------------------ */
-
-/*
-** nand_hw_eccoob
-** New oob placement block for use with hardware ecc generation.
-*/
-static struct nand_ecclayout nand_hw_eccoob_512 = {
-       /* Reserve 5 for BI indicator */
-       .oobfree = {
-#if (NAND_ECC_NUM_BYTES > 3)
-                   {.offset = 0, .length = 2}
-#else
-                   {.offset = 0, .length = 5},
-                   {.offset = 6, .length = 7}
-#endif
-                   }
-};
-
-/*
-** We treat the OOB for a 2K page as if it were 4 512 byte oobs,
-** except the BI is at byte 0.
-*/
-static struct nand_ecclayout nand_hw_eccoob_2048 = {
-       /* Reserve 0 as BI indicator */
-       .oobfree = {
-#if (NAND_ECC_NUM_BYTES > 10)
-                   {.offset = 1, .length = 2},
-#elif (NAND_ECC_NUM_BYTES > 7)
-                   {.offset = 1, .length = 5},
-                   {.offset = 16, .length = 6},
-                   {.offset = 32, .length = 6},
-                   {.offset = 48, .length = 6}
-#else
-                   {.offset = 1, .length = 8},
-                   {.offset = 16, .length = 9},
-                   {.offset = 32, .length = 9},
-                   {.offset = 48, .length = 9}
-#endif
-                   }
-};
-
-/* We treat the OOB for a 4K page as if it were 8 512 byte oobs,
- * except the BI is at byte 0. */
-static struct nand_ecclayout nand_hw_eccoob_4096 = {
-       /* Reserve 0 as BI indicator */
-       .oobfree = {
-#if (NAND_ECC_NUM_BYTES > 10)
-                   {.offset = 1, .length = 2},
-                   {.offset = 16, .length = 3},
-                   {.offset = 32, .length = 3},
-                   {.offset = 48, .length = 3},
-                   {.offset = 64, .length = 3},
-                   {.offset = 80, .length = 3},
-                   {.offset = 96, .length = 3},
-                   {.offset = 112, .length = 3}
-#else
-                   {.offset = 1, .length = 5},
-                   {.offset = 16, .length = 6},
-                   {.offset = 32, .length = 6},
-                   {.offset = 48, .length = 6},
-                   {.offset = 64, .length = 6},
-                   {.offset = 80, .length = 6},
-                   {.offset = 96, .length = 6},
-                   {.offset = 112, .length = 6}
-#endif
-                   }
-};
-
-/* ---- Private Functions ------------------------------------------------ */
-/* ==== Public Functions ================================================= */
-
-/****************************************************************************
-*
-*  bcm_umi_bch_read_page_hwecc - hardware ecc based page read function
-*  @mtd:       mtd info structure
-*  @chip:      nand chip info structure
-*  @buf:       buffer to store read data
-*  @oob_required:      caller expects OOB data read to chip->oob_poi
-*
-***************************************************************************/
-static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
-                                      struct nand_chip *chip, uint8_t * buf,
-                                      int oob_required, int page)
-{
-       int sectorIdx = 0;
-       int eccsize = chip->ecc.size;
-       int eccsteps = chip->ecc.steps;
-       uint8_t *datap = buf;
-       uint8_t eccCalc[NAND_ECC_NUM_BYTES];
-       int sectorOobSize = mtd->oobsize / eccsteps;
-       int stat;
-       unsigned int max_bitflips = 0;
-
-       for (sectorIdx = 0; sectorIdx < eccsteps;
-                       sectorIdx++, datap += eccsize) {
-               if (sectorIdx > 0) {
-                       /* Seek to page location within sector */
-                       chip->cmdfunc(mtd, NAND_CMD_RNDOUT, sectorIdx * eccsize,
-                                     -1);
-               }
-
-               /* Enable hardware ECC before reading the buf */
-               nand_bcm_umi_bch_enable_read_hwecc();
-
-               /* Read in data */
-               bcm_umi_nand_read_buf(mtd, datap, eccsize);
-
-               /* Pause hardware ECC after reading the buf */
-               nand_bcm_umi_bch_pause_read_ecc_calc();
-
-               /* Read the OOB ECC */
-               chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
-                             mtd->writesize + sectorIdx * sectorOobSize, -1);
-               nand_bcm_umi_bch_read_oobEcc(mtd->writesize, eccCalc,
-                                            NAND_ECC_NUM_BYTES,
-                                            chip->oob_poi +
-                                            sectorIdx * sectorOobSize);
-
-               /* Correct any ECC detected errors */
-               stat =
-                   nand_bcm_umi_bch_correct_page(datap, eccCalc,
-                                                 NAND_ECC_NUM_BYTES);
-
-               /* Update Stats */
-               if (stat < 0) {
-#if defined(NAND_BCM_UMI_DEBUG)
-                       printk(KERN_WARNING "%s uncorr_err sectorIdx=%d\n",
-                              __func__, sectorIdx);
-                       printk(KERN_WARNING
-                              "%s data %02x %02x %02x %02x "
-                                        "%02x %02x %02x %02x\n",
-                              __func__, datap[0], datap[1], datap[2], datap[3],
-                              datap[4], datap[5], datap[6], datap[7]);
-                       printk(KERN_WARNING
-                              "%s ecc  %02x %02x %02x %02x "
-                                        "%02x %02x %02x %02x %02x %02x "
-                                        "%02x %02x %02x\n",
-                              __func__, eccCalc[0], eccCalc[1], eccCalc[2],
-                              eccCalc[3], eccCalc[4], eccCalc[5], eccCalc[6],
-                              eccCalc[7], eccCalc[8], eccCalc[9], eccCalc[10],
-                              eccCalc[11], eccCalc[12]);
-                       BUG();
-#endif
-                       mtd->ecc_stats.failed++;
-               } else {
-#if defined(NAND_BCM_UMI_DEBUG)
-                       if (stat > 0) {
-                               printk(KERN_INFO
-                                      "%s %d correctable_errors detected\n",
-                                      __func__, stat);
-                       }
-#endif
-                       mtd->ecc_stats.corrected += stat;
-                       max_bitflips = max_t(unsigned int, max_bitflips, stat);
-               }
-       }
-       return max_bitflips;
-}
-
-/****************************************************************************
-*
-*  bcm_umi_bch_write_page_hwecc - hardware ecc based page write function
-*  @mtd:       mtd info structure
-*  @chip:      nand chip info structure
-*  @buf:       data buffer
-*  @oob_required:      must write chip->oob_poi to OOB
-*
-***************************************************************************/
-static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd,
-       struct nand_chip *chip, const uint8_t *buf, int oob_required)
-{
-       int sectorIdx = 0;
-       int eccsize = chip->ecc.size;
-       int eccsteps = chip->ecc.steps;
-       const uint8_t *datap = buf;
-       uint8_t *oobp = chip->oob_poi;
-       int sectorOobSize = mtd->oobsize / eccsteps;
-
-       for (sectorIdx = 0; sectorIdx < eccsteps;
-            sectorIdx++, datap += eccsize, oobp += sectorOobSize) {
-               /* Enable hardware ECC before writing the buf */
-               nand_bcm_umi_bch_enable_write_hwecc();
-               bcm_umi_nand_write_buf(mtd, datap, eccsize);
-               nand_bcm_umi_bch_write_oobEcc(mtd->writesize, oobp,
-                                             NAND_ECC_NUM_BYTES);
-       }
-
-       bcm_umi_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
-}
diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c
deleted file mode 100644 (file)
index d0d1bd4..0000000
+++ /dev/null
@@ -1,555 +0,0 @@
-/*****************************************************************************
-* Copyright 2004 - 2009 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-/* ---- Include Files ---------------------------------------------------- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/mach-types.h>
-
-#include <mach/reg_nand.h>
-#include <mach/reg_umi.h>
-
-#include "nand_bcm_umi.h"
-
-#include <mach/memory_settings.h>
-
-#define USE_DMA 1
-#include <mach/dma.h>
-#include <linux/dma-mapping.h>
-#include <linux/completion.h>
-
-/* ---- External Variable Declarations ----------------------------------- */
-/* ---- External Function Prototypes ------------------------------------- */
-/* ---- Public Variables ------------------------------------------------- */
-/* ---- Private Constants and Types -------------------------------------- */
-static const __devinitconst char gBanner[] = KERN_INFO \
-       "BCM UMI MTD NAND Driver: 1.00\n";
-
-#if NAND_ECC_BCH
-static uint8_t scan_ff_pattern[] = { 0xff };
-
-static struct nand_bbt_descr largepage_bbt = {
-       .options = 0,
-       .offs = 0,
-       .len = 1,
-       .pattern = scan_ff_pattern
-};
-#endif
-
-/*
-** Preallocate a buffer to avoid having to do this every dma operation.
-** This is the size of the preallocated coherent DMA buffer.
-*/
-#if USE_DMA
-#define DMA_MIN_BUFLEN 512
-#define DMA_MAX_BUFLEN PAGE_SIZE
-#define USE_DIRECT_IO(len)     (((len) < DMA_MIN_BUFLEN) || \
-       ((len) > DMA_MAX_BUFLEN))
-
-/*
- * The current NAND data space goes from 0x80001900 to 0x80001FFF,
- * which is only 0x700 = 1792 bytes long. This is too small for 2K, 4K page
- * size NAND flash. Need to break the DMA down to multiple 1Ks.
- *
- * Need to make sure REG_NAND_DATA_PADDR + DMA_MAX_LEN < 0x80002000
- */
-#define DMA_MAX_LEN             1024
-
-#else /* !USE_DMA */
-#define DMA_MIN_BUFLEN          0
-#define DMA_MAX_BUFLEN          0
-#define USE_DIRECT_IO(len)      1
-#endif
-/* ---- Private Function Prototypes -------------------------------------- */
-static void bcm_umi_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len);
-static void bcm_umi_nand_write_buf(struct mtd_info *mtd, const u_char * buf,
-                                  int len);
-
-/* ---- Private Variables ------------------------------------------------ */
-static struct mtd_info *board_mtd;
-static void __iomem *bcm_umi_io_base;
-static void *virtPtr;
-static dma_addr_t physPtr;
-static struct completion nand_comp;
-
-/* ---- Private Functions ------------------------------------------------ */
-#if NAND_ECC_BCH
-#include "bcm_umi_bch.c"
-#else
-#include "bcm_umi_hamming.c"
-#endif
-
-#if USE_DMA
-
-/* Handler called when the DMA finishes. */
-static void nand_dma_handler(DMA_Device_t dev, int reason, void *userData)
-{
-       complete(&nand_comp);
-}
-
-static int nand_dma_init(void)
-{
-       int rc;
-
-       rc = dma_set_device_handler(DMA_DEVICE_NAND_MEM_TO_MEM,
-               nand_dma_handler, NULL);
-       if (rc != 0) {
-               printk(KERN_ERR "dma_set_device_handler failed: %d\n", rc);
-               return rc;
-       }
-
-       virtPtr =
-           dma_alloc_coherent(NULL, DMA_MAX_BUFLEN, &physPtr, GFP_KERNEL);
-       if (virtPtr == NULL) {
-               printk(KERN_ERR "NAND - Failed to allocate memory for DMA buffer\n");
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-static void nand_dma_term(void)
-{
-       if (virtPtr != NULL)
-               dma_free_coherent(NULL, DMA_MAX_BUFLEN, virtPtr, physPtr);
-}
-
-static void nand_dma_read(void *buf, int len)
-{
-       int offset = 0;
-       int tmp_len = 0;
-       int len_left = len;
-       DMA_Handle_t hndl;
-
-       if (virtPtr == NULL)
-               panic("nand_dma_read: virtPtr == NULL\n");
-
-       if ((void *)physPtr == NULL)
-               panic("nand_dma_read: physPtr == NULL\n");
-
-       hndl = dma_request_channel(DMA_DEVICE_NAND_MEM_TO_MEM);
-       if (hndl < 0) {
-               printk(KERN_ERR
-                      "nand_dma_read: unable to allocate dma channel: %d\n",
-                      (int)hndl);
-               panic("\n");
-       }
-
-       while (len_left > 0) {
-               if (len_left > DMA_MAX_LEN) {
-                       tmp_len = DMA_MAX_LEN;
-                       len_left -= DMA_MAX_LEN;
-               } else {
-                       tmp_len = len_left;
-                       len_left = 0;
-               }
-
-               init_completion(&nand_comp);
-               dma_transfer_mem_to_mem(hndl, REG_NAND_DATA_PADDR,
-                                       physPtr + offset, tmp_len);
-               wait_for_completion(&nand_comp);
-
-               offset += tmp_len;
-       }
-
-       dma_free_channel(hndl);
-
-       if (buf != NULL)
-               memcpy(buf, virtPtr, len);
-}
-
-static void nand_dma_write(const void *buf, int len)
-{
-       int offset = 0;
-       int tmp_len = 0;
-       int len_left = len;
-       DMA_Handle_t hndl;
-
-       if (buf == NULL)
-               panic("nand_dma_write: buf == NULL\n");
-
-       if (virtPtr == NULL)
-               panic("nand_dma_write: virtPtr == NULL\n");
-
-       if ((void *)physPtr == NULL)
-               panic("nand_dma_write: physPtr == NULL\n");
-
-       memcpy(virtPtr, buf, len);
-
-
-       hndl = dma_request_channel(DMA_DEVICE_NAND_MEM_TO_MEM);
-       if (hndl < 0) {
-               printk(KERN_ERR
-                      "nand_dma_write: unable to allocate dma channel: %d\n",
-                      (int)hndl);
-               panic("\n");
-       }
-
-       while (len_left > 0) {
-               if (len_left > DMA_MAX_LEN) {
-                       tmp_len = DMA_MAX_LEN;
-                       len_left -= DMA_MAX_LEN;
-               } else {
-                       tmp_len = len_left;
-                       len_left = 0;
-               }
-
-               init_completion(&nand_comp);
-               dma_transfer_mem_to_mem(hndl, physPtr + offset,
-                                       REG_NAND_DATA_PADDR, tmp_len);
-               wait_for_completion(&nand_comp);
-
-               offset += tmp_len;
-       }
-
-       dma_free_channel(hndl);
-}
-
-#endif
-
-static int nand_dev_ready(struct mtd_info *mtd)
-{
-       return nand_bcm_umi_dev_ready();
-}
-
-/****************************************************************************
-*
-*  bcm_umi_nand_inithw
-*
-*   This routine does the necessary hardware (board-specific)
-*   initializations.  This includes setting up the timings, etc.
-*
-***************************************************************************/
-int bcm_umi_nand_inithw(void)
-{
-       /* Configure nand timing parameters */
-       writel(readl(&REG_UMI_NAND_TCR) & ~0x7ffff, &REG_UMI_NAND_TCR);
-       writel(readl(&REG_UMI_NAND_TCR) | HW_CFG_NAND_TCR, &REG_UMI_NAND_TCR);
-
-#if !defined(CONFIG_MTD_NAND_BCM_UMI_HWCS)
-       /* enable software control of CS */
-       writel(readl(&REG_UMI_NAND_TCR) | REG_UMI_NAND_TCR_CS_SWCTRL, &REG_UMI_NAND_TCR);
-#endif
-
-       /* keep NAND chip select asserted */
-       writel(readl(&REG_UMI_NAND_RCSR) | REG_UMI_NAND_RCSR_CS_ASSERTED, &REG_UMI_NAND_RCSR);
-
-       writel(readl(&REG_UMI_NAND_TCR) & ~REG_UMI_NAND_TCR_WORD16, &REG_UMI_NAND_TCR);
-       /* enable writes to flash */
-       writel(readl(&REG_UMI_MMD_ICR) | REG_UMI_MMD_ICR_FLASH_WP, &REG_UMI_MMD_ICR);
-
-       writel(NAND_CMD_RESET, bcm_umi_io_base + REG_NAND_CMD_OFFSET);
-       nand_bcm_umi_wait_till_ready();
-
-#if NAND_ECC_BCH
-       nand_bcm_umi_bch_config_ecc(NAND_ECC_NUM_BYTES);
-#endif
-
-       return 0;
-}
-
-/* Used to turn latch the proper register for access. */
-static void bcm_umi_nand_hwcontrol(struct mtd_info *mtd, int cmd,
-                                  unsigned int ctrl)
-{
-       /* send command to hardware */
-       struct nand_chip *chip = mtd->priv;
-       if (ctrl & NAND_CTRL_CHANGE) {
-               if (ctrl & NAND_CLE) {
-                       chip->IO_ADDR_W = bcm_umi_io_base + REG_NAND_CMD_OFFSET;
-                       goto CMD;
-               }
-               if (ctrl & NAND_ALE) {
-                       chip->IO_ADDR_W =
-                           bcm_umi_io_base + REG_NAND_ADDR_OFFSET;
-                       goto CMD;
-               }
-               chip->IO_ADDR_W = bcm_umi_io_base + REG_NAND_DATA8_OFFSET;
-       }
-
-CMD:
-       /* Send command to chip directly */
-       if (cmd != NAND_CMD_NONE)
-               writeb(cmd, chip->IO_ADDR_W);
-}
-
-static void bcm_umi_nand_write_buf(struct mtd_info *mtd, const u_char * buf,
-                                  int len)
-{
-       if (USE_DIRECT_IO(len)) {
-               /* Do it the old way if the buffer is small or too large.
-                * Probably quicker than starting and checking dma. */
-               int i;
-               struct nand_chip *this = mtd->priv;
-
-               for (i = 0; i < len; i++)
-                       writeb(buf[i], this->IO_ADDR_W);
-       }
-#if USE_DMA
-       else
-               nand_dma_write(buf, len);
-#endif
-}
-
-static void bcm_umi_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len)
-{
-       if (USE_DIRECT_IO(len)) {
-               int i;
-               struct nand_chip *this = mtd->priv;
-
-               for (i = 0; i < len; i++)
-                       buf[i] = readb(this->IO_ADDR_R);
-       }
-#if USE_DMA
-       else
-               nand_dma_read(buf, len);
-#endif
-}
-
-static uint8_t readbackbuf[NAND_MAX_PAGESIZE];
-static int bcm_umi_nand_verify_buf(struct mtd_info *mtd, const u_char * buf,
-                                  int len)
-{
-       /*
-        * Try to readback page with ECC correction. This is necessary
-        * for MLC parts which may have permanently stuck bits.
-        */
-       struct nand_chip *chip = mtd->priv;
-       int ret = chip->ecc.read_page(mtd, chip, readbackbuf, 0, 0);
-       if (ret < 0)
-               return -EFAULT;
-       else {
-               if (memcmp(readbackbuf, buf, len) == 0)
-                       return 0;
-
-               return -EFAULT;
-       }
-       return 0;
-}
-
-static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
-{
-       struct nand_chip *this;
-       struct resource *r;
-       int err = 0;
-
-       printk(gBanner);
-
-       /* Allocate memory for MTD device structure and private data */
-       board_mtd =
-           kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),
-                   GFP_KERNEL);
-       if (!board_mtd) {
-               printk(KERN_WARNING
-                      "Unable to allocate NAND MTD device structure.\n");
-               return -ENOMEM;
-       }
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-       if (!r) {
-               err = -ENXIO;
-               goto out_free;
-       }
-
-       /* map physical address */
-       bcm_umi_io_base = ioremap(r->start, resource_size(r));
-
-       if (!bcm_umi_io_base) {
-               printk(KERN_ERR "ioremap to access BCM UMI NAND chip failed\n");
-               err = -EIO;
-               goto out_free;
-       }
-
-       /* Get pointer to private data */
-       this = (struct nand_chip *)(&board_mtd[1]);
-
-       /* Initialize structures */
-       memset((char *)board_mtd, 0, sizeof(struct mtd_info));
-       memset((char *)this, 0, sizeof(struct nand_chip));
-
-       /* Link the private data with the MTD structure */
-       board_mtd->priv = this;
-
-       /* Initialize the NAND hardware.  */
-       if (bcm_umi_nand_inithw() < 0) {
-               printk(KERN_ERR "BCM UMI NAND chip could not be initialized\n");
-               err = -EIO;
-               goto out_unmap;
-       }
-
-       /* Set address of NAND IO lines */
-       this->IO_ADDR_W = bcm_umi_io_base + REG_NAND_DATA8_OFFSET;
-       this->IO_ADDR_R = bcm_umi_io_base + REG_NAND_DATA8_OFFSET;
-
-       /* Set command delay time, see datasheet for correct value */
-       this->chip_delay = 0;
-       /* Assign the device ready function, if available */
-       this->dev_ready = nand_dev_ready;
-       this->options = 0;
-
-       this->write_buf = bcm_umi_nand_write_buf;
-       this->read_buf = bcm_umi_nand_read_buf;
-       this->verify_buf = bcm_umi_nand_verify_buf;
-
-       this->cmd_ctrl = bcm_umi_nand_hwcontrol;
-       this->ecc.mode = NAND_ECC_HW;
-       this->ecc.size = 512;
-       this->ecc.bytes = NAND_ECC_NUM_BYTES;
-#if NAND_ECC_BCH
-       this->ecc.read_page = bcm_umi_bch_read_page_hwecc;
-       this->ecc.write_page = bcm_umi_bch_write_page_hwecc;
-#else
-       this->ecc.correct = nand_correct_data512;
-       this->ecc.calculate = bcm_umi_hamming_get_hw_ecc;
-       this->ecc.hwctl = bcm_umi_hamming_enable_hwecc;
-#endif
-
-#if USE_DMA
-       err = nand_dma_init();
-       if (err != 0)
-               goto out_unmap;
-#endif
-
-       /* Figure out the size of the device that we have.
-        * We need to do this to figure out which ECC
-        * layout we'll be using.
-        */
-
-       err = nand_scan_ident(board_mtd, 1, NULL);
-       if (err) {
-               printk(KERN_ERR "nand_scan failed: %d\n", err);
-               goto out_unmap;
-       }
-
-       /* Now that we know the nand size, we can setup the ECC layout */
-
-       switch (board_mtd->writesize) { /* writesize is the pagesize */
-       case 4096:
-               this->ecc.layout = &nand_hw_eccoob_4096;
-               break;
-       case 2048:
-               this->ecc.layout = &nand_hw_eccoob_2048;
-               break;
-       case 512:
-               this->ecc.layout = &nand_hw_eccoob_512;
-               break;
-       default:
-               {
-                       printk(KERN_ERR "NAND - Unrecognized pagesize: %d\n",
-                                        board_mtd->writesize);
-                       err = -EINVAL;
-                       goto out_unmap;
-               }
-       }
-
-#if NAND_ECC_BCH
-       if (board_mtd->writesize > 512) {
-               if (this->bbt_options & NAND_BBT_USE_FLASH)
-                       largepage_bbt.options = NAND_BBT_SCAN2NDPAGE;
-               this->badblock_pattern = &largepage_bbt;
-       }
-
-       this->ecc.strength = 8;
-
-#endif
-
-       /* Now finish off the scan, now that ecc.layout has been initialized. */
-
-       err = nand_scan_tail(board_mtd);
-       if (err) {
-               printk(KERN_ERR "nand_scan failed: %d\n", err);
-               goto out_unmap;
-       }
-
-       /* Register the partitions */
-       board_mtd->name = "bcm_umi-nand";
-       mtd_device_parse_register(board_mtd, NULL, NULL, NULL, 0);
-
-       /* Return happy */
-       return 0;
-out_unmap:
-       iounmap(bcm_umi_io_base);
-out_free:
-       kfree(board_mtd);
-       return err;
-}
-
-static int bcm_umi_nand_remove(struct platform_device *pdev)
-{
-#if USE_DMA
-       nand_dma_term();
-#endif
-
-       /* Release resources, unregister device */
-       nand_release(board_mtd);
-
-       /* unmap physical address */
-       iounmap(bcm_umi_io_base);
-
-       /* Free the MTD device structure */
-       kfree(board_mtd);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int bcm_umi_nand_suspend(struct platform_device *pdev,
-                               pm_message_t state)
-{
-       printk(KERN_ERR "MTD NAND suspend is being called\n");
-       return 0;
-}
-
-static int bcm_umi_nand_resume(struct platform_device *pdev)
-{
-       printk(KERN_ERR "MTD NAND resume is being called\n");
-       return 0;
-}
-#else
-#define bcm_umi_nand_suspend   NULL
-#define bcm_umi_nand_resume    NULL
-#endif
-
-static struct platform_driver nand_driver = {
-       .driver = {
-                  .name = "bcm-nand",
-                  .owner = THIS_MODULE,
-                  },
-       .probe = bcm_umi_nand_probe,
-       .remove = bcm_umi_nand_remove,
-       .suspend = bcm_umi_nand_suspend,
-       .resume = bcm_umi_nand_resume,
-};
-
-module_platform_driver(nand_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Broadcom");
-MODULE_DESCRIPTION("BCM UMI MTD NAND driver");
index 3f1c18599cbd9484096caed856f69c79c61c2bff..ab0caa74eb43e428b57e298b1ff29d4b7a38a0a0 100644 (file)
@@ -566,11 +566,13 @@ static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip
        return 0;
 }
 
-static void bf5xx_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
-               const uint8_t *buf, int oob_required)
+static int bf5xx_nand_write_page_raw(struct mtd_info *mtd,
+               struct nand_chip *chip, const uint8_t *buf, int oob_required)
 {
        bf5xx_nand_write_buf(mtd, buf, mtd->writesize);
        bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       return 0;
 }
 
 /*
index f3f6cfedd69eb5e1367c196de7e8e249740bb77b..2bb7170502c2dde3966b931eb9d1a270e5953feb 100644 (file)
@@ -377,7 +377,7 @@ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
  * @buf:       buffer to store read data
  * @oob_required:      caller expects OOB data read to chip->oob_poi
  *
- * The hw generator calculates the error syndrome automatically. Therefor
+ * The hw generator calculates the error syndrome automatically. Therefore
  * we need a special oob layout and handling.
  */
 static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
@@ -520,7 +520,7 @@ static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = {
 };
 
 
-static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
+static int cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
                                          struct nand_chip *chip,
                                          const uint8_t *buf, int oob_required)
 {
@@ -531,6 +531,8 @@ static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
 
        /* Set up ECC autogeneration */
        cafe->ctl2 |= (1<<30);
+
+       return 0;
 }
 
 static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
@@ -542,9 +544,12 @@ static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
        chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
 
        if (unlikely(raw))
-               chip->ecc.write_page_raw(mtd, chip, buf, oob_required);
+               status = chip->ecc.write_page_raw(mtd, chip, buf, oob_required);
        else
-               chip->ecc.write_page(mtd, chip, buf, oob_required);
+               status = chip->ecc.write_page(mtd, chip, buf, oob_required);
+
+       if (status < 0)
+               return status;
 
        /*
         * Cached progamming disabled for now, Not sure if its worth the
@@ -571,13 +576,6 @@ static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                status = chip->waitfunc(mtd, chip);
        }
 
-#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
-       /* Send command to read back the data */
-       chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
-
-       if (chip->verify_buf(mtd, buf, mtd->writesize))
-               return -EIO;
-#endif
        return 0;
 }
 
index 1024bfc05c8696485861e35b630522c44810d674..39b2ef848811a5d1cf1c7fea98ef8f6168e98c5f 100644 (file)
@@ -76,18 +76,6 @@ static void cmx270_read_buf(struct mtd_info *mtd, u_char *buf, int len)
                *buf++ = readl(this->IO_ADDR_R) >> 16;
 }
 
-static int cmx270_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
-{
-       int i;
-       struct nand_chip *this = mtd->priv;
-
-       for (i=0; i<len; i++)
-               if (buf[i] != (u_char)(readl(this->IO_ADDR_R) >> 16))
-                       return -EFAULT;
-
-       return 0;
-}
-
 static inline void nand_cs_on(void)
 {
        gpio_set_value(GPIO_NAND_CS, 0);
@@ -209,7 +197,6 @@ static int __init cmx270_init(void)
        this->read_byte = cmx270_read_byte;
        this->read_buf = cmx270_read_buf;
        this->write_buf = cmx270_write_buf;
-       this->verify_buf = cmx270_verify_buf;
 
        /* Scan to find existence of the device */
        if (nand_scan (cmx270_nand_mtd, 1)) {
index f1deb1ee2c954c2a15a0c8a60aaf91bc0c9eccb9..945047ad09527ca6a9328f34866ddd5a3a7e7dd8 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 
 #include <linux/platform_data/mtd-davinci.h>
 #include <linux/platform_data/mtd-davinci-aemif.h>
@@ -518,9 +519,75 @@ static struct nand_ecclayout hwecc4_2048 __initconst = {
        },
 };
 
+#if defined(CONFIG_OF)
+static const struct of_device_id davinci_nand_of_match[] = {
+       {.compatible = "ti,davinci-nand", },
+       {},
+}
+MODULE_DEVICE_TABLE(of, davinci_nand_of_match);
+
+static struct davinci_nand_pdata
+       *nand_davinci_get_pdata(struct platform_device *pdev)
+{
+       if (!pdev->dev.platform_data && pdev->dev.of_node) {
+               struct davinci_nand_pdata *pdata;
+               const char *mode;
+               u32 prop;
+               int len;
+
+               pdata =  devm_kzalloc(&pdev->dev,
+                               sizeof(struct davinci_nand_pdata),
+                               GFP_KERNEL);
+               pdev->dev.platform_data = pdata;
+               if (!pdata)
+                       return NULL;
+               if (!of_property_read_u32(pdev->dev.of_node,
+                       "ti,davinci-chipselect", &prop))
+                       pdev->id = prop;
+               if (!of_property_read_u32(pdev->dev.of_node,
+                       "ti,davinci-mask-ale", &prop))
+                       pdata->mask_ale = prop;
+               if (!of_property_read_u32(pdev->dev.of_node,
+                       "ti,davinci-mask-cle", &prop))
+                       pdata->mask_cle = prop;
+               if (!of_property_read_u32(pdev->dev.of_node,
+                       "ti,davinci-mask-chipsel", &prop))
+                       pdata->mask_chipsel = prop;
+               if (!of_property_read_string(pdev->dev.of_node,
+                       "ti,davinci-ecc-mode", &mode)) {
+                       if (!strncmp("none", mode, 4))
+                               pdata->ecc_mode = NAND_ECC_NONE;
+                       if (!strncmp("soft", mode, 4))
+                               pdata->ecc_mode = NAND_ECC_SOFT;
+                       if (!strncmp("hw", mode, 2))
+                               pdata->ecc_mode = NAND_ECC_HW;
+               }
+               if (!of_property_read_u32(pdev->dev.of_node,
+                       "ti,davinci-ecc-bits", &prop))
+                       pdata->ecc_bits = prop;
+               if (!of_property_read_u32(pdev->dev.of_node,
+                       "ti,davinci-nand-buswidth", &prop))
+                       if (prop == 16)
+                               pdata->options |= NAND_BUSWIDTH_16;
+               if (of_find_property(pdev->dev.of_node,
+                       "ti,davinci-nand-use-bbt", &len))
+                       pdata->bbt_options = NAND_BBT_USE_FLASH;
+       }
+
+       return pdev->dev.platform_data;
+}
+#else
+#define davinci_nand_of_match NULL
+static struct davinci_nand_pdata
+       *nand_davinci_get_pdata(struct platform_device *pdev)
+{
+       return pdev->dev.platform_data;
+}
+#endif
+
 static int __init nand_davinci_probe(struct platform_device *pdev)
 {
-       struct davinci_nand_pdata       *pdata = pdev->dev.platform_data;
+       struct davinci_nand_pdata       *pdata;
        struct davinci_nand_info        *info;
        struct resource                 *res1;
        struct resource                 *res2;
@@ -530,6 +597,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        uint32_t                        val;
        nand_ecc_modes_t                ecc_mode;
 
+       pdata = nand_davinci_get_pdata(pdev);
        /* insist on board-specific configuration */
        if (!pdata)
                return -ENODEV;
@@ -656,7 +724,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                goto err_clk;
        }
 
-       ret = clk_enable(info->clk);
+       ret = clk_prepare_enable(info->clk);
        if (ret < 0) {
                dev_dbg(&pdev->dev, "unable to enable AEMIF clock, err %d\n",
                        ret);
@@ -767,7 +835,7 @@ syndrome_done:
 
 err_scan:
 err_timing:
-       clk_disable(info->clk);
+       clk_disable_unprepare(info->clk);
 
 err_clk_enable:
        clk_put(info->clk);
@@ -804,7 +872,7 @@ static int __exit nand_davinci_remove(struct platform_device *pdev)
 
        nand_release(&info->mtd);
 
-       clk_disable(info->clk);
+       clk_disable_unprepare(info->clk);
        clk_put(info->clk);
 
        kfree(info);
@@ -816,6 +884,8 @@ static struct platform_driver nand_davinci_driver = {
        .remove         = __exit_p(nand_davinci_remove),
        .driver         = {
                .name   = "davinci_nand",
+               .owner  = THIS_MODULE,
+               .of_match_table = davinci_nand_of_match,
        },
 };
 MODULE_ALIAS("platform:davinci_nand");
index 0650aafa0dd2238b2af08a1328970e5efb38d24e..e706a237170f503142089cb5644fe2957cafae07 100644 (file)
@@ -1028,7 +1028,7 @@ static void denali_setup_dma(struct denali_nand_info *denali, int op)
 
 /* writes a page. user specifies type, and this function handles the
  * configuration details. */
-static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
+static int write_page(struct mtd_info *mtd, struct nand_chip *chip,
                        const uint8_t *buf, bool raw_xfer)
 {
        struct denali_nand_info *denali = mtd_to_denali(mtd);
@@ -1078,6 +1078,8 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
 
        denali_enable_dma(denali, false);
        dma_sync_single_for_cpu(denali->dev, addr, size, DMA_TO_DEVICE);
+
+       return 0;
 }
 
 /* NAND core entry points */
@@ -1086,24 +1088,24 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
  * writing a page with ECC or without is similar, all the work is done
  * by write_page above.
  * */
-static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+static int denali_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                                const uint8_t *buf, int oob_required)
 {
        /* for regular page writes, we let HW handle all the ECC
         * data written to the device. */
-       write_page(mtd, chip, buf, false);
+       return write_page(mtd, chip, buf, false);
 }
 
 /* This is the callback that the NAND core calls to write a page without ECC.
  * raw access is similar to ECC page writes, so all the work is done in the
  * write_page() function above.
  */
-static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+static int denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
                                        const uint8_t *buf, int oob_required)
 {
        /* for raw page writes, we want to disable ECC and simply write
           whatever data is in the buffer. */
-       write_page(mtd, chip, buf, true);
+       return write_page(mtd, chip, buf, true);
 }
 
 static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
index e2ca067631cf118704c107e2bffbe4ab515abda8..256eb30f6180f655e120e2ad90b988a1b7754e0b 100644 (file)
@@ -376,19 +376,6 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len)
        }
 }
 
-static int doc2000_verifybuf(struct mtd_info *mtd, const u_char *buf, int len)
-{
-       struct nand_chip *this = mtd->priv;
-       struct doc_priv *doc = this->priv;
-       void __iomem *docptr = doc->virtadr;
-       int i;
-
-       for (i = 0; i < len; i++)
-               if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO))
-                       return -EFAULT;
-       return 0;
-}
-
 static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
 {
        struct nand_chip *this = mtd->priv;
@@ -526,26 +513,6 @@ static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len)
        buf[i] = ReadDOC(docptr, LastDataRead);
 }
 
-static int doc2001_verifybuf(struct mtd_info *mtd, const u_char *buf, int len)
-{
-       struct nand_chip *this = mtd->priv;
-       struct doc_priv *doc = this->priv;
-       void __iomem *docptr = doc->virtadr;
-       int i;
-
-       /* Start read pipeline */
-       ReadDOC(docptr, ReadPipeInit);
-
-       for (i = 0; i < len - 1; i++)
-               if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) {
-                       ReadDOC(docptr, LastDataRead);
-                       return i;
-               }
-       if (buf[i] != ReadDOC(docptr, LastDataRead))
-               return i;
-       return 0;
-}
-
 static u_char doc2001plus_read_byte(struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
@@ -610,33 +577,6 @@ static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len)
                printk("\n");
 }
 
-static int doc2001plus_verifybuf(struct mtd_info *mtd, const u_char *buf, int len)
-{
-       struct nand_chip *this = mtd->priv;
-       struct doc_priv *doc = this->priv;
-       void __iomem *docptr = doc->virtadr;
-       int i;
-
-       if (debug)
-               printk("verifybuf of %d bytes: ", len);
-
-       /* Start read pipeline */
-       ReadDOC(docptr, Mplus_ReadPipeInit);
-       ReadDOC(docptr, Mplus_ReadPipeInit);
-
-       for (i = 0; i < len - 2; i++)
-               if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) {
-                       ReadDOC(docptr, Mplus_LastDataRead);
-                       ReadDOC(docptr, Mplus_LastDataRead);
-                       return i;
-               }
-       if (buf[len - 2] != ReadDOC(docptr, Mplus_LastDataRead))
-               return len - 2;
-       if (buf[len - 1] != ReadDOC(docptr, Mplus_LastDataRead))
-               return len - 1;
-       return 0;
-}
-
 static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
 {
        struct nand_chip *this = mtd->priv;
@@ -1432,7 +1372,6 @@ static inline int __init doc2000_init(struct mtd_info *mtd)
        this->read_byte = doc2000_read_byte;
        this->write_buf = doc2000_writebuf;
        this->read_buf = doc2000_readbuf;
-       this->verify_buf = doc2000_verifybuf;
        this->scan_bbt = nftl_scan_bbt;
 
        doc->CDSNControl = CDSN_CTRL_FLASH_IO | CDSN_CTRL_ECC_IO;
@@ -1449,7 +1388,6 @@ static inline int __init doc2001_init(struct mtd_info *mtd)
        this->read_byte = doc2001_read_byte;
        this->write_buf = doc2001_writebuf;
        this->read_buf = doc2001_readbuf;
-       this->verify_buf = doc2001_verifybuf;
 
        ReadDOC(doc->virtadr, ChipID);
        ReadDOC(doc->virtadr, ChipID);
@@ -1480,7 +1418,6 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd)
        this->read_byte = doc2001plus_read_byte;
        this->write_buf = doc2001plus_writebuf;
        this->read_buf = doc2001plus_readbuf;
-       this->verify_buf = doc2001plus_verifybuf;
        this->scan_bbt = inftl_scan_bbt;
        this->cmd_ctrl = NULL;
        this->select_chip = doc2001plus_select_chip;
index a225e49a56235763b35cfd5118f30f7c20c4fb55..799da5d1c85737671d7ab0039b1e022e8c9bbf40 100644 (file)
@@ -378,9 +378,9 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
                 * bit flips(s) are not reported in stats.
                 */
 
-               if (doc->oob_buf[15]) {
+               if (nand->oob_poi[15]) {
                        int bit, numsetbits = 0;
-                       unsigned long written_flag = doc->oob_buf[15];
+                       unsigned long written_flag = nand->oob_poi[15];
                        for_each_set_bit(bit, &written_flag, 8)
                                numsetbits++;
                        if (numsetbits > 4) { /* assume blank */
@@ -428,7 +428,7 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
                /* if error within oob area preceeding ecc bytes... */
                if (errpos[i] > DOCG4_PAGE_SIZE * 8)
                        change_bit(errpos[i] - DOCG4_PAGE_SIZE * 8,
-                                  (unsigned long *)doc->oob_buf);
+                                  (unsigned long *)nand->oob_poi);
 
                else    /* error in page data */
                        change_bit(errpos[i], (unsigned long *)buf);
@@ -748,18 +748,12 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand,
 
        docg4_read_buf(mtd, buf, DOCG4_PAGE_SIZE); /* read the page data */
 
-       /*
-        * Diskonchips read oob immediately after a page read.  Mtd
-        * infrastructure issues a separate command for reading oob after the
-        * page is read.  So we save the oob bytes in a local buffer and just
-        * copy it if the next command reads oob from the same page.
-        */
-
+       /* this device always reads oob after page data */
        /* first 14 oob bytes read from I/O reg */
-       docg4_read_buf(mtd, doc->oob_buf, 14);
+       docg4_read_buf(mtd, nand->oob_poi, 14);
 
        /* last 2 read from another reg */
-       buf16 = (uint16_t *)(doc->oob_buf + 14);
+       buf16 = (uint16_t *)(nand->oob_poi + 14);
        *buf16 = readw(docptr + DOCG4_MYSTERY_REG);
 
        write_nop(docptr);
@@ -782,6 +776,8 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand,
        }
 
        writew(0, docptr + DOC_DATAEND);
+       if (bits_corrected == -EBADMSG)   /* uncorrectable errors */
+               return 0;
        return bits_corrected;
 }
 
@@ -807,21 +803,6 @@ static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
 
        dev_dbg(doc->dev, "%s: page %x\n", __func__, page);
 
-       /*
-        * Oob bytes are read as part of a normal page read.  If the previous
-        * nand command was a read of the page whose oob is now being read, just
-        * copy the oob bytes that we saved in a local buffer and avoid a
-        * separate oob read.
-        */
-       if (doc->last_command.command == NAND_CMD_READ0 &&
-           doc->last_command.page == page) {
-               memcpy(nand->oob_poi, doc->oob_buf, 16);
-               return 0;
-       }
-
-       /*
-        * Separate read of oob data only.
-        */
        docg4_command(mtd, NAND_CMD_READ0, nand->ecc.size, page);
 
        writew(DOC_ECCCONF0_READ_MODE | DOCG4_OOB_SIZE, docptr + DOC_ECCCONF0);
@@ -898,7 +879,7 @@ static void docg4_erase_block(struct mtd_info *mtd, int page)
        write_nop(docptr);
 }
 
-static void write_page(struct mtd_info *mtd, struct nand_chip *nand,
+static int write_page(struct mtd_info *mtd, struct nand_chip *nand,
                       const uint8_t *buf, bool use_ecc)
 {
        struct docg4_priv *doc = nand->priv;
@@ -950,15 +931,17 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *nand,
        write_nop(docptr);
        writew(0, docptr + DOC_DATAEND);
        write_nop(docptr);
+
+       return 0;
 }
 
-static void docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
+static int docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
                                 const uint8_t *buf, int oob_required)
 {
        return write_page(mtd, nand, buf, false);
 }
 
-static void docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand,
+static int docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand,
                             const uint8_t *buf, int oob_required)
 {
        return write_page(mtd, nand, buf, true);
index 784293806110acc63ee4ae062c689dab534860d6..cc1480a5e4c1e0a23f262a4c880890217fa4ca6c 100644 (file)
@@ -614,41 +614,6 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
                        len, avail);
 }
 
-/*
- * Verify buffer against the FCM Controller Data Buffer
- */
-static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
-{
-       struct nand_chip *chip = mtd->priv;
-       struct fsl_elbc_mtd *priv = chip->priv;
-       struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
-       int i;
-
-       if (len < 0) {
-               dev_err(priv->dev, "write_buf of %d bytes", len);
-               return -EINVAL;
-       }
-
-       if ((unsigned int)len >
-                       elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index) {
-               dev_err(priv->dev,
-                       "verify_buf beyond end of buffer "
-                       "(%d requested, %u available)\n",
-                       len, elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
-
-               elbc_fcm_ctrl->index = elbc_fcm_ctrl->read_bytes;
-               return -EINVAL;
-       }
-
-       for (i = 0; i < len; i++)
-               if (in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index + i])
-                               != buf[i])
-                       break;
-
-       elbc_fcm_ctrl->index += len;
-       return i == len && elbc_fcm_ctrl->status == LTESR_CC ? 0 : -EIO;
-}
-
 /* This function is called after Program and Erase Operations to
  * check for success or failure.
  */
@@ -766,11 +731,13 @@ static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 /* ECC will be calculated automatically, and errors will be detected in
  * waitfunc.
  */
-static void fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                                const uint8_t *buf, int oob_required)
 {
        fsl_elbc_write_buf(mtd, buf, mtd->writesize);
        fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       return 0;
 }
 
 static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
@@ -796,7 +763,6 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
        chip->read_byte = fsl_elbc_read_byte;
        chip->write_buf = fsl_elbc_write_buf;
        chip->read_buf = fsl_elbc_read_buf;
-       chip->verify_buf = fsl_elbc_verify_buf;
        chip->select_chip = fsl_elbc_select_chip;
        chip->cmdfunc = fsl_elbc_cmdfunc;
        chip->waitfunc = fsl_elbc_wait;
@@ -805,7 +771,6 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
        chip->bbt_md = &bbt_mirror_descr;
 
        /* set up nand options */
-       chip->options = NAND_NO_READRDY;
        chip->bbt_options = NAND_BBT_USE_FLASH;
 
        chip->controller = &elbc_fcm_ctrl->controller;
@@ -916,7 +881,8 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
        elbc_fcm_ctrl->chips[bank] = priv;
        priv->bank = bank;
        priv->ctrl = fsl_lbc_ctrl_dev;
-       priv->dev = dev;
+       priv->dev = &pdev->dev;
+       dev_set_drvdata(priv->dev, priv);
 
        priv->vbase = ioremap(res.start, resource_size(&res));
        if (!priv->vbase) {
@@ -963,11 +929,10 @@ err:
 
 static int fsl_elbc_nand_remove(struct platform_device *pdev)
 {
-       int i;
        struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
-       for (i = 0; i < MAX_BANKS; i++)
-               if (elbc_fcm_ctrl->chips[i])
-                       fsl_elbc_chip_remove(elbc_fcm_ctrl->chips[i]);
+       struct fsl_elbc_mtd *priv = dev_get_drvdata(&pdev->dev);
+
+       fsl_elbc_chip_remove(priv);
 
        mutex_lock(&fsl_elbc_nand_mutex);
        elbc_fcm_ctrl->counter--;
index 01e2f2e87d8c2b7166f548f6ec14d557b596673b..3551a99076ba51d20addcc41e7e57ae66735c896 100644 (file)
@@ -194,7 +194,7 @@ static int is_blank(struct mtd_info *mtd, unsigned int bufnum)
        struct nand_chip *chip = mtd->priv;
        struct fsl_ifc_mtd *priv = chip->priv;
        u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2);
-       u32 __iomem *mainarea = (u32 *)addr;
+       u32 __iomem *mainarea = (u32 __iomem *)addr;
        u8 __iomem *oob = addr + mtd->writesize;
        int i;
 
@@ -592,8 +592,8 @@ static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
         * next byte.
         */
        if (ifc_nand_ctrl->index < ifc_nand_ctrl->read_bytes) {
-               data = in_be16((uint16_t *)&ifc_nand_ctrl->
-                                       addr[ifc_nand_ctrl->index]);
+               data = in_be16((uint16_t __iomem *)&ifc_nand_ctrl->
+                              addr[ifc_nand_ctrl->index]);
                ifc_nand_ctrl->index += 2;
                return (uint8_t) data;
        }
@@ -627,46 +627,6 @@ static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
                        __func__, len, avail);
 }
 
-/*
- * Verify buffer against the IFC Controller Data Buffer
- */
-static int fsl_ifc_verify_buf(struct mtd_info *mtd,
-                              const u_char *buf, int len)
-{
-       struct nand_chip *chip = mtd->priv;
-       struct fsl_ifc_mtd *priv = chip->priv;
-       struct fsl_ifc_ctrl *ctrl = priv->ctrl;
-       struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;
-       int i;
-
-       if (len < 0) {
-               dev_err(priv->dev, "%s: write_buf of %d bytes", __func__, len);
-               return -EINVAL;
-       }
-
-       if ((unsigned int)len > nctrl->read_bytes - nctrl->index) {
-               dev_err(priv->dev,
-                       "%s: beyond end of buffer (%d requested, %u available)\n",
-                       __func__, len, nctrl->read_bytes - nctrl->index);
-
-               nctrl->index = nctrl->read_bytes;
-               return -EINVAL;
-       }
-
-       for (i = 0; i < len; i++)
-               if (in_8(&nctrl->addr[nctrl->index + i]) != buf[i])
-                       break;
-
-       nctrl->index += len;
-
-       if (i != len)
-               return -EIO;
-       if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC)
-               return -EIO;
-
-       return 0;
-}
-
 /*
  * This function is called after Program and Erase Operations to
  * check for success or failure.
@@ -722,11 +682,13 @@ static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 /* ECC will be calculated automatically, and errors will be detected in
  * waitfunc.
  */
-static void fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                               const uint8_t *buf, int oob_required)
 {
        fsl_ifc_write_buf(mtd, buf, mtd->writesize);
        fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       return 0;
 }
 
 static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
@@ -844,7 +806,6 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
 
        chip->write_buf = fsl_ifc_write_buf;
        chip->read_buf = fsl_ifc_read_buf;
-       chip->verify_buf = fsl_ifc_verify_buf;
        chip->select_chip = fsl_ifc_select_chip;
        chip->cmdfunc = fsl_ifc_cmdfunc;
        chip->waitfunc = fsl_ifc_wait;
@@ -855,7 +816,6 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
        out_be32(&ifc->ifc_nand.ncfgr, 0x0);
 
        /* set up nand options */
-       chip->options = NAND_NO_READRDY;
        chip->bbt_options = NAND_BBT_USE_FLASH;
 
 
index 27000a5f5f47722a1b30707a7b7d56f83b0e0559..bc73bc5f2713695ff0edadc5d6278bf90fa8dce2 100644 (file)
@@ -100,23 +100,6 @@ static void gpio_nand_readbuf(struct mtd_info *mtd, u_char *buf, int len)
        readsb(this->IO_ADDR_R, buf, len);
 }
 
-static int gpio_nand_verifybuf(struct mtd_info *mtd, const u_char *buf, int len)
-{
-       struct nand_chip *this = mtd->priv;
-       unsigned char read, *p = (unsigned char *) buf;
-       int i, err = 0;
-
-       for (i = 0; i < len; i++) {
-               read = readb(this->IO_ADDR_R);
-               if (read != p[i]) {
-                       pr_debug("%s: err at %d (read %04x vs %04x)\n",
-                              __func__, i, read, p[i]);
-                       err = -EFAULT;
-               }
-       }
-       return err;
-}
-
 static void gpio_nand_writebuf16(struct mtd_info *mtd, const u_char *buf,
                                 int len)
 {
@@ -148,26 +131,6 @@ static void gpio_nand_readbuf16(struct mtd_info *mtd, u_char *buf, int len)
        }
 }
 
-static int gpio_nand_verifybuf16(struct mtd_info *mtd, const u_char *buf,
-                                int len)
-{
-       struct nand_chip *this = mtd->priv;
-       unsigned short read, *p = (unsigned short *) buf;
-       int i, err = 0;
-       len >>= 1;
-
-       for (i = 0; i < len; i++) {
-               read = readw(this->IO_ADDR_R);
-               if (read != p[i]) {
-                       pr_debug("%s: err at %d (read %04x vs %04x)\n",
-                              __func__, i, read, p[i]);
-                       err = -EFAULT;
-               }
-       }
-       return err;
-}
-
-
 static int gpio_nand_devready(struct mtd_info *mtd)
 {
        struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd);
@@ -391,11 +354,9 @@ static int __devinit gpio_nand_probe(struct platform_device *dev)
        if (this->options & NAND_BUSWIDTH_16) {
                this->read_buf   = gpio_nand_readbuf16;
                this->write_buf  = gpio_nand_writebuf16;
-               this->verify_buf = gpio_nand_verifybuf16;
        } else {
                this->read_buf   = gpio_nand_readbuf;
                this->write_buf  = gpio_nand_writebuf;
-               this->verify_buf = gpio_nand_verifybuf;
        }
 
        /* set the mtd private data for the nand driver */
@@ -456,20 +417,7 @@ static struct platform_driver gpio_nand_driver = {
        },
 };
 
-static int __init gpio_nand_init(void)
-{
-       printk(KERN_INFO "GPIO NAND driver, Â© 2004 Simtec Electronics\n");
-
-       return platform_driver_register(&gpio_nand_driver);
-}
-
-static void __exit gpio_nand_exit(void)
-{
-       platform_driver_unregister(&gpio_nand_driver);
-}
-
-module_init(gpio_nand_init);
-module_exit(gpio_nand_exit);
+module_platform_driver(gpio_nand_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
index a1f43329ad43d2c7898f7c978cb3f9f15721fe5e..3502accd4bc3cfad059af5445497827fe6c02ddb 100644 (file)
@@ -26,7 +26,7 @@
 #include "gpmi-regs.h"
 #include "bch-regs.h"
 
-struct timing_threshod timing_default_threshold = {
+static struct timing_threshod timing_default_threshold = {
        .max_data_setup_cycles       = (BM_GPMI_TIMING0_DATA_SETUP >>
                                                BP_GPMI_TIMING0_DATA_SETUP),
        .internal_data_setup_in_ns   = 0,
@@ -124,12 +124,42 @@ error:
        return -ETIMEDOUT;
 }
 
+static int __gpmi_enable_clk(struct gpmi_nand_data *this, bool v)
+{
+       struct clk *clk;
+       int ret;
+       int i;
+
+       for (i = 0; i < GPMI_CLK_MAX; i++) {
+               clk = this->resources.clock[i];
+               if (!clk)
+                       break;
+
+               if (v) {
+                       ret = clk_prepare_enable(clk);
+                       if (ret)
+                               goto err_clk;
+               } else {
+                       clk_disable_unprepare(clk);
+               }
+       }
+       return 0;
+
+err_clk:
+       for (; i > 0; i--)
+               clk_disable_unprepare(this->resources.clock[i - 1]);
+       return ret;
+}
+
+#define gpmi_enable_clk(x) __gpmi_enable_clk(x, true)
+#define gpmi_disable_clk(x) __gpmi_enable_clk(x, false)
+
 int gpmi_init(struct gpmi_nand_data *this)
 {
        struct resources *r = &this->resources;
        int ret;
 
-       ret = clk_prepare_enable(r->clock);
+       ret = gpmi_enable_clk(this);
        if (ret)
                goto err_out;
        ret = gpmi_reset_block(r->gpmi_regs, false);
@@ -149,7 +179,7 @@ int gpmi_init(struct gpmi_nand_data *this)
        /* Select BCH ECC. */
        writel(BM_GPMI_CTRL1_BCH_MODE, r->gpmi_regs + HW_GPMI_CTRL1_SET);
 
-       clk_disable_unprepare(r->clock);
+       gpmi_disable_clk(this);
        return 0;
 err_out:
        return ret;
@@ -205,7 +235,7 @@ int bch_set_geometry(struct gpmi_nand_data *this)
        ecc_strength  = bch_geo->ecc_strength >> 1;
        page_size     = bch_geo->page_size;
 
-       ret = clk_prepare_enable(r->clock);
+       ret = gpmi_enable_clk(this);
        if (ret)
                goto err_out;
 
@@ -240,7 +270,7 @@ int bch_set_geometry(struct gpmi_nand_data *this)
        writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
                                r->bch_regs + HW_BCH_CTRL_SET);
 
-       clk_disable_unprepare(r->clock);
+       gpmi_disable_clk(this);
        return 0;
 err_out:
        return ret;
@@ -263,6 +293,7 @@ static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this,
                                        struct gpmi_nfc_hardware_timing *hw)
 {
        struct timing_threshod *nfc = &timing_default_threshold;
+       struct resources *r = &this->resources;
        struct nand_chip *nand = &this->nand;
        struct nand_timing target = this->timing;
        bool improved_timing_is_available;
@@ -302,8 +333,9 @@ static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this,
                (target.tRHOH_in_ns >= 0) ;
 
        /* Inspect the clock. */
+       nfc->clock_frequency_in_hz = clk_get_rate(r->clock[0]);
        clock_frequency_in_hz = nfc->clock_frequency_in_hz;
-       clock_period_in_ns    = 1000000000 / clock_frequency_in_hz;
+       clock_period_in_ns    = NSEC_PER_SEC / clock_frequency_in_hz;
 
        /*
         * The NFC quantizes setup and hold parameters in terms of clock cycles.
@@ -698,17 +730,230 @@ return_results:
        hw->address_setup_in_cycles = address_setup_in_cycles;
        hw->use_half_periods        = dll_use_half_periods;
        hw->sample_delay_factor     = sample_delay_factor;
+       hw->device_busy_timeout     = GPMI_DEFAULT_BUSY_TIMEOUT;
+       hw->wrn_dly_sel             = BV_GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS;
 
        /* Return success. */
        return 0;
 }
 
+/*
+ * <1> Firstly, we should know what's the GPMI-clock means.
+ *     The GPMI-clock is the internal clock in the gpmi nand controller.
+ *     If you set 100MHz to gpmi nand controller, the GPMI-clock's period
+ *     is 10ns. Mark the GPMI-clock's period as GPMI-clock-period.
+ *
+ * <2> Secondly, we should know what's the frequency on the nand chip pins.
+ *     The frequency on the nand chip pins is derived from the GPMI-clock.
+ *     We can get it from the following equation:
+ *
+ *         F = G / (DS + DH)
+ *
+ *         F  : the frequency on the nand chip pins.
+ *         G  : the GPMI clock, such as 100MHz.
+ *         DS : GPMI_HW_GPMI_TIMING0:DATA_SETUP
+ *         DH : GPMI_HW_GPMI_TIMING0:DATA_HOLD
+ *
+ * <3> Thirdly, when the frequency on the nand chip pins is above 33MHz,
+ *     the nand EDO(extended Data Out) timing could be applied.
+ *     The GPMI implements a feedback read strobe to sample the read data.
+ *     The feedback read strobe can be delayed to support the nand EDO timing
+ *     where the read strobe may deasserts before the read data is valid, and
+ *     read data is valid for some time after read strobe.
+ *
+ *     The following figure illustrates some aspects of a NAND Flash read:
+ *
+ *                   |<---tREA---->|
+ *                   |             |
+ *                   |         |   |
+ *                   |<--tRP-->|   |
+ *                   |         |   |
+ *                  __          ___|__________________________________
+ *     RDN            \________/   |
+ *                                 |
+ *                                 /---------\
+ *     Read Data    --------------<           >---------
+ *                                 \---------/
+ *                                |     |
+ *                                |<-D->|
+ *     FeedbackRDN  ________             ____________
+ *                          \___________/
+ *
+ *          D stands for delay, set in the HW_GPMI_CTRL1:RDN_DELAY.
+ *
+ *
+ * <4> Now, we begin to describe how to compute the right RDN_DELAY.
+ *
+ *  4.1) From the aspect of the nand chip pins:
+ *        Delay = (tREA + C - tRP)               {1}
+ *
+ *        tREA : the maximum read access time. From the ONFI nand standards,
+ *               we know that tREA is 16ns in mode 5, tREA is 20ns is mode 4.
+ *               Please check it in : www.onfi.org
+ *        C    : a constant for adjust the delay. default is 4.
+ *        tRP  : the read pulse width.
+ *               Specified by the HW_GPMI_TIMING0:DATA_SETUP:
+ *                    tRP = (GPMI-clock-period) * DATA_SETUP
+ *
+ *  4.2) From the aspect of the GPMI nand controller:
+ *         Delay = RDN_DELAY * 0.125 * RP        {2}
+ *
+ *         RP   : the DLL reference period.
+ *            if (GPMI-clock-period > DLL_THRETHOLD)
+ *                   RP = GPMI-clock-period / 2;
+ *            else
+ *                   RP = GPMI-clock-period;
+ *
+ *            Set the HW_GPMI_CTRL1:HALF_PERIOD if GPMI-clock-period
+ *            is greater DLL_THRETHOLD. In other SOCs, the DLL_THRETHOLD
+ *            is 16ns, but in mx6q, we use 12ns.
+ *
+ *  4.3) since {1} equals {2}, we get:
+ *
+ *                    (tREA + 4 - tRP) * 8
+ *         RDN_DELAY = ---------------------     {3}
+ *                           RP
+ *
+ *  4.4) We only support the fastest asynchronous mode of ONFI nand.
+ *       For some ONFI nand, the mode 4 is the fastest mode;
+ *       while for some ONFI nand, the mode 5 is the fastest mode.
+ *       So we only support the mode 4 and mode 5. It is no need to
+ *       support other modes.
+ */
+static void gpmi_compute_edo_timing(struct gpmi_nand_data *this,
+                       struct gpmi_nfc_hardware_timing *hw)
+{
+       struct resources *r = &this->resources;
+       unsigned long rate = clk_get_rate(r->clock[0]);
+       int mode = this->timing_mode;
+       int dll_threshold = 16; /* in ns */
+       unsigned long delay;
+       unsigned long clk_period;
+       int t_rea;
+       int c = 4;
+       int t_rp;
+       int rp;
+
+       /*
+        * [1] for GPMI_HW_GPMI_TIMING0:
+        *     The async mode requires 40MHz for mode 4, 50MHz for mode 5.
+        *     The GPMI can support 100MHz at most. So if we want to
+        *     get the 40MHz or 50MHz, we have to set DS=1, DH=1.
+        *     Set the ADDRESS_SETUP to 0 in mode 4.
+        */
+       hw->data_setup_in_cycles = 1;
+       hw->data_hold_in_cycles = 1;
+       hw->address_setup_in_cycles = ((mode == 5) ? 1 : 0);
+
+       /* [2] for GPMI_HW_GPMI_TIMING1 */
+       hw->device_busy_timeout = 0x9000;
+
+       /* [3] for GPMI_HW_GPMI_CTRL1 */
+       hw->wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
+
+       if (GPMI_IS_MX6Q(this))
+               dll_threshold = 12;
+
+       /*
+        * Enlarge 10 times for the numerator and denominator in {3}.
+        * This make us to get more accurate result.
+        */
+       clk_period = NSEC_PER_SEC / (rate / 10);
+       dll_threshold *= 10;
+       t_rea = ((mode == 5) ? 16 : 20) * 10;
+       c *= 10;
+
+       t_rp = clk_period * 1; /* DATA_SETUP is 1 */
+
+       if (clk_period > dll_threshold) {
+               hw->use_half_periods = 1;
+               rp = clk_period / 2;
+       } else {
+               hw->use_half_periods = 0;
+               rp = clk_period;
+       }
+
+       /*
+        * Multiply the numerator with 10, we could do a round off:
+        *      7.8 round up to 8; 7.4 round down to 7.
+        */
+       delay  = (((t_rea + c - t_rp) * 8) * 10) / rp;
+       delay = (delay + 5) / 10;
+
+       hw->sample_delay_factor = delay;
+}
+
+static int enable_edo_mode(struct gpmi_nand_data *this, int mode)
+{
+       struct resources  *r = &this->resources;
+       struct nand_chip *nand = &this->nand;
+       struct mtd_info  *mtd = &this->mtd;
+       uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {};
+       unsigned long rate;
+       int ret;
+
+       nand->select_chip(mtd, 0);
+
+       /* [1] send SET FEATURE commond to NAND */
+       feature[0] = mode;
+       ret = nand->onfi_set_features(mtd, nand,
+                               ONFI_FEATURE_ADDR_TIMING_MODE, feature);
+       if (ret)
+               goto err_out;
+
+       /* [2] send GET FEATURE command to double-check the timing mode */
+       memset(feature, 0, ONFI_SUBFEATURE_PARAM_LEN);
+       ret = nand->onfi_get_features(mtd, nand,
+                               ONFI_FEATURE_ADDR_TIMING_MODE, feature);
+       if (ret || feature[0] != mode)
+               goto err_out;
+
+       nand->select_chip(mtd, -1);
+
+       /* [3] set the main IO clock, 100MHz for mode 5, 80MHz for mode 4. */
+       rate = (mode == 5) ? 100000000 : 80000000;
+       clk_set_rate(r->clock[0], rate);
+
+       /* Let the gpmi_begin() re-compute the timing again. */
+       this->flags &= ~GPMI_TIMING_INIT_OK;
+
+       this->flags |= GPMI_ASYNC_EDO_ENABLED;
+       this->timing_mode = mode;
+       dev_info(this->dev, "enable the asynchronous EDO mode %d\n", mode);
+       return 0;
+
+err_out:
+       nand->select_chip(mtd, -1);
+       dev_err(this->dev, "mode:%d ,failed in set feature.\n", mode);
+       return -EINVAL;
+}
+
+int gpmi_extra_init(struct gpmi_nand_data *this)
+{
+       struct nand_chip *chip = &this->nand;
+
+       /* Enable the asynchronous EDO feature. */
+       if (GPMI_IS_MX6Q(this) && chip->onfi_version) {
+               int mode = onfi_get_async_timing_mode(chip);
+
+               /* We only support the timing mode 4 and mode 5. */
+               if (mode & ONFI_TIMING_MODE_5)
+                       mode = 5;
+               else if (mode & ONFI_TIMING_MODE_4)
+                       mode = 4;
+               else
+                       return 0;
+
+               return enable_edo_mode(this, mode);
+       }
+       return 0;
+}
+
 /* Begin the I/O */
 void gpmi_begin(struct gpmi_nand_data *this)
 {
        struct resources *r = &this->resources;
-       struct timing_threshod *nfc = &timing_default_threshold;
-       unsigned char  *gpmi_regs = r->gpmi_regs;
+       void __iomem *gpmi_regs = r->gpmi_regs;
        unsigned int   clock_period_in_ns;
        uint32_t       reg;
        unsigned int   dll_wait_time_in_us;
@@ -716,60 +961,66 @@ void gpmi_begin(struct gpmi_nand_data *this)
        int ret;
 
        /* Enable the clock. */
-       ret = clk_prepare_enable(r->clock);
+       ret = gpmi_enable_clk(this);
        if (ret) {
                pr_err("We failed in enable the clk\n");
                goto err_out;
        }
 
-       /* set ready/busy timeout */
-       writel(0x500 << BP_GPMI_TIMING1_BUSY_TIMEOUT,
-               gpmi_regs + HW_GPMI_TIMING1);
-
-       /* Get the timing information we need. */
-       nfc->clock_frequency_in_hz = clk_get_rate(r->clock);
-       clock_period_in_ns = 1000000000 / nfc->clock_frequency_in_hz;
+       /* Only initialize the timing once */
+       if (this->flags & GPMI_TIMING_INIT_OK)
+               return;
+       this->flags |= GPMI_TIMING_INIT_OK;
 
-       gpmi_nfc_compute_hardware_timing(this, &hw);
+       if (this->flags & GPMI_ASYNC_EDO_ENABLED)
+               gpmi_compute_edo_timing(this, &hw);
+       else
+               gpmi_nfc_compute_hardware_timing(this, &hw);
 
-       /* Set up all the simple timing parameters. */
+       /* [1] Set HW_GPMI_TIMING0 */
        reg = BF_GPMI_TIMING0_ADDRESS_SETUP(hw.address_setup_in_cycles) |
                BF_GPMI_TIMING0_DATA_HOLD(hw.data_hold_in_cycles)         |
                BF_GPMI_TIMING0_DATA_SETUP(hw.data_setup_in_cycles)       ;
 
        writel(reg, gpmi_regs + HW_GPMI_TIMING0);
 
-       /*
-        * DLL_ENABLE must be set to 0 when setting RDN_DELAY or HALF_PERIOD.
-        */
+       /* [2] Set HW_GPMI_TIMING1 */
+       writel(BF_GPMI_TIMING1_BUSY_TIMEOUT(hw.device_busy_timeout),
+               gpmi_regs + HW_GPMI_TIMING1);
+
+       /* [3] The following code is to set the HW_GPMI_CTRL1. */
+
+       /* Set the WRN_DLY_SEL */
+       writel(BM_GPMI_CTRL1_WRN_DLY_SEL, gpmi_regs + HW_GPMI_CTRL1_CLR);
+       writel(BF_GPMI_CTRL1_WRN_DLY_SEL(hw.wrn_dly_sel),
+                                       gpmi_regs + HW_GPMI_CTRL1_SET);
+
+       /* DLL_ENABLE must be set to 0 when setting RDN_DELAY or HALF_PERIOD. */
        writel(BM_GPMI_CTRL1_DLL_ENABLE, gpmi_regs + HW_GPMI_CTRL1_CLR);
 
        /* Clear out the DLL control fields. */
-       writel(BM_GPMI_CTRL1_RDN_DELAY,   gpmi_regs + HW_GPMI_CTRL1_CLR);
-       writel(BM_GPMI_CTRL1_HALF_PERIOD, gpmi_regs + HW_GPMI_CTRL1_CLR);
+       reg = BM_GPMI_CTRL1_RDN_DELAY | BM_GPMI_CTRL1_HALF_PERIOD;
+       writel(reg, gpmi_regs + HW_GPMI_CTRL1_CLR);
 
        /* If no sample delay is called for, return immediately. */
        if (!hw.sample_delay_factor)
                return;
 
-       /* Configure the HALF_PERIOD flag. */
-       if (hw.use_half_periods)
-               writel(BM_GPMI_CTRL1_HALF_PERIOD,
-                                               gpmi_regs + HW_GPMI_CTRL1_SET);
+       /* Set RDN_DELAY or HALF_PERIOD. */
+       reg = ((hw.use_half_periods) ? BM_GPMI_CTRL1_HALF_PERIOD : 0)
+               | BF_GPMI_CTRL1_RDN_DELAY(hw.sample_delay_factor);
 
-       /* Set the delay factor. */
-       writel(BF_GPMI_CTRL1_RDN_DELAY(hw.sample_delay_factor),
-                                               gpmi_regs + HW_GPMI_CTRL1_SET);
+       writel(reg, gpmi_regs + HW_GPMI_CTRL1_SET);
 
-       /* Enable the DLL. */
+       /* At last, we enable the DLL. */
        writel(BM_GPMI_CTRL1_DLL_ENABLE, gpmi_regs + HW_GPMI_CTRL1_SET);
 
        /*
         * After we enable the GPMI DLL, we have to wait 64 clock cycles before
-        * we can use the GPMI.
-        *
-        * Calculate the amount of time we need to wait, in microseconds.
+        * we can use the GPMI. Calculate the amount of time we need to wait,
+        * in microseconds.
         */
+       clock_period_in_ns = NSEC_PER_SEC / clk_get_rate(r->clock[0]);
        dll_wait_time_in_us = (clock_period_in_ns * 64) / 1000;
 
        if (!dll_wait_time_in_us)
@@ -784,8 +1035,7 @@ err_out:
 
 void gpmi_end(struct gpmi_nand_data *this)
 {
-       struct resources *r = &this->resources;
-       clk_disable_unprepare(r->clock);
+       gpmi_disable_clk(this);
 }
 
 /* Clears a BCH interrupt. */
index a6cad5caba788fe8b665270a3fc7494d7a071887..d79696b2f19b8a50cf2c91f6c88225925a478d43 100644 (file)
@@ -18,6 +18,9 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
@@ -27,6 +30,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_mtd.h>
 #include "gpmi-nand.h"
 
 /* add our owner bbt descriptor */
@@ -113,7 +117,7 @@ int common_nfc_set_geometry(struct gpmi_nand_data *this)
        /* We use the same ECC strength for all chunks. */
        geo->ecc_strength = get_ecc_strength(this);
        if (!geo->ecc_strength) {
-               pr_err("We get a wrong ECC strength.\n");
+               pr_err("wrong ECC strength.\n");
                return -EINVAL;
        }
 
@@ -316,7 +320,7 @@ acquire_register_block(struct gpmi_nand_data *this, const char *res_name)
        struct platform_device *pdev = this->pdev;
        struct resources *res = &this->resources;
        struct resource *r;
-       void *p;
+       void __iomem *p;
 
        r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
        if (!r) {
@@ -423,8 +427,8 @@ static int __devinit acquire_dma_channels(struct gpmi_nand_data *this)
        struct platform_device *pdev = this->pdev;
        struct resource *r_dma;
        struct device_node *dn;
-       int dma_channel;
-       unsigned int ret;
+       u32 dma_channel;
+       int ret;
        struct dma_chan *dma_chan;
        dma_cap_mask_t mask;
 
@@ -464,9 +468,73 @@ acquire_err:
        return -EINVAL;
 }
 
+static void gpmi_put_clks(struct gpmi_nand_data *this)
+{
+       struct resources *r = &this->resources;
+       struct clk *clk;
+       int i;
+
+       for (i = 0; i < GPMI_CLK_MAX; i++) {
+               clk = r->clock[i];
+               if (clk) {
+                       clk_put(clk);
+                       r->clock[i] = NULL;
+               }
+       }
+}
+
+static char *extra_clks_for_mx6q[GPMI_CLK_MAX] = {
+       "gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch",
+};
+
+static int __devinit gpmi_get_clks(struct gpmi_nand_data *this)
+{
+       struct resources *r = &this->resources;
+       char **extra_clks = NULL;
+       struct clk *clk;
+       int i;
+
+       /* The main clock is stored in the first. */
+       r->clock[0] = clk_get(this->dev, "gpmi_io");
+       if (IS_ERR(r->clock[0]))
+               goto err_clock;
+
+       /* Get extra clocks */
+       if (GPMI_IS_MX6Q(this))
+               extra_clks = extra_clks_for_mx6q;
+       if (!extra_clks)
+               return 0;
+
+       for (i = 1; i < GPMI_CLK_MAX; i++) {
+               if (extra_clks[i - 1] == NULL)
+                       break;
+
+               clk = clk_get(this->dev, extra_clks[i - 1]);
+               if (IS_ERR(clk))
+                       goto err_clock;
+
+               r->clock[i] = clk;
+       }
+
+       if (GPMI_IS_MX6Q(this))
+               /*
+                * Set the default value for the gpmi clock in mx6q:
+                *
+                * If you want to use the ONFI nand which is in the
+                * Synchronous Mode, you should change the clock as you need.
+                */
+               clk_set_rate(r->clock[0], 22000000);
+
+       return 0;
+
+err_clock:
+       dev_dbg(this->dev, "failed in finding the clocks.\n");
+       gpmi_put_clks(this);
+       return -ENOMEM;
+}
+
 static int __devinit acquire_resources(struct gpmi_nand_data *this)
 {
-       struct resources *res = &this->resources;
        struct pinctrl *pinctrl;
        int ret;
 
@@ -492,12 +560,9 @@ static int __devinit acquire_resources(struct gpmi_nand_data *this)
                goto exit_pin;
        }
 
-       res->clock = clk_get(&this->pdev->dev, NULL);
-       if (IS_ERR(res->clock)) {
-               pr_err("can not get the clock\n");
-               ret = -ENOENT;
+       ret = gpmi_get_clks(this);
+       if (ret)
                goto exit_clock;
-       }
        return 0;
 
 exit_clock:
@@ -512,9 +577,7 @@ exit_regs:
 
 static void release_resources(struct gpmi_nand_data *this)
 {
-       struct resources *r = &this->resources;
-
-       clk_put(r->clock);
+       gpmi_put_clks(this);
        release_register_block(this);
        release_bch_irq(this);
        release_dma_channels(this);
@@ -667,12 +730,12 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
        struct device *dev = this->dev;
 
        /* [1] Allocate a command buffer. PAGE_SIZE is enough. */
-       this->cmd_buffer = kzalloc(PAGE_SIZE, GFP_DMA);
+       this->cmd_buffer = kzalloc(PAGE_SIZE, GFP_DMA | GFP_KERNEL);
        if (this->cmd_buffer == NULL)
                goto error_alloc;
 
        /* [2] Allocate a read/write data buffer. PAGE_SIZE is enough. */
-       this->data_buffer_dma = kzalloc(PAGE_SIZE, GFP_DMA);
+       this->data_buffer_dma = kzalloc(PAGE_SIZE, GFP_DMA | GFP_KERNEL);
        if (this->data_buffer_dma == NULL)
                goto error_alloc;
 
@@ -930,7 +993,7 @@ exit_nfc:
        return ret;
 }
 
-static void gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                                const uint8_t *buf, int oob_required)
 {
        struct gpmi_nand_data *this = chip->priv;
@@ -972,7 +1035,7 @@ static void gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                                &payload_virt, &payload_phys);
                if (ret) {
                        pr_err("Inadequate payload DMA buffer\n");
-                       return;
+                       return 0;
                }
 
                ret = send_page_prepare(this,
@@ -1002,6 +1065,8 @@ exit_auxiliary:
                                nfc_geo->payload_size,
                                payload_virt, payload_phys);
        }
+
+       return 0;
 }
 
 /*
@@ -1064,6 +1129,9 @@ exit_auxiliary:
  * ECC-based or raw view of the page is implicit in which function it calls
  * (there is a similar pair of ECC-based/raw functions for writing).
  *
+ * FIXME: The following paragraph is incorrect, now that there exist
+ * ecc.read_oob_raw and ecc.write_oob_raw functions.
+ *
  * Since MTD assumes the OOB is not covered by ECC, there is no pair of
  * ECC-based/raw functions for reading or or writing the OOB. The fact that the
  * caller wants an ECC-based or raw view of the page is not propagated down to
@@ -1190,7 +1258,6 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this)
        unsigned int search_area_size_in_strides;
        unsigned int stride;
        unsigned int page;
-       loff_t byte;
        uint8_t *buffer = chip->buffers->databuf;
        int saved_chip_number;
        int found_an_ncb_fingerprint = false;
@@ -1207,9 +1274,8 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this)
        dev_dbg(dev, "Scanning for an NCB fingerprint...\n");
 
        for (stride = 0; stride < search_area_size_in_strides; stride++) {
-               /* Compute the page and byte addresses. */
+               /* Compute the page addresses. */
                page = stride * rom_geo->stride_size_in_pages;
-               byte = page   * mtd->writesize;
 
                dev_dbg(dev, "Looking for a fingerprint in page 0x%x\n", page);
 
@@ -1251,7 +1317,6 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
        unsigned int block;
        unsigned int stride;
        unsigned int page;
-       loff_t       byte;
        uint8_t      *buffer = chip->buffers->databuf;
        int saved_chip_number;
        int status;
@@ -1300,9 +1365,8 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
        /* Loop through the first search area, writing NCB fingerprints. */
        dev_dbg(dev, "Writing NCB fingerprints...\n");
        for (stride = 0; stride < search_area_size_in_strides; stride++) {
-               /* Compute the page and byte addresses. */
+               /* Compute the page addresses. */
                page = stride * rom_geo->stride_size_in_pages;
-               byte = page   * mtd->writesize;
 
                /* Write the first page of the current stride. */
                dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page);
@@ -1436,6 +1500,7 @@ static int gpmi_pre_bbt_scan(struct gpmi_nand_data  *this)
        /* Adjust the ECC strength according to the chip. */
        this->nand.ecc.strength = this->bch_geometry.ecc_strength;
        this->mtd.ecc_strength = this->bch_geometry.ecc_strength;
+       this->mtd.bitflip_threshold = this->bch_geometry.ecc_strength;
 
        /* NAND boot init, depends on the gpmi_set_geometry(). */
        return nand_boot_init(this);
@@ -1452,11 +1517,19 @@ static int gpmi_scan_bbt(struct mtd_info *mtd)
        if (ret)
                return ret;
 
+       /*
+        * Can we enable the extra features? such as EDO or Sync mode.
+        *
+        * We do not check the return value now. That's means if we fail in
+        * enable the extra features, we still can run in the normal way.
+        */
+       gpmi_extra_init(this);
+
        /* use the default BBT implementation */
        return nand_default_bbt(mtd);
 }
 
-void gpmi_nfc_exit(struct gpmi_nand_data *this)
+static void gpmi_nfc_exit(struct gpmi_nand_data *this)
 {
        nand_release(&this->mtd);
        gpmi_free_dma_buffer(this);
@@ -1497,6 +1570,8 @@ static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this)
        chip->ecc.size          = 1;
        chip->ecc.strength      = 8;
        chip->ecc.layout        = &gpmi_hw_ecclayout;
+       if (of_get_nand_on_flash_bbt(this->dev->of_node))
+               chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
 
        /* Allocate a temporary DMA buffer for reading ID in the nand_scan() */
        this->bch_geometry.payload_size = 1024;
@@ -1579,6 +1654,8 @@ static int __devinit gpmi_nand_probe(struct platform_device *pdev)
        if (ret)
                goto exit_nfc_init;
 
+       dev_info(this->dev, "driver registered.\n");
+
        return 0;
 
 exit_nfc_init:
@@ -1586,10 +1663,12 @@ exit_nfc_init:
 exit_acquire_resources:
        platform_set_drvdata(pdev, NULL);
        kfree(this);
+       dev_err(this->dev, "driver registration failed: %d\n", ret);
+
        return ret;
 }
 
-static int __exit gpmi_nand_remove(struct platform_device *pdev)
+static int __devexit gpmi_nand_remove(struct platform_device *pdev)
 {
        struct gpmi_nand_data *this = platform_get_drvdata(pdev);
 
@@ -1606,29 +1685,10 @@ static struct platform_driver gpmi_nand_driver = {
                .of_match_table = gpmi_nand_id_table,
        },
        .probe   = gpmi_nand_probe,
-       .remove  = __exit_p(gpmi_nand_remove),
+       .remove  = __devexit_p(gpmi_nand_remove),
        .id_table = gpmi_ids,
 };
-
-static int __init gpmi_nand_init(void)
-{
-       int err;
-
-       err = platform_driver_register(&gpmi_nand_driver);
-       if (err == 0)
-               printk(KERN_INFO "GPMI NAND driver registered. (IMX)\n");
-       else
-               pr_err("i.MX GPMI NAND driver registration failed\n");
-       return err;
-}
-
-static void __exit gpmi_nand_exit(void)
-{
-       platform_driver_unregister(&gpmi_nand_driver);
-}
-
-module_init(gpmi_nand_init);
-module_exit(gpmi_nand_exit);
+module_platform_driver(gpmi_nand_driver);
 
 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 MODULE_DESCRIPTION("i.MX GPMI NAND Flash Controller Driver");
index ce5daa1609203923caee19f576be884c27919a97..7ac25c1e58f96aedc383e96d8c0897d6903c872f 100644 (file)
 #include <linux/dma-mapping.h>
 #include <linux/fsl/mxs-dma.h>
 
+#define GPMI_CLK_MAX 5 /* MX6Q needs five clocks */
 struct resources {
-       void          *gpmi_regs;
-       void          *bch_regs;
+       void __iomem  *gpmi_regs;
+       void __iomem  *bch_regs;
        unsigned int  bch_low_interrupt;
        unsigned int  bch_high_interrupt;
        unsigned int  dma_low_channel;
        unsigned int  dma_high_channel;
-       struct clk    *clock;
+       struct clk    *clock[GPMI_CLK_MAX];
 };
 
 /**
@@ -121,6 +122,11 @@ struct nand_timing {
 };
 
 struct gpmi_nand_data {
+       /* flags */
+#define GPMI_ASYNC_EDO_ENABLED (1 << 0)
+#define GPMI_TIMING_INIT_OK    (1 << 1)
+       int                     flags;
+
        /* System Interface */
        struct device           *dev;
        struct platform_device  *pdev;
@@ -131,6 +137,7 @@ struct gpmi_nand_data {
 
        /* Flash Hardware */
        struct nand_timing      timing;
+       int                     timing_mode;
 
        /* BCH */
        struct bch_geometry     bch_geometry;
@@ -188,16 +195,28 @@ struct gpmi_nand_data {
  * @data_setup_in_cycles:      The data setup time, in cycles.
  * @data_hold_in_cycles:       The data hold time, in cycles.
  * @address_setup_in_cycles:   The address setup time, in cycles.
+ * @device_busy_timeout:       The timeout waiting for NAND Ready/Busy,
+ *                             this value is the number of cycles multiplied
+ *                             by 4096.
  * @use_half_periods:          Indicates the clock is running slowly, so the
  *                             NFC DLL should use half-periods.
  * @sample_delay_factor:       The sample delay factor.
+ * @wrn_dly_sel:               The delay on the GPMI write strobe.
  */
 struct gpmi_nfc_hardware_timing {
+       /* for HW_GPMI_TIMING0 */
        uint8_t  data_setup_in_cycles;
        uint8_t  data_hold_in_cycles;
        uint8_t  address_setup_in_cycles;
+
+       /* for HW_GPMI_TIMING1 */
+       uint16_t device_busy_timeout;
+#define GPMI_DEFAULT_BUSY_TIMEOUT      0x500 /* default busy timeout value.*/
+
+       /* for HW_GPMI_CTRL1 */
        bool     use_half_periods;
        uint8_t  sample_delay_factor;
+       uint8_t  wrn_dly_sel;
 };
 
 /**
@@ -246,6 +265,7 @@ extern int start_dma_with_bch_irq(struct gpmi_nand_data *,
 
 /* GPMI-NAND helper function library */
 extern int gpmi_init(struct gpmi_nand_data *);
+extern int gpmi_extra_init(struct gpmi_nand_data *);
 extern void gpmi_clear_bch(struct gpmi_nand_data *);
 extern void gpmi_dump_info(struct gpmi_nand_data *);
 extern int bch_set_geometry(struct gpmi_nand_data *);
index 83431240e2f275a9148686a5a736143a834aa6d8..53397cc290fcb522c921d746e768a649de663335 100644 (file)
 #define HW_GPMI_CTRL1_CLR                              0x00000068
 #define HW_GPMI_CTRL1_TOG                              0x0000006c
 
+#define BP_GPMI_CTRL1_WRN_DLY_SEL                      22
+#define BM_GPMI_CTRL1_WRN_DLY_SEL      (0x3 << BP_GPMI_CTRL1_WRN_DLY_SEL)
+#define BF_GPMI_CTRL1_WRN_DLY_SEL(v)  \
+       (((v) << BP_GPMI_CTRL1_WRN_DLY_SEL) & BM_GPMI_CTRL1_WRN_DLY_SEL)
+#define BV_GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS             0x0
+#define BV_GPMI_CTRL1_WRN_DLY_SEL_6_TO_10NS            0x1
+#define BV_GPMI_CTRL1_WRN_DLY_SEL_7_TO_12NS            0x2
+#define BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY             0x3
+
 #define BM_GPMI_CTRL1_BCH_MODE                         (1 << 18)
 
 #define BP_GPMI_CTRL1_DLL_ENABLE                       17
 
 #define HW_GPMI_TIMING1                                        0x00000080
 #define BP_GPMI_TIMING1_BUSY_TIMEOUT                   16
+#define BM_GPMI_TIMING1_BUSY_TIMEOUT   (0xffff << BP_GPMI_TIMING1_BUSY_TIMEOUT)
+#define BF_GPMI_TIMING1_BUSY_TIMEOUT(v)                \
+       (((v) << BP_GPMI_TIMING1_BUSY_TIMEOUT) & BM_GPMI_TIMING1_BUSY_TIMEOUT)
 
 #define HW_GPMI_TIMING2                                        0x00000090
 #define HW_GPMI_DATA                                   0x000000a0
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c
new file mode 100644 (file)
index 0000000..c29b7ac
--- /dev/null
@@ -0,0 +1,924 @@
+/*
+ * Driver for NAND MLC Controller in LPC32xx
+ *
+ * Author: Roland Stigge <stigge@antcom.de>
+ *
+ * Copyright Â© 2011 WORK Microwave GmbH
+ * Copyright Â© 2011, 2012 Roland Stigge
+ *
+ * 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.
+ *
+ *
+ * NAND Flash Controller Operation:
+ * - Read: Auto Decode
+ * - Write: Auto Encode
+ * - Tested Page Sizes: 2048, 4096
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_mtd.h>
+#include <linux/of_gpio.h>
+#include <linux/mtd/lpc32xx_mlc.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/mtd/nand_ecc.h>
+
+#define DRV_NAME "lpc32xx_mlc"
+
+/**********************************************************************
+* MLC NAND controller register offsets
+**********************************************************************/
+
+#define MLC_BUFF(x)                    (x + 0x00000)
+#define MLC_DATA(x)                    (x + 0x08000)
+#define MLC_CMD(x)                     (x + 0x10000)
+#define MLC_ADDR(x)                    (x + 0x10004)
+#define MLC_ECC_ENC_REG(x)             (x + 0x10008)
+#define MLC_ECC_DEC_REG(x)             (x + 0x1000C)
+#define MLC_ECC_AUTO_ENC_REG(x)                (x + 0x10010)
+#define MLC_ECC_AUTO_DEC_REG(x)                (x + 0x10014)
+#define MLC_RPR(x)                     (x + 0x10018)
+#define MLC_WPR(x)                     (x + 0x1001C)
+#define MLC_RUBP(x)                    (x + 0x10020)
+#define MLC_ROBP(x)                    (x + 0x10024)
+#define MLC_SW_WP_ADD_LOW(x)           (x + 0x10028)
+#define MLC_SW_WP_ADD_HIG(x)           (x + 0x1002C)
+#define MLC_ICR(x)                     (x + 0x10030)
+#define MLC_TIME_REG(x)                        (x + 0x10034)
+#define MLC_IRQ_MR(x)                  (x + 0x10038)
+#define MLC_IRQ_SR(x)                  (x + 0x1003C)
+#define MLC_LOCK_PR(x)                 (x + 0x10044)
+#define MLC_ISR(x)                     (x + 0x10048)
+#define MLC_CEH(x)                     (x + 0x1004C)
+
+/**********************************************************************
+* MLC_CMD bit definitions
+**********************************************************************/
+#define MLCCMD_RESET                   0xFF
+
+/**********************************************************************
+* MLC_ICR bit definitions
+**********************************************************************/
+#define MLCICR_WPROT                   (1 << 3)
+#define MLCICR_LARGEBLOCK              (1 << 2)
+#define MLCICR_LONGADDR                        (1 << 1)
+#define MLCICR_16BIT                   (1 << 0)  /* unsupported by LPC32x0! */
+
+/**********************************************************************
+* MLC_TIME_REG bit definitions
+**********************************************************************/
+#define MLCTIMEREG_TCEA_DELAY(n)       (((n) & 0x03) << 24)
+#define MLCTIMEREG_BUSY_DELAY(n)       (((n) & 0x1F) << 19)
+#define MLCTIMEREG_NAND_TA(n)          (((n) & 0x07) << 16)
+#define MLCTIMEREG_RD_HIGH(n)          (((n) & 0x0F) << 12)
+#define MLCTIMEREG_RD_LOW(n)           (((n) & 0x0F) << 8)
+#define MLCTIMEREG_WR_HIGH(n)          (((n) & 0x0F) << 4)
+#define MLCTIMEREG_WR_LOW(n)           (((n) & 0x0F) << 0)
+
+/**********************************************************************
+* MLC_IRQ_MR and MLC_IRQ_SR bit definitions
+**********************************************************************/
+#define MLCIRQ_NAND_READY              (1 << 5)
+#define MLCIRQ_CONTROLLER_READY                (1 << 4)
+#define MLCIRQ_DECODE_FAILURE          (1 << 3)
+#define MLCIRQ_DECODE_ERROR            (1 << 2)
+#define MLCIRQ_ECC_READY               (1 << 1)
+#define MLCIRQ_WRPROT_FAULT            (1 << 0)
+
+/**********************************************************************
+* MLC_LOCK_PR bit definitions
+**********************************************************************/
+#define MLCLOCKPR_MAGIC                        0xA25E
+
+/**********************************************************************
+* MLC_ISR bit definitions
+**********************************************************************/
+#define MLCISR_DECODER_FAILURE         (1 << 6)
+#define MLCISR_ERRORS                  ((1 << 4) | (1 << 5))
+#define MLCISR_ERRORS_DETECTED         (1 << 3)
+#define MLCISR_ECC_READY               (1 << 2)
+#define MLCISR_CONTROLLER_READY                (1 << 1)
+#define MLCISR_NAND_READY              (1 << 0)
+
+/**********************************************************************
+* MLC_CEH bit definitions
+**********************************************************************/
+#define MLCCEH_NORMAL                  (1 << 0)
+
+struct lpc32xx_nand_cfg_mlc {
+       uint32_t tcea_delay;
+       uint32_t busy_delay;
+       uint32_t nand_ta;
+       uint32_t rd_high;
+       uint32_t rd_low;
+       uint32_t wr_high;
+       uint32_t wr_low;
+       int wp_gpio;
+       struct mtd_partition *parts;
+       unsigned num_parts;
+};
+
+static struct nand_ecclayout lpc32xx_nand_oob = {
+       .eccbytes = 40,
+       .eccpos = { 6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+                  22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+                  38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+                  54, 55, 56, 57, 58, 59, 60, 61, 62, 63 },
+       .oobfree = {
+               { .offset = 0,
+                 .length = 6, },
+               { .offset = 16,
+                 .length = 6, },
+               { .offset = 32,
+                 .length = 6, },
+               { .offset = 48,
+                 .length = 6, },
+               },
+};
+
+static struct nand_bbt_descr lpc32xx_nand_bbt = {
+       .options = NAND_BBT_ABSPAGE | NAND_BBT_2BIT | NAND_BBT_NO_OOB |
+                  NAND_BBT_WRITE,
+       .pages = { 524224, 0, 0, 0, 0, 0, 0, 0 },
+};
+
+static struct nand_bbt_descr lpc32xx_nand_bbt_mirror = {
+       .options = NAND_BBT_ABSPAGE | NAND_BBT_2BIT | NAND_BBT_NO_OOB |
+                  NAND_BBT_WRITE,
+       .pages = { 524160, 0, 0, 0, 0, 0, 0, 0 },
+};
+
+struct lpc32xx_nand_host {
+       struct nand_chip        nand_chip;
+       struct lpc32xx_mlc_platform_data *pdata;
+       struct clk              *clk;
+       struct mtd_info         mtd;
+       void __iomem            *io_base;
+       int                     irq;
+       struct lpc32xx_nand_cfg_mlc     *ncfg;
+       struct completion       comp_nand;
+       struct completion       comp_controller;
+       uint32_t llptr;
+       /*
+        * Physical addresses of ECC buffer, DMA data buffers, OOB data buffer
+        */
+       dma_addr_t              oob_buf_phy;
+       /*
+        * Virtual addresses of ECC buffer, DMA data buffers, OOB data buffer
+        */
+       uint8_t                 *oob_buf;
+       /* Physical address of DMA base address */
+       dma_addr_t              io_base_phy;
+
+       struct completion       comp_dma;
+       struct dma_chan         *dma_chan;
+       struct dma_slave_config dma_slave_config;
+       struct scatterlist      sgl;
+       uint8_t                 *dma_buf;
+       uint8_t                 *dummy_buf;
+       int                     mlcsubpages; /* number of 512bytes-subpages */
+};
+
+/*
+ * Activate/Deactivate DMA Operation:
+ *
+ * Using the PL080 DMA Controller for transferring the 512 byte subpages
+ * instead of doing readl() / writel() in a loop slows it down significantly.
+ * Measurements via getnstimeofday() upon 512 byte subpage reads reveal:
+ *
+ * - readl() of 128 x 32 bits in a loop: ~20us
+ * - DMA read of 512 bytes (32 bit, 4...128 words bursts): ~60us
+ * - DMA read of 512 bytes (32 bit, no bursts): ~100us
+ *
+ * This applies to the transfer itself. In the DMA case: only the
+ * wait_for_completion() (DMA setup _not_ included).
+ *
+ * Note that the 512 bytes subpage transfer is done directly from/to a
+ * FIFO/buffer inside the NAND controller. Most of the time (~400-800us for a
+ * 2048 bytes page) is spent waiting for the NAND IRQ, anyway. (The NAND
+ * controller transferring data between its internal buffer to/from the NAND
+ * chip.)
+ *
+ * Therefore, using the PL080 DMA is disabled by default, for now.
+ *
+ */
+static int use_dma;
+
+static void lpc32xx_nand_setup(struct lpc32xx_nand_host *host)
+{
+       uint32_t clkrate, tmp;
+
+       /* Reset MLC controller */
+       writel(MLCCMD_RESET, MLC_CMD(host->io_base));
+       udelay(1000);
+
+       /* Get base clock for MLC block */
+       clkrate = clk_get_rate(host->clk);
+       if (clkrate == 0)
+               clkrate = 104000000;
+
+       /* Unlock MLC_ICR
+        * (among others, will be locked again automatically) */
+       writew(MLCLOCKPR_MAGIC, MLC_LOCK_PR(host->io_base));
+
+       /* Configure MLC Controller: Large Block, 5 Byte Address */
+       tmp = MLCICR_LARGEBLOCK | MLCICR_LONGADDR;
+       writel(tmp, MLC_ICR(host->io_base));
+
+       /* Unlock MLC_TIME_REG
+        * (among others, will be locked again automatically) */
+       writew(MLCLOCKPR_MAGIC, MLC_LOCK_PR(host->io_base));
+
+       /* Compute clock setup values, see LPC and NAND manual */
+       tmp = 0;
+       tmp |= MLCTIMEREG_TCEA_DELAY(clkrate / host->ncfg->tcea_delay + 1);
+       tmp |= MLCTIMEREG_BUSY_DELAY(clkrate / host->ncfg->busy_delay + 1);
+       tmp |= MLCTIMEREG_NAND_TA(clkrate / host->ncfg->nand_ta + 1);
+       tmp |= MLCTIMEREG_RD_HIGH(clkrate / host->ncfg->rd_high + 1);
+       tmp |= MLCTIMEREG_RD_LOW(clkrate / host->ncfg->rd_low);
+       tmp |= MLCTIMEREG_WR_HIGH(clkrate / host->ncfg->wr_high + 1);
+       tmp |= MLCTIMEREG_WR_LOW(clkrate / host->ncfg->wr_low);
+       writel(tmp, MLC_TIME_REG(host->io_base));
+
+       /* Enable IRQ for CONTROLLER_READY and NAND_READY */
+       writeb(MLCIRQ_CONTROLLER_READY | MLCIRQ_NAND_READY,
+                       MLC_IRQ_MR(host->io_base));
+
+       /* Normal nCE operation: nCE controlled by controller */
+       writel(MLCCEH_NORMAL, MLC_CEH(host->io_base));
+}
+
+/*
+ * Hardware specific access to control lines
+ */
+static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
+                                 unsigned int ctrl)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct lpc32xx_nand_host *host = nand_chip->priv;
+
+       if (cmd != NAND_CMD_NONE) {
+               if (ctrl & NAND_CLE)
+                       writel(cmd, MLC_CMD(host->io_base));
+               else
+                       writel(cmd, MLC_ADDR(host->io_base));
+       }
+}
+
+/*
+ * Read Device Ready (NAND device _and_ controller ready)
+ */
+static int lpc32xx_nand_device_ready(struct mtd_info *mtd)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct lpc32xx_nand_host *host = nand_chip->priv;
+
+       if ((readb(MLC_ISR(host->io_base)) &
+            (MLCISR_CONTROLLER_READY | MLCISR_NAND_READY)) ==
+           (MLCISR_CONTROLLER_READY | MLCISR_NAND_READY))
+               return  1;
+
+       return 0;
+}
+
+static irqreturn_t lpc3xxx_nand_irq(int irq, struct lpc32xx_nand_host *host)
+{
+       uint8_t sr;
+
+       /* Clear interrupt flag by reading status */
+       sr = readb(MLC_IRQ_SR(host->io_base));
+       if (sr & MLCIRQ_NAND_READY)
+               complete(&host->comp_nand);
+       if (sr & MLCIRQ_CONTROLLER_READY)
+               complete(&host->comp_controller);
+
+       return IRQ_HANDLED;
+}
+
+static int lpc32xx_waitfunc_nand(struct mtd_info *mtd, struct nand_chip *chip)
+{
+       struct lpc32xx_nand_host *host = chip->priv;
+
+       if (readb(MLC_ISR(host->io_base)) & MLCISR_NAND_READY)
+               goto exit;
+
+       wait_for_completion(&host->comp_nand);
+
+       while (!(readb(MLC_ISR(host->io_base)) & MLCISR_NAND_READY)) {
+               /* Seems to be delayed sometimes by controller */
+               dev_dbg(&mtd->dev, "Warning: NAND not ready.\n");
+               cpu_relax();
+       }
+
+exit:
+       return NAND_STATUS_READY;
+}
+
+static int lpc32xx_waitfunc_controller(struct mtd_info *mtd,
+                                      struct nand_chip *chip)
+{
+       struct lpc32xx_nand_host *host = chip->priv;
+
+       if (readb(MLC_ISR(host->io_base)) & MLCISR_CONTROLLER_READY)
+               goto exit;
+
+       wait_for_completion(&host->comp_controller);
+
+       while (!(readb(MLC_ISR(host->io_base)) &
+                MLCISR_CONTROLLER_READY)) {
+               dev_dbg(&mtd->dev, "Warning: Controller not ready.\n");
+               cpu_relax();
+       }
+
+exit:
+       return NAND_STATUS_READY;
+}
+
+static int lpc32xx_waitfunc(struct mtd_info *mtd, struct nand_chip *chip)
+{
+       lpc32xx_waitfunc_nand(mtd, chip);
+       lpc32xx_waitfunc_controller(mtd, chip);
+
+       return NAND_STATUS_READY;
+}
+
+/*
+ * Enable NAND write protect
+ */
+static void lpc32xx_wp_enable(struct lpc32xx_nand_host *host)
+{
+       if (gpio_is_valid(host->ncfg->wp_gpio))
+               gpio_set_value(host->ncfg->wp_gpio, 0);
+}
+
+/*
+ * Disable NAND write protect
+ */
+static void lpc32xx_wp_disable(struct lpc32xx_nand_host *host)
+{
+       if (gpio_is_valid(host->ncfg->wp_gpio))
+               gpio_set_value(host->ncfg->wp_gpio, 1);
+}
+
+static void lpc32xx_dma_complete_func(void *completion)
+{
+       complete(completion);
+}
+
+static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len,
+                           enum dma_transfer_direction dir)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct lpc32xx_nand_host *host = chip->priv;
+       struct dma_async_tx_descriptor *desc;
+       int flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+       int res;
+
+       sg_init_one(&host->sgl, mem, len);
+
+       res = dma_map_sg(host->dma_chan->device->dev, &host->sgl, 1,
+                        DMA_BIDIRECTIONAL);
+       if (res != 1) {
+               dev_err(mtd->dev.parent, "Failed to map sg list\n");
+               return -ENXIO;
+       }
+       desc = dmaengine_prep_slave_sg(host->dma_chan, &host->sgl, 1, dir,
+                                      flags);
+       if (!desc) {
+               dev_err(mtd->dev.parent, "Failed to prepare slave sg\n");
+               goto out1;
+       }
+
+       init_completion(&host->comp_dma);
+       desc->callback = lpc32xx_dma_complete_func;
+       desc->callback_param = &host->comp_dma;
+
+       dmaengine_submit(desc);
+       dma_async_issue_pending(host->dma_chan);
+
+       wait_for_completion_timeout(&host->comp_dma, msecs_to_jiffies(1000));
+
+       dma_unmap_sg(host->dma_chan->device->dev, &host->sgl, 1,
+                    DMA_BIDIRECTIONAL);
+       return 0;
+out1:
+       dma_unmap_sg(host->dma_chan->device->dev, &host->sgl, 1,
+                    DMA_BIDIRECTIONAL);
+       return -ENXIO;
+}
+
+static int lpc32xx_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+                            uint8_t *buf, int oob_required, int page)
+{
+       struct lpc32xx_nand_host *host = chip->priv;
+       int i, j;
+       uint8_t *oobbuf = chip->oob_poi;
+       uint32_t mlc_isr;
+       int res;
+       uint8_t *dma_buf;
+       bool dma_mapped;
+
+       if ((void *)buf <= high_memory) {
+               dma_buf = buf;
+               dma_mapped = true;
+       } else {
+               dma_buf = host->dma_buf;
+               dma_mapped = false;
+       }
+
+       /* Writing Command and Address */
+       chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+
+       /* For all sub-pages */
+       for (i = 0; i < host->mlcsubpages; i++) {
+               /* Start Auto Decode Command */
+               writeb(0x00, MLC_ECC_AUTO_DEC_REG(host->io_base));
+
+               /* Wait for Controller Ready */
+               lpc32xx_waitfunc_controller(mtd, chip);
+
+               /* Check ECC Error status */
+               mlc_isr = readl(MLC_ISR(host->io_base));
+               if (mlc_isr & MLCISR_DECODER_FAILURE) {
+                       mtd->ecc_stats.failed++;
+                       dev_warn(&mtd->dev, "%s: DECODER_FAILURE\n", __func__);
+               } else if (mlc_isr & MLCISR_ERRORS_DETECTED) {
+                       mtd->ecc_stats.corrected += ((mlc_isr >> 4) & 0x3) + 1;
+               }
+
+               /* Read 512 + 16 Bytes */
+               if (use_dma) {
+                       res = lpc32xx_xmit_dma(mtd, dma_buf + i * 512, 512,
+                                              DMA_DEV_TO_MEM);
+                       if (res)
+                               return res;
+               } else {
+                       for (j = 0; j < (512 >> 2); j++) {
+                               *((uint32_t *)(buf)) =
+                                       readl(MLC_BUFF(host->io_base));
+                               buf += 4;
+                       }
+               }
+               for (j = 0; j < (16 >> 2); j++) {
+                       *((uint32_t *)(oobbuf)) =
+                               readl(MLC_BUFF(host->io_base));
+                       oobbuf += 4;
+               }
+       }
+
+       if (use_dma && !dma_mapped)
+               memcpy(buf, dma_buf, mtd->writesize);
+
+       return 0;
+}
+
+static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd,
+                                      struct nand_chip *chip,
+                                      const uint8_t *buf, int oob_required)
+{
+       struct lpc32xx_nand_host *host = chip->priv;
+       const uint8_t *oobbuf = chip->oob_poi;
+       uint8_t *dma_buf = (uint8_t *)buf;
+       int res;
+       int i, j;
+
+       if (use_dma && (void *)buf >= high_memory) {
+               dma_buf = host->dma_buf;
+               memcpy(dma_buf, buf, mtd->writesize);
+       }
+
+       for (i = 0; i < host->mlcsubpages; i++) {
+               /* Start Encode */
+               writeb(0x00, MLC_ECC_ENC_REG(host->io_base));
+
+               /* Write 512 + 6 Bytes to Buffer */
+               if (use_dma) {
+                       res = lpc32xx_xmit_dma(mtd, dma_buf + i * 512, 512,
+                                              DMA_MEM_TO_DEV);
+                       if (res)
+                               return res;
+               } else {
+                       for (j = 0; j < (512 >> 2); j++) {
+                               writel(*((uint32_t *)(buf)),
+                                      MLC_BUFF(host->io_base));
+                               buf += 4;
+                       }
+               }
+               writel(*((uint32_t *)(oobbuf)), MLC_BUFF(host->io_base));
+               oobbuf += 4;
+               writew(*((uint16_t *)(oobbuf)), MLC_BUFF(host->io_base));
+               oobbuf += 12;
+
+               /* Auto Encode w/ Bit 8 = 0 (see LPC MLC Controller manual) */
+               writeb(0x00, MLC_ECC_AUTO_ENC_REG(host->io_base));
+
+               /* Wait for Controller Ready */
+               lpc32xx_waitfunc_controller(mtd, chip);
+       }
+       return 0;
+}
+
+static int lpc32xx_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+                             const uint8_t *buf, int oob_required, int page,
+                             int cached, int raw)
+{
+       int res;
+
+       chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+       res = lpc32xx_write_page_lowlevel(mtd, chip, buf, oob_required);
+       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+       lpc32xx_waitfunc(mtd, chip);
+
+       return res;
+}
+
+static int lpc32xx_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
+                           int page)
+{
+       struct lpc32xx_nand_host *host = chip->priv;
+
+       /* Read whole page - necessary with MLC controller! */
+       lpc32xx_read_page(mtd, chip, host->dummy_buf, 1, page);
+
+       return 0;
+}
+
+static int lpc32xx_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
+                             int page)
+{
+       /* None, write_oob conflicts with the automatic LPC MLC ECC decoder! */
+       return 0;
+}
+
+/* Prepares MLC for transfers with H/W ECC enabled: always enabled anyway */
+static void lpc32xx_ecc_enable(struct mtd_info *mtd, int mode)
+{
+       /* Always enabled! */
+}
+
+static int lpc32xx_dma_setup(struct lpc32xx_nand_host *host)
+{
+       struct mtd_info *mtd = &host->mtd;
+       dma_cap_mask_t mask;
+
+       if (!host->pdata || !host->pdata->dma_filter) {
+               dev_err(mtd->dev.parent, "no DMA platform data\n");
+               return -ENOENT;
+       }
+
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+       host->dma_chan = dma_request_channel(mask, host->pdata->dma_filter,
+                                            "nand-mlc");
+       if (!host->dma_chan) {
+               dev_err(mtd->dev.parent, "Failed to request DMA channel\n");
+               return -EBUSY;
+       }
+
+       /*
+        * Set direction to a sensible value even if the dmaengine driver
+        * should ignore it. With the default (DMA_MEM_TO_MEM), the amba-pl08x
+        * driver criticizes it as "alien transfer direction".
+        */
+       host->dma_slave_config.direction = DMA_DEV_TO_MEM;
+       host->dma_slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       host->dma_slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       host->dma_slave_config.src_maxburst = 128;
+       host->dma_slave_config.dst_maxburst = 128;
+       /* DMA controller does flow control: */
+       host->dma_slave_config.device_fc = false;
+       host->dma_slave_config.src_addr = MLC_BUFF(host->io_base_phy);
+       host->dma_slave_config.dst_addr = MLC_BUFF(host->io_base_phy);
+       if (dmaengine_slave_config(host->dma_chan, &host->dma_slave_config)) {
+               dev_err(mtd->dev.parent, "Failed to setup DMA slave\n");
+               goto out1;
+       }
+
+       return 0;
+out1:
+       dma_release_channel(host->dma_chan);
+       return -ENXIO;
+}
+
+static struct lpc32xx_nand_cfg_mlc *lpc32xx_parse_dt(struct device *dev)
+{
+       struct lpc32xx_nand_cfg_mlc *ncfg;
+       struct device_node *np = dev->of_node;
+
+       ncfg = devm_kzalloc(dev, sizeof(*ncfg), GFP_KERNEL);
+       if (!ncfg) {
+               dev_err(dev, "could not allocate memory for platform data\n");
+               return NULL;
+       }
+
+       of_property_read_u32(np, "nxp,tcea-delay", &ncfg->tcea_delay);
+       of_property_read_u32(np, "nxp,busy-delay", &ncfg->busy_delay);
+       of_property_read_u32(np, "nxp,nand-ta", &ncfg->nand_ta);
+       of_property_read_u32(np, "nxp,rd-high", &ncfg->rd_high);
+       of_property_read_u32(np, "nxp,rd-low", &ncfg->rd_low);
+       of_property_read_u32(np, "nxp,wr-high", &ncfg->wr_high);
+       of_property_read_u32(np, "nxp,wr-low", &ncfg->wr_low);
+
+       if (!ncfg->tcea_delay || !ncfg->busy_delay || !ncfg->nand_ta ||
+           !ncfg->rd_high || !ncfg->rd_low || !ncfg->wr_high ||
+           !ncfg->wr_low) {
+               dev_err(dev, "chip parameters not specified correctly\n");
+               return NULL;
+       }
+
+       ncfg->wp_gpio = of_get_named_gpio(np, "gpios", 0);
+
+       return ncfg;
+}
+
+/*
+ * Probe for NAND controller
+ */
+static int __devinit lpc32xx_nand_probe(struct platform_device *pdev)
+{
+       struct lpc32xx_nand_host *host;
+       struct mtd_info *mtd;
+       struct nand_chip *nand_chip;
+       struct resource *rc;
+       int res;
+       struct mtd_part_parser_data ppdata = {};
+
+       /* Allocate memory for the device structure (and zero it) */
+       host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+       if (!host) {
+               dev_err(&pdev->dev, "failed to allocate device structure.\n");
+               return -ENOMEM;
+       }
+
+       rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (rc == NULL) {
+               dev_err(&pdev->dev, "No memory resource found for device!\r\n");
+               return -ENXIO;
+       }
+
+       host->io_base = devm_request_and_ioremap(&pdev->dev, rc);
+       if (host->io_base == NULL) {
+               dev_err(&pdev->dev, "ioremap failed\n");
+               return -EIO;
+       }
+       host->io_base_phy = rc->start;
+
+       mtd = &host->mtd;
+       nand_chip = &host->nand_chip;
+       if (pdev->dev.of_node)
+               host->ncfg = lpc32xx_parse_dt(&pdev->dev);
+       if (!host->ncfg) {
+               dev_err(&pdev->dev,
+                       "Missing or bad NAND config from device tree\n");
+               return -ENOENT;
+       }
+       if (host->ncfg->wp_gpio == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
+       if (gpio_is_valid(host->ncfg->wp_gpio) &&
+                       gpio_request(host->ncfg->wp_gpio, "NAND WP")) {
+               dev_err(&pdev->dev, "GPIO not available\n");
+               return -EBUSY;
+       }
+       lpc32xx_wp_disable(host);
+
+       host->pdata = pdev->dev.platform_data;
+
+       nand_chip->priv = host;         /* link the private data structures */
+       mtd->priv = nand_chip;
+       mtd->owner = THIS_MODULE;
+       mtd->dev.parent = &pdev->dev;
+
+       /* Get NAND clock */
+       host->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(host->clk)) {
+               dev_err(&pdev->dev, "Clock initialization failure\n");
+               res = -ENOENT;
+               goto err_exit1;
+       }
+       clk_enable(host->clk);
+
+       nand_chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl;
+       nand_chip->dev_ready = lpc32xx_nand_device_ready;
+       nand_chip->chip_delay = 25; /* us */
+       nand_chip->IO_ADDR_R = MLC_DATA(host->io_base);
+       nand_chip->IO_ADDR_W = MLC_DATA(host->io_base);
+
+       /* Init NAND controller */
+       lpc32xx_nand_setup(host);
+
+       platform_set_drvdata(pdev, host);
+
+       /* Initialize function pointers */
+       nand_chip->ecc.hwctl = lpc32xx_ecc_enable;
+       nand_chip->ecc.read_page_raw = lpc32xx_read_page;
+       nand_chip->ecc.read_page = lpc32xx_read_page;
+       nand_chip->ecc.write_page_raw = lpc32xx_write_page_lowlevel;
+       nand_chip->ecc.write_page = lpc32xx_write_page_lowlevel;
+       nand_chip->ecc.write_oob = lpc32xx_write_oob;
+       nand_chip->ecc.read_oob = lpc32xx_read_oob;
+       nand_chip->ecc.strength = 4;
+       nand_chip->write_page = lpc32xx_write_page;
+       nand_chip->waitfunc = lpc32xx_waitfunc;
+
+       nand_chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
+       nand_chip->bbt_td = &lpc32xx_nand_bbt;
+       nand_chip->bbt_md = &lpc32xx_nand_bbt_mirror;
+
+       /* bitflip_threshold's default is defined as ecc_strength anyway.
+        * Unfortunately, it is set only later at add_mtd_device(). Meanwhile
+        * being 0, it causes bad block table scanning errors in
+        * nand_scan_tail(), so preparing it here. */
+       mtd->bitflip_threshold = nand_chip->ecc.strength;
+
+       if (use_dma) {
+               res = lpc32xx_dma_setup(host);
+               if (res) {
+                       res = -EIO;
+                       goto err_exit2;
+               }
+       }
+
+       /*
+        * Scan to find existance of the device and
+        * Get the type of NAND device SMALL block or LARGE block
+        */
+       if (nand_scan_ident(mtd, 1, NULL)) {
+               res = -ENXIO;
+               goto err_exit3;
+       }
+
+       host->dma_buf = devm_kzalloc(&pdev->dev, mtd->writesize, GFP_KERNEL);
+       if (!host->dma_buf) {
+               dev_err(&pdev->dev, "Error allocating dma_buf memory\n");
+               res = -ENOMEM;
+               goto err_exit3;
+       }
+
+       host->dummy_buf = devm_kzalloc(&pdev->dev, mtd->writesize, GFP_KERNEL);
+       if (!host->dummy_buf) {
+               dev_err(&pdev->dev, "Error allocating dummy_buf memory\n");
+               res = -ENOMEM;
+               goto err_exit3;
+       }
+
+       nand_chip->ecc.mode = NAND_ECC_HW;
+       nand_chip->ecc.size = mtd->writesize;
+       nand_chip->ecc.layout = &lpc32xx_nand_oob;
+       host->mlcsubpages = mtd->writesize / 512;
+
+       /* initially clear interrupt status */
+       readb(MLC_IRQ_SR(host->io_base));
+
+       init_completion(&host->comp_nand);
+       init_completion(&host->comp_controller);
+
+       host->irq = platform_get_irq(pdev, 0);
+       if ((host->irq < 0) || (host->irq >= NR_IRQS)) {
+               dev_err(&pdev->dev, "failed to get platform irq\n");
+               res = -EINVAL;
+               goto err_exit3;
+       }
+
+       if (request_irq(host->irq, (irq_handler_t)&lpc3xxx_nand_irq,
+                       IRQF_TRIGGER_HIGH, DRV_NAME, host)) {
+               dev_err(&pdev->dev, "Error requesting NAND IRQ\n");
+               res = -ENXIO;
+               goto err_exit3;
+       }
+
+       /*
+        * Fills out all the uninitialized function pointers with the defaults
+        * And scans for a bad block table if appropriate.
+        */
+       if (nand_scan_tail(mtd)) {
+               res = -ENXIO;
+               goto err_exit4;
+       }
+
+       mtd->name = DRV_NAME;
+
+       ppdata.of_node = pdev->dev.of_node;
+       res = mtd_device_parse_register(mtd, NULL, &ppdata, host->ncfg->parts,
+                                       host->ncfg->num_parts);
+       if (!res)
+               return res;
+
+       nand_release(mtd);
+
+err_exit4:
+       free_irq(host->irq, host);
+err_exit3:
+       if (use_dma)
+               dma_release_channel(host->dma_chan);
+err_exit2:
+       clk_disable(host->clk);
+       clk_put(host->clk);
+       platform_set_drvdata(pdev, NULL);
+err_exit1:
+       lpc32xx_wp_enable(host);
+       gpio_free(host->ncfg->wp_gpio);
+
+       return res;
+}
+
+/*
+ * Remove NAND device
+ */
+static int __devexit lpc32xx_nand_remove(struct platform_device *pdev)
+{
+       struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
+       struct mtd_info *mtd = &host->mtd;
+
+       nand_release(mtd);
+       free_irq(host->irq, host);
+       if (use_dma)
+               dma_release_channel(host->dma_chan);
+
+       clk_disable(host->clk);
+       clk_put(host->clk);
+       platform_set_drvdata(pdev, NULL);
+
+       lpc32xx_wp_enable(host);
+       gpio_free(host->ncfg->wp_gpio);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int lpc32xx_nand_resume(struct platform_device *pdev)
+{
+       struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
+
+       /* Re-enable NAND clock */
+       clk_enable(host->clk);
+
+       /* Fresh init of NAND controller */
+       lpc32xx_nand_setup(host);
+
+       /* Disable write protect */
+       lpc32xx_wp_disable(host);
+
+       return 0;
+}
+
+static int lpc32xx_nand_suspend(struct platform_device *pdev, pm_message_t pm)
+{
+       struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
+
+       /* Enable write protect for safety */
+       lpc32xx_wp_enable(host);
+
+       /* Disable clock */
+       clk_disable(host->clk);
+       return 0;
+}
+
+#else
+#define lpc32xx_nand_resume NULL
+#define lpc32xx_nand_suspend NULL
+#endif
+
+static const struct of_device_id lpc32xx_nand_match[] = {
+       { .compatible = "nxp,lpc3220-mlc" },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, lpc32xx_nand_match);
+
+static struct platform_driver lpc32xx_nand_driver = {
+       .probe          = lpc32xx_nand_probe,
+       .remove         = __devexit_p(lpc32xx_nand_remove),
+       .resume         = lpc32xx_nand_resume,
+       .suspend        = lpc32xx_nand_suspend,
+       .driver         = {
+               .name   = DRV_NAME,
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(lpc32xx_nand_match),
+       },
+};
+
+module_platform_driver(lpc32xx_nand_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_DESCRIPTION("NAND driver for the NXP LPC32XX MLC controller");
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c
new file mode 100644 (file)
index 0000000..32409c4
--- /dev/null
@@ -0,0 +1,1039 @@
+/*
+ * NXP LPC32XX NAND SLC driver
+ *
+ * Authors:
+ *    Kevin Wells <kevin.wells@nxp.com>
+ *    Roland Stigge <stigge@antcom.de>
+ *
+ * Copyright Â© 2011 NXP Semiconductors
+ * Copyright Â© 2012 Roland Stigge
+ *
+ * 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/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_mtd.h>
+#include <linux/of_gpio.h>
+#include <linux/mtd/lpc32xx_slc.h>
+
+#define LPC32XX_MODNAME                "lpc32xx-nand"
+
+/**********************************************************************
+* SLC NAND controller register offsets
+**********************************************************************/
+
+#define SLC_DATA(x)            (x + 0x000)
+#define SLC_ADDR(x)            (x + 0x004)
+#define SLC_CMD(x)             (x + 0x008)
+#define SLC_STOP(x)            (x + 0x00C)
+#define SLC_CTRL(x)            (x + 0x010)
+#define SLC_CFG(x)             (x + 0x014)
+#define SLC_STAT(x)            (x + 0x018)
+#define SLC_INT_STAT(x)                (x + 0x01C)
+#define SLC_IEN(x)             (x + 0x020)
+#define SLC_ISR(x)             (x + 0x024)
+#define SLC_ICR(x)             (x + 0x028)
+#define SLC_TAC(x)             (x + 0x02C)
+#define SLC_TC(x)              (x + 0x030)
+#define SLC_ECC(x)             (x + 0x034)
+#define SLC_DMA_DATA(x)                (x + 0x038)
+
+/**********************************************************************
+* slc_ctrl register definitions
+**********************************************************************/
+#define SLCCTRL_SW_RESET       (1 << 2) /* Reset the NAND controller bit */
+#define SLCCTRL_ECC_CLEAR      (1 << 1) /* Reset ECC bit */
+#define SLCCTRL_DMA_START      (1 << 0) /* Start DMA channel bit */
+
+/**********************************************************************
+* slc_cfg register definitions
+**********************************************************************/
+#define SLCCFG_CE_LOW          (1 << 5) /* Force CE low bit */
+#define SLCCFG_DMA_ECC         (1 << 4) /* Enable DMA ECC bit */
+#define SLCCFG_ECC_EN          (1 << 3) /* ECC enable bit */
+#define SLCCFG_DMA_BURST       (1 << 2) /* DMA burst bit */
+#define SLCCFG_DMA_DIR         (1 << 1) /* DMA write(0)/read(1) bit */
+#define SLCCFG_WIDTH           (1 << 0) /* External device width, 0=8bit */
+
+/**********************************************************************
+* slc_stat register definitions
+**********************************************************************/
+#define SLCSTAT_DMA_FIFO       (1 << 2) /* DMA FIFO has data bit */
+#define SLCSTAT_SLC_FIFO       (1 << 1) /* SLC FIFO has data bit */
+#define SLCSTAT_NAND_READY     (1 << 0) /* NAND device is ready bit */
+
+/**********************************************************************
+* slc_int_stat, slc_ien, slc_isr, and slc_icr register definitions
+**********************************************************************/
+#define SLCSTAT_INT_TC         (1 << 1) /* Transfer count bit */
+#define SLCSTAT_INT_RDY_EN     (1 << 0) /* Ready interrupt bit */
+
+/**********************************************************************
+* slc_tac register definitions
+**********************************************************************/
+/* Clock setting for RDY write sample wait time in 2*n clocks */
+#define SLCTAC_WDR(n)          (((n) & 0xF) << 28)
+/* Write pulse width in clock cycles, 1 to 16 clocks */
+#define SLCTAC_WWIDTH(n)       (((n) & 0xF) << 24)
+/* Write hold time of control and data signals, 1 to 16 clocks */
+#define SLCTAC_WHOLD(n)                (((n) & 0xF) << 20)
+/* Write setup time of control and data signals, 1 to 16 clocks */
+#define SLCTAC_WSETUP(n)       (((n) & 0xF) << 16)
+/* Clock setting for RDY read sample wait time in 2*n clocks */
+#define SLCTAC_RDR(n)          (((n) & 0xF) << 12)
+/* Read pulse width in clock cycles, 1 to 16 clocks */
+#define SLCTAC_RWIDTH(n)       (((n) & 0xF) << 8)
+/* Read hold time of control and data signals, 1 to 16 clocks */
+#define SLCTAC_RHOLD(n)                (((n) & 0xF) << 4)
+/* Read setup time of control and data signals, 1 to 16 clocks */
+#define SLCTAC_RSETUP(n)       (((n) & 0xF) << 0)
+
+/**********************************************************************
+* slc_ecc register definitions
+**********************************************************************/
+/* ECC line party fetch macro */
+#define SLCECC_TO_LINEPAR(n)   (((n) >> 6) & 0x7FFF)
+#define SLCECC_TO_COLPAR(n)    ((n) & 0x3F)
+
+/*
+ * DMA requires storage space for the DMA local buffer and the hardware ECC
+ * storage area. The DMA local buffer is only used if DMA mapping fails
+ * during runtime.
+ */
+#define LPC32XX_DMA_DATA_SIZE          4096
+#define LPC32XX_ECC_SAVE_SIZE          ((4096 / 256) * 4)
+
+/* Number of bytes used for ECC stored in NAND per 256 bytes */
+#define LPC32XX_SLC_DEV_ECC_BYTES      3
+
+/*
+ * If the NAND base clock frequency can't be fetched, this frequency will be
+ * used instead as the base. This rate is used to setup the timing registers
+ * used for NAND accesses.
+ */
+#define LPC32XX_DEF_BUS_RATE           133250000
+
+/* Milliseconds for DMA FIFO timeout (unlikely anyway) */
+#define LPC32XX_DMA_TIMEOUT            100
+
+/*
+ * NAND ECC Layout for small page NAND devices
+ * Note: For large and huge page devices, the default layouts are used
+ */
+static struct nand_ecclayout lpc32xx_nand_oob_16 = {
+       .eccbytes = 6,
+       .eccpos = {10, 11, 12, 13, 14, 15},
+       .oobfree = {
+               { .offset = 0, .length = 4 },
+               { .offset = 6, .length = 4 },
+       },
+};
+
+static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
+static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
+
+/*
+ * Small page FLASH BBT descriptors, marker at offset 0, version at offset 6
+ * Note: Large page devices used the default layout
+ */
+static struct nand_bbt_descr bbt_smallpage_main_descr = {
+       .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+               | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+       .offs = 0,
+       .len = 4,
+       .veroffs = 6,
+       .maxblocks = 4,
+       .pattern = bbt_pattern
+};
+
+static struct nand_bbt_descr bbt_smallpage_mirror_descr = {
+       .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+               | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+       .offs = 0,
+       .len = 4,
+       .veroffs = 6,
+       .maxblocks = 4,
+       .pattern = mirror_pattern
+};
+
+/*
+ * NAND platform configuration structure
+ */
+struct lpc32xx_nand_cfg_slc {
+       uint32_t wdr_clks;
+       uint32_t wwidth;
+       uint32_t whold;
+       uint32_t wsetup;
+       uint32_t rdr_clks;
+       uint32_t rwidth;
+       uint32_t rhold;
+       uint32_t rsetup;
+       bool use_bbt;
+       int wp_gpio;
+       struct mtd_partition *parts;
+       unsigned num_parts;
+};
+
+struct lpc32xx_nand_host {
+       struct nand_chip        nand_chip;
+       struct lpc32xx_slc_platform_data *pdata;
+       struct clk              *clk;
+       struct mtd_info         mtd;
+       void __iomem            *io_base;
+       struct lpc32xx_nand_cfg_slc *ncfg;
+
+       struct completion       comp;
+       struct dma_chan         *dma_chan;
+       uint32_t                dma_buf_len;
+       struct dma_slave_config dma_slave_config;
+       struct scatterlist      sgl;
+
+       /*
+        * DMA and CPU addresses of ECC work area and data buffer
+        */
+       uint32_t                *ecc_buf;
+       uint8_t                 *data_buf;
+       dma_addr_t              io_base_dma;
+};
+
+static void lpc32xx_nand_setup(struct lpc32xx_nand_host *host)
+{
+       uint32_t clkrate, tmp;
+
+       /* Reset SLC controller */
+       writel(SLCCTRL_SW_RESET, SLC_CTRL(host->io_base));
+       udelay(1000);
+
+       /* Basic setup */
+       writel(0, SLC_CFG(host->io_base));
+       writel(0, SLC_IEN(host->io_base));
+       writel((SLCSTAT_INT_TC | SLCSTAT_INT_RDY_EN),
+               SLC_ICR(host->io_base));
+
+       /* Get base clock for SLC block */
+       clkrate = clk_get_rate(host->clk);
+       if (clkrate == 0)
+               clkrate = LPC32XX_DEF_BUS_RATE;
+
+       /* Compute clock setup values */
+       tmp = SLCTAC_WDR(host->ncfg->wdr_clks) |
+               SLCTAC_WWIDTH(1 + (clkrate / host->ncfg->wwidth)) |
+               SLCTAC_WHOLD(1 + (clkrate / host->ncfg->whold)) |
+               SLCTAC_WSETUP(1 + (clkrate / host->ncfg->wsetup)) |
+               SLCTAC_RDR(host->ncfg->rdr_clks) |
+               SLCTAC_RWIDTH(1 + (clkrate / host->ncfg->rwidth)) |
+               SLCTAC_RHOLD(1 + (clkrate / host->ncfg->rhold)) |
+               SLCTAC_RSETUP(1 + (clkrate / host->ncfg->rsetup));
+       writel(tmp, SLC_TAC(host->io_base));
+}
+
+/*
+ * Hardware specific access to control lines
+ */
+static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
+       unsigned int ctrl)
+{
+       uint32_t tmp;
+       struct nand_chip *chip = mtd->priv;
+       struct lpc32xx_nand_host *host = chip->priv;
+
+       /* Does CE state need to be changed? */
+       tmp = readl(SLC_CFG(host->io_base));
+       if (ctrl & NAND_NCE)
+               tmp |= SLCCFG_CE_LOW;
+       else
+               tmp &= ~SLCCFG_CE_LOW;
+       writel(tmp, SLC_CFG(host->io_base));
+
+       if (cmd != NAND_CMD_NONE) {
+               if (ctrl & NAND_CLE)
+                       writel(cmd, SLC_CMD(host->io_base));
+               else
+                       writel(cmd, SLC_ADDR(host->io_base));
+       }
+}
+
+/*
+ * Read the Device Ready pin
+ */
+static int lpc32xx_nand_device_ready(struct mtd_info *mtd)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct lpc32xx_nand_host *host = chip->priv;
+       int rdy = 0;
+
+       if ((readl(SLC_STAT(host->io_base)) & SLCSTAT_NAND_READY) != 0)
+               rdy = 1;
+
+       return rdy;
+}
+
+/*
+ * Enable NAND write protect
+ */
+static void lpc32xx_wp_enable(struct lpc32xx_nand_host *host)
+{
+       if (gpio_is_valid(host->ncfg->wp_gpio))
+               gpio_set_value(host->ncfg->wp_gpio, 0);
+}
+
+/*
+ * Disable NAND write protect
+ */
+static void lpc32xx_wp_disable(struct lpc32xx_nand_host *host)
+{
+       if (gpio_is_valid(host->ncfg->wp_gpio))
+               gpio_set_value(host->ncfg->wp_gpio, 1);
+}
+
+/*
+ * Prepares SLC for transfers with H/W ECC enabled
+ */
+static void lpc32xx_nand_ecc_enable(struct mtd_info *mtd, int mode)
+{
+       /* Hardware ECC is enabled automatically in hardware as needed */
+}
+
+/*
+ * Calculates the ECC for the data
+ */
+static int lpc32xx_nand_ecc_calculate(struct mtd_info *mtd,
+                                     const unsigned char *buf,
+                                     unsigned char *code)
+{
+       /*
+        * ECC is calculated automatically in hardware during syndrome read
+        * and write operations, so it doesn't need to be calculated here.
+        */
+       return 0;
+}
+
+/*
+ * Read a single byte from NAND device
+ */
+static uint8_t lpc32xx_nand_read_byte(struct mtd_info *mtd)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct lpc32xx_nand_host *host = chip->priv;
+
+       return (uint8_t)readl(SLC_DATA(host->io_base));
+}
+
+/*
+ * Simple device read without ECC
+ */
+static void lpc32xx_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct lpc32xx_nand_host *host = chip->priv;
+
+       /* Direct device read with no ECC */
+       while (len-- > 0)
+               *buf++ = (uint8_t)readl(SLC_DATA(host->io_base));
+}
+
+/*
+ * Simple device write without ECC
+ */
+static void lpc32xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct lpc32xx_nand_host *host = chip->priv;
+
+       /* Direct device write with no ECC */
+       while (len-- > 0)
+               writel((uint32_t)*buf++, SLC_DATA(host->io_base));
+}
+
+/*
+ * Read the OOB data from the device without ECC using FIFO method
+ */
+static int lpc32xx_nand_read_oob_syndrome(struct mtd_info *mtd,
+                                         struct nand_chip *chip, int page)
+{
+       chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       return 0;
+}
+
+/*
+ * Write the OOB data to the device without ECC using FIFO method
+ */
+static int lpc32xx_nand_write_oob_syndrome(struct mtd_info *mtd,
+       struct nand_chip *chip, int page)
+{
+       int status;
+
+       chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+       chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       /* Send command to program the OOB data */
+       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+       status = chip->waitfunc(mtd, chip);
+
+       return status & NAND_STATUS_FAIL ? -EIO : 0;
+}
+
+/*
+ * Fills in the ECC fields in the OOB buffer with the hardware generated ECC
+ */
+static void lpc32xx_slc_ecc_copy(uint8_t *spare, const uint32_t *ecc, int count)
+{
+       int i;
+
+       for (i = 0; i < (count * 3); i += 3) {
+               uint32_t ce = ecc[i / 3];
+               ce = ~(ce << 2) & 0xFFFFFF;
+               spare[i + 2] = (uint8_t)(ce & 0xFF);
+               ce >>= 8;
+               spare[i + 1] = (uint8_t)(ce & 0xFF);
+               ce >>= 8;
+               spare[i] = (uint8_t)(ce & 0xFF);
+       }
+}
+
+static void lpc32xx_dma_complete_func(void *completion)
+{
+       complete(completion);
+}
+
+static int lpc32xx_xmit_dma(struct mtd_info *mtd, dma_addr_t dma,
+                           void *mem, int len, enum dma_transfer_direction dir)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct lpc32xx_nand_host *host = chip->priv;
+       struct dma_async_tx_descriptor *desc;
+       int flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+       int res;
+
+       host->dma_slave_config.direction = dir;
+       host->dma_slave_config.src_addr = dma;
+       host->dma_slave_config.dst_addr = dma;
+       host->dma_slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       host->dma_slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       host->dma_slave_config.src_maxburst = 4;
+       host->dma_slave_config.dst_maxburst = 4;
+       /* DMA controller does flow control: */
+       host->dma_slave_config.device_fc = false;
+       if (dmaengine_slave_config(host->dma_chan, &host->dma_slave_config)) {
+               dev_err(mtd->dev.parent, "Failed to setup DMA slave\n");
+               return -ENXIO;
+       }
+
+       sg_init_one(&host->sgl, mem, len);
+
+       res = dma_map_sg(host->dma_chan->device->dev, &host->sgl, 1,
+                        DMA_BIDIRECTIONAL);
+       if (res != 1) {
+               dev_err(mtd->dev.parent, "Failed to map sg list\n");
+               return -ENXIO;
+       }
+       desc = dmaengine_prep_slave_sg(host->dma_chan, &host->sgl, 1, dir,
+                                      flags);
+       if (!desc) {
+               dev_err(mtd->dev.parent, "Failed to prepare slave sg\n");
+               goto out1;
+       }
+
+       init_completion(&host->comp);
+       desc->callback = lpc32xx_dma_complete_func;
+       desc->callback_param = &host->comp;
+
+       dmaengine_submit(desc);
+       dma_async_issue_pending(host->dma_chan);
+
+       wait_for_completion_timeout(&host->comp, msecs_to_jiffies(1000));
+
+       dma_unmap_sg(host->dma_chan->device->dev, &host->sgl, 1,
+                    DMA_BIDIRECTIONAL);
+
+       return 0;
+out1:
+       dma_unmap_sg(host->dma_chan->device->dev, &host->sgl, 1,
+                    DMA_BIDIRECTIONAL);
+       return -ENXIO;
+}
+
+/*
+ * DMA read/write transfers with ECC support
+ */
+static int lpc32xx_xfer(struct mtd_info *mtd, uint8_t *buf, int eccsubpages,
+                       int read)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct lpc32xx_nand_host *host = chip->priv;
+       int i, status = 0;
+       unsigned long timeout;
+       int res;
+       enum dma_transfer_direction dir =
+               read ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
+       uint8_t *dma_buf;
+       bool dma_mapped;
+
+       if ((void *)buf <= high_memory) {
+               dma_buf = buf;
+               dma_mapped = true;
+       } else {
+               dma_buf = host->data_buf;
+               dma_mapped = false;
+               if (!read)
+                       memcpy(host->data_buf, buf, mtd->writesize);
+       }
+
+       if (read) {
+               writel(readl(SLC_CFG(host->io_base)) |
+                      SLCCFG_DMA_DIR | SLCCFG_ECC_EN | SLCCFG_DMA_ECC |
+                      SLCCFG_DMA_BURST, SLC_CFG(host->io_base));
+       } else {
+               writel((readl(SLC_CFG(host->io_base)) |
+                       SLCCFG_ECC_EN | SLCCFG_DMA_ECC | SLCCFG_DMA_BURST) &
+                      ~SLCCFG_DMA_DIR,
+                       SLC_CFG(host->io_base));
+       }
+
+       /* Clear initial ECC */
+       writel(SLCCTRL_ECC_CLEAR, SLC_CTRL(host->io_base));
+
+       /* Transfer size is data area only */
+       writel(mtd->writesize, SLC_TC(host->io_base));
+
+       /* Start transfer in the NAND controller */
+       writel(readl(SLC_CTRL(host->io_base)) | SLCCTRL_DMA_START,
+              SLC_CTRL(host->io_base));
+
+       for (i = 0; i < chip->ecc.steps; i++) {
+               /* Data */
+               res = lpc32xx_xmit_dma(mtd, SLC_DMA_DATA(host->io_base_dma),
+                                      dma_buf + i * chip->ecc.size,
+                                      mtd->writesize / chip->ecc.steps, dir);
+               if (res)
+                       return res;
+
+               /* Always _read_ ECC */
+               if (i == chip->ecc.steps - 1)
+                       break;
+               if (!read) /* ECC availability delayed on write */
+                       udelay(10);
+               res = lpc32xx_xmit_dma(mtd, SLC_ECC(host->io_base_dma),
+                                      &host->ecc_buf[i], 4, DMA_DEV_TO_MEM);
+               if (res)
+                       return res;
+       }
+
+       /*
+        * According to NXP, the DMA can be finished here, but the NAND
+        * controller may still have buffered data. After porting to using the
+        * dmaengine DMA driver (amba-pl080), the condition (DMA_FIFO empty)
+        * appears to be always true, according to tests. Keeping the check for
+        * safety reasons for now.
+        */
+       if (readl(SLC_STAT(host->io_base)) & SLCSTAT_DMA_FIFO) {
+               dev_warn(mtd->dev.parent, "FIFO not empty!\n");
+               timeout = jiffies + msecs_to_jiffies(LPC32XX_DMA_TIMEOUT);
+               while ((readl(SLC_STAT(host->io_base)) & SLCSTAT_DMA_FIFO) &&
+                      time_before(jiffies, timeout))
+                       cpu_relax();
+               if (!time_before(jiffies, timeout)) {
+                       dev_err(mtd->dev.parent, "FIFO held data too long\n");
+                       status = -EIO;
+               }
+       }
+
+       /* Read last calculated ECC value */
+       if (!read)
+               udelay(10);
+       host->ecc_buf[chip->ecc.steps - 1] =
+               readl(SLC_ECC(host->io_base));
+
+       /* Flush DMA */
+       dmaengine_terminate_all(host->dma_chan);
+
+       if (readl(SLC_STAT(host->io_base)) & SLCSTAT_DMA_FIFO ||
+           readl(SLC_TC(host->io_base))) {
+               /* Something is left in the FIFO, something is wrong */
+               dev_err(mtd->dev.parent, "DMA FIFO failure\n");
+               status = -EIO;
+       }
+
+       /* Stop DMA & HW ECC */
+       writel(readl(SLC_CTRL(host->io_base)) & ~SLCCTRL_DMA_START,
+              SLC_CTRL(host->io_base));
+       writel(readl(SLC_CFG(host->io_base)) &
+              ~(SLCCFG_DMA_DIR | SLCCFG_ECC_EN | SLCCFG_DMA_ECC |
+                SLCCFG_DMA_BURST), SLC_CFG(host->io_base));
+
+       if (!dma_mapped && read)
+               memcpy(buf, host->data_buf, mtd->writesize);
+
+       return status;
+}
+
+/*
+ * Read the data and OOB data from the device, use ECC correction with the
+ * data, disable ECC for the OOB data
+ */
+static int lpc32xx_nand_read_page_syndrome(struct mtd_info *mtd,
+                                          struct nand_chip *chip, uint8_t *buf,
+                                          int oob_required, int page)
+{
+       struct lpc32xx_nand_host *host = chip->priv;
+       int stat, i, status;
+       uint8_t *oobecc, tmpecc[LPC32XX_ECC_SAVE_SIZE];
+
+       /* Issue read command */
+       chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+
+       /* Read data and oob, calculate ECC */
+       status = lpc32xx_xfer(mtd, buf, chip->ecc.steps, 1);
+
+       /* Get OOB data */
+       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       /* Convert to stored ECC format */
+       lpc32xx_slc_ecc_copy(tmpecc, (uint32_t *) host->ecc_buf, chip->ecc.steps);
+
+       /* Pointer to ECC data retrieved from NAND spare area */
+       oobecc = chip->oob_poi + chip->ecc.layout->eccpos[0];
+
+       for (i = 0; i < chip->ecc.steps; i++) {
+               stat = chip->ecc.correct(mtd, buf, oobecc,
+                                        &tmpecc[i * chip->ecc.bytes]);
+               if (stat < 0)
+                       mtd->ecc_stats.failed++;
+               else
+                       mtd->ecc_stats.corrected += stat;
+
+               buf += chip->ecc.size;
+               oobecc += chip->ecc.bytes;
+       }
+
+       return status;
+}
+
+/*
+ * Read the data and OOB data from the device, no ECC correction with the
+ * data or OOB data
+ */
+static int lpc32xx_nand_read_page_raw_syndrome(struct mtd_info *mtd,
+                                              struct nand_chip *chip,
+                                              uint8_t *buf, int oob_required,
+                                              int page)
+{
+       /* Issue read command */
+       chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+
+       /* Raw reads can just use the FIFO interface */
+       chip->read_buf(mtd, buf, chip->ecc.size * chip->ecc.steps);
+       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       return 0;
+}
+
+/*
+ * Write the data and OOB data to the device, use ECC with the data,
+ * disable ECC for the OOB data
+ */
+static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd,
+                                           struct nand_chip *chip,
+                                           const uint8_t *buf, int oob_required)
+{
+       struct lpc32xx_nand_host *host = chip->priv;
+       uint8_t *pb = chip->oob_poi + chip->ecc.layout->eccpos[0];
+       int error;
+
+       /* Write data, calculate ECC on outbound data */
+       error = lpc32xx_xfer(mtd, (uint8_t *)buf, chip->ecc.steps, 0);
+       if (error)
+               return error;
+
+       /*
+        * The calculated ECC needs some manual work done to it before
+        * committing it to NAND. Process the calculated ECC and place
+        * the resultant values directly into the OOB buffer. */
+       lpc32xx_slc_ecc_copy(pb, (uint32_t *)host->ecc_buf, chip->ecc.steps);
+
+       /* Write ECC data to device */
+       chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+       return 0;
+}
+
+/*
+ * Write the data and OOB data to the device, no ECC correction with the
+ * data or OOB data
+ */
+static int lpc32xx_nand_write_page_raw_syndrome(struct mtd_info *mtd,
+                                               struct nand_chip *chip,
+                                               const uint8_t *buf,
+                                               int oob_required)
+{
+       /* Raw writes can just use the FIFO interface */
+       chip->write_buf(mtd, buf, chip->ecc.size * chip->ecc.steps);
+       chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+       return 0;
+}
+
+static int lpc32xx_nand_dma_setup(struct lpc32xx_nand_host *host)
+{
+       struct mtd_info *mtd = &host->mtd;
+       dma_cap_mask_t mask;
+
+       if (!host->pdata || !host->pdata->dma_filter) {
+               dev_err(mtd->dev.parent, "no DMA platform data\n");
+               return -ENOENT;
+       }
+
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+       host->dma_chan = dma_request_channel(mask, host->pdata->dma_filter,
+                                            "nand-slc");
+       if (!host->dma_chan) {
+               dev_err(mtd->dev.parent, "Failed to request DMA channel\n");
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+static struct lpc32xx_nand_cfg_slc *lpc32xx_parse_dt(struct device *dev)
+{
+       struct lpc32xx_nand_cfg_slc *ncfg;
+       struct device_node *np = dev->of_node;
+
+       ncfg = devm_kzalloc(dev, sizeof(*ncfg), GFP_KERNEL);
+       if (!ncfg) {
+               dev_err(dev, "could not allocate memory for NAND config\n");
+               return NULL;
+       }
+
+       of_property_read_u32(np, "nxp,wdr-clks", &ncfg->wdr_clks);
+       of_property_read_u32(np, "nxp,wwidth", &ncfg->wwidth);
+       of_property_read_u32(np, "nxp,whold", &ncfg->whold);
+       of_property_read_u32(np, "nxp,wsetup", &ncfg->wsetup);
+       of_property_read_u32(np, "nxp,rdr-clks", &ncfg->rdr_clks);
+       of_property_read_u32(np, "nxp,rwidth", &ncfg->rwidth);
+       of_property_read_u32(np, "nxp,rhold", &ncfg->rhold);
+       of_property_read_u32(np, "nxp,rsetup", &ncfg->rsetup);
+
+       if (!ncfg->wdr_clks || !ncfg->wwidth || !ncfg->whold ||
+           !ncfg->wsetup || !ncfg->rdr_clks || !ncfg->rwidth ||
+           !ncfg->rhold || !ncfg->rsetup) {
+               dev_err(dev, "chip parameters not specified correctly\n");
+               return NULL;
+       }
+
+       ncfg->use_bbt = of_get_nand_on_flash_bbt(np);
+       ncfg->wp_gpio = of_get_named_gpio(np, "gpios", 0);
+
+       return ncfg;
+}
+
+/*
+ * Probe for NAND controller
+ */
+static int __devinit lpc32xx_nand_probe(struct platform_device *pdev)
+{
+       struct lpc32xx_nand_host *host;
+       struct mtd_info *mtd;
+       struct nand_chip *chip;
+       struct resource *rc;
+       struct mtd_part_parser_data ppdata = {};
+       int res;
+
+       rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (rc == NULL) {
+               dev_err(&pdev->dev, "No memory resource found for device\n");
+               return -EBUSY;
+       }
+
+       /* Allocate memory for the device structure (and zero it) */
+       host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+       if (!host) {
+               dev_err(&pdev->dev, "failed to allocate device structure\n");
+               return -ENOMEM;
+       }
+       host->io_base_dma = rc->start;
+
+       host->io_base = devm_request_and_ioremap(&pdev->dev, rc);
+       if (host->io_base == NULL) {
+               dev_err(&pdev->dev, "ioremap failed\n");
+               return -ENOMEM;
+       }
+
+       if (pdev->dev.of_node)
+               host->ncfg = lpc32xx_parse_dt(&pdev->dev);
+       if (!host->ncfg) {
+               dev_err(&pdev->dev,
+                       "Missing or bad NAND config from device tree\n");
+               return -ENOENT;
+       }
+       if (host->ncfg->wp_gpio == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
+       if (gpio_is_valid(host->ncfg->wp_gpio) &&
+                       gpio_request(host->ncfg->wp_gpio, "NAND WP")) {
+               dev_err(&pdev->dev, "GPIO not available\n");
+               return -EBUSY;
+       }
+       lpc32xx_wp_disable(host);
+
+       host->pdata = pdev->dev.platform_data;
+
+       mtd = &host->mtd;
+       chip = &host->nand_chip;
+       chip->priv = host;
+       mtd->priv = chip;
+       mtd->owner = THIS_MODULE;
+       mtd->dev.parent = &pdev->dev;
+
+       /* Get NAND clock */
+       host->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(host->clk)) {
+               dev_err(&pdev->dev, "Clock failure\n");
+               res = -ENOENT;
+               goto err_exit1;
+       }
+       clk_enable(host->clk);
+
+       /* Set NAND IO addresses and command/ready functions */
+       chip->IO_ADDR_R = SLC_DATA(host->io_base);
+       chip->IO_ADDR_W = SLC_DATA(host->io_base);
+       chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl;
+       chip->dev_ready = lpc32xx_nand_device_ready;
+       chip->chip_delay = 20; /* 20us command delay time */
+
+       /* Init NAND controller */
+       lpc32xx_nand_setup(host);
+
+       platform_set_drvdata(pdev, host);
+
+       /* NAND callbacks for LPC32xx SLC hardware */
+       chip->ecc.mode = NAND_ECC_HW_SYNDROME;
+       chip->read_byte = lpc32xx_nand_read_byte;
+       chip->read_buf = lpc32xx_nand_read_buf;
+       chip->write_buf = lpc32xx_nand_write_buf;
+       chip->ecc.read_page_raw = lpc32xx_nand_read_page_raw_syndrome;
+       chip->ecc.read_page = lpc32xx_nand_read_page_syndrome;
+       chip->ecc.write_page_raw = lpc32xx_nand_write_page_raw_syndrome;
+       chip->ecc.write_page = lpc32xx_nand_write_page_syndrome;
+       chip->ecc.write_oob = lpc32xx_nand_write_oob_syndrome;
+       chip->ecc.read_oob = lpc32xx_nand_read_oob_syndrome;
+       chip->ecc.calculate = lpc32xx_nand_ecc_calculate;
+       chip->ecc.correct = nand_correct_data;
+       chip->ecc.strength = 1;
+       chip->ecc.hwctl = lpc32xx_nand_ecc_enable;
+
+       /* bitflip_threshold's default is defined as ecc_strength anyway.
+        * Unfortunately, it is set only later at add_mtd_device(). Meanwhile
+        * being 0, it causes bad block table scanning errors in
+        * nand_scan_tail(), so preparing it here already. */
+       mtd->bitflip_threshold = chip->ecc.strength;
+
+       /*
+        * Allocate a large enough buffer for a single huge page plus
+        * extra space for the spare area and ECC storage area
+        */
+       host->dma_buf_len = LPC32XX_DMA_DATA_SIZE + LPC32XX_ECC_SAVE_SIZE;
+       host->data_buf = devm_kzalloc(&pdev->dev, host->dma_buf_len,
+                                     GFP_KERNEL);
+       if (host->data_buf == NULL) {
+               dev_err(&pdev->dev, "Error allocating memory\n");
+               res = -ENOMEM;
+               goto err_exit2;
+       }
+
+       res = lpc32xx_nand_dma_setup(host);
+       if (res) {
+               res = -EIO;
+               goto err_exit2;
+       }
+
+       /* Find NAND device */
+       if (nand_scan_ident(mtd, 1, NULL)) {
+               res = -ENXIO;
+               goto err_exit3;
+       }
+
+       /* OOB and ECC CPU and DMA work areas */
+       host->ecc_buf = (uint32_t *)(host->data_buf + LPC32XX_DMA_DATA_SIZE);
+
+       /*
+        * Small page FLASH has a unique OOB layout, but large and huge
+        * page FLASH use the standard layout. Small page FLASH uses a
+        * custom BBT marker layout.
+        */
+       if (mtd->writesize <= 512)
+               chip->ecc.layout = &lpc32xx_nand_oob_16;
+
+       /* These sizes remain the same regardless of page size */
+       chip->ecc.size = 256;
+       chip->ecc.bytes = LPC32XX_SLC_DEV_ECC_BYTES;
+       chip->ecc.prepad = chip->ecc.postpad = 0;
+
+       /* Avoid extra scan if using BBT, setup BBT support */
+       if (host->ncfg->use_bbt) {
+               chip->options |= NAND_SKIP_BBTSCAN;
+               chip->bbt_options |= NAND_BBT_USE_FLASH;
+
+               /*
+                * Use a custom BBT marker setup for small page FLASH that
+                * won't interfere with the ECC layout. Large and huge page
+                * FLASH use the standard layout.
+                */
+               if (mtd->writesize <= 512) {
+                       chip->bbt_td = &bbt_smallpage_main_descr;
+                       chip->bbt_md = &bbt_smallpage_mirror_descr;
+               }
+       }
+
+       /*
+        * Fills out all the uninitialized function pointers with the defaults
+        */
+       if (nand_scan_tail(mtd)) {
+               res = -ENXIO;
+               goto err_exit3;
+       }
+
+       /* Standard layout in FLASH for bad block tables */
+       if (host->ncfg->use_bbt) {
+               if (nand_default_bbt(mtd) < 0)
+                       dev_err(&pdev->dev,
+                              "Error initializing default bad block tables\n");
+       }
+
+       mtd->name = "nxp_lpc3220_slc";
+       ppdata.of_node = pdev->dev.of_node;
+       res = mtd_device_parse_register(mtd, NULL, &ppdata, host->ncfg->parts,
+                                       host->ncfg->num_parts);
+       if (!res)
+               return res;
+
+       nand_release(mtd);
+
+err_exit3:
+       dma_release_channel(host->dma_chan);
+err_exit2:
+       clk_disable(host->clk);
+       clk_put(host->clk);
+       platform_set_drvdata(pdev, NULL);
+err_exit1:
+       lpc32xx_wp_enable(host);
+       gpio_free(host->ncfg->wp_gpio);
+
+       return res;
+}
+
+/*
+ * Remove NAND device.
+ */
+static int __devexit lpc32xx_nand_remove(struct platform_device *pdev)
+{
+       uint32_t tmp;
+       struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
+       struct mtd_info *mtd = &host->mtd;
+
+       nand_release(mtd);
+       dma_release_channel(host->dma_chan);
+
+       /* Force CE high */
+       tmp = readl(SLC_CTRL(host->io_base));
+       tmp &= ~SLCCFG_CE_LOW;
+       writel(tmp, SLC_CTRL(host->io_base));
+
+       clk_disable(host->clk);
+       clk_put(host->clk);
+       platform_set_drvdata(pdev, NULL);
+       lpc32xx_wp_enable(host);
+       gpio_free(host->ncfg->wp_gpio);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int lpc32xx_nand_resume(struct platform_device *pdev)
+{
+       struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
+
+       /* Re-enable NAND clock */
+       clk_enable(host->clk);
+
+       /* Fresh init of NAND controller */
+       lpc32xx_nand_setup(host);
+
+       /* Disable write protect */
+       lpc32xx_wp_disable(host);
+
+       return 0;
+}
+
+static int lpc32xx_nand_suspend(struct platform_device *pdev, pm_message_t pm)
+{
+       uint32_t tmp;
+       struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
+
+       /* Force CE high */
+       tmp = readl(SLC_CTRL(host->io_base));
+       tmp &= ~SLCCFG_CE_LOW;
+       writel(tmp, SLC_CTRL(host->io_base));
+
+       /* Enable write protect for safety */
+       lpc32xx_wp_enable(host);
+
+       /* Disable clock */
+       clk_disable(host->clk);
+
+       return 0;
+}
+
+#else
+#define lpc32xx_nand_resume NULL
+#define lpc32xx_nand_suspend NULL
+#endif
+
+static const struct of_device_id lpc32xx_nand_match[] = {
+       { .compatible = "nxp,lpc3220-slc" },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, lpc32xx_nand_match);
+
+static struct platform_driver lpc32xx_nand_driver = {
+       .probe          = lpc32xx_nand_probe,
+       .remove         = __devexit_p(lpc32xx_nand_remove),
+       .resume         = lpc32xx_nand_resume,
+       .suspend        = lpc32xx_nand_suspend,
+       .driver         = {
+               .name   = LPC32XX_MODNAME,
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(lpc32xx_nand_match),
+       },
+};
+
+module_platform_driver(lpc32xx_nand_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_DESCRIPTION("NAND driver for the NXP LPC32XX SLC controller");
index c259c24d7986034f3a2d14e02d5c06fb9a19a323..f776c8577b8cc4b36b5a7397084f88b457715898 100644 (file)
@@ -506,27 +506,6 @@ static void mpc5121_nfc_write_buf(struct mtd_info *mtd,
        mpc5121_nfc_buf_copy(mtd, (u_char *)buf, len, 1);
 }
 
-/* Compare buffer with NAND flash */
-static int mpc5121_nfc_verify_buf(struct mtd_info *mtd,
-                                               const u_char *buf, int len)
-{
-       u_char tmp[256];
-       uint bsize;
-
-       while (len) {
-               bsize = min(len, 256);
-               mpc5121_nfc_read_buf(mtd, tmp, bsize);
-
-               if (memcmp(buf, tmp, bsize))
-                       return 1;
-
-               buf += bsize;
-               len -= bsize;
-       }
-
-       return 0;
-}
-
 /* Read byte from NFC buffers */
 static u8 mpc5121_nfc_read_byte(struct mtd_info *mtd)
 {
@@ -732,7 +711,6 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
        chip->read_word = mpc5121_nfc_read_word;
        chip->read_buf = mpc5121_nfc_read_buf;
        chip->write_buf = mpc5121_nfc_write_buf;
-       chip->verify_buf = mpc5121_nfc_verify_buf;
        chip->select_chip = mpc5121_nfc_select_chip;
        chip->bbt_options = NAND_BBT_USE_FLASH;
        chip->ecc.mode = NAND_ECC_SOFT;
index 5683604967d7687102bf97487d950a228ea8143a..72e31d86030d9c2e2b7f9cb20302b4b7955877f0 100644 (file)
@@ -43,8 +43,8 @@
 
 #define nfc_is_v21()           (cpu_is_mx25() || cpu_is_mx35())
 #define nfc_is_v1()            (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
-#define nfc_is_v3_2()          (cpu_is_mx51() || cpu_is_mx53())
-#define nfc_is_v3()            nfc_is_v3_2()
+#define nfc_is_v3_2a()         cpu_is_mx51()
+#define nfc_is_v3_2b()         cpu_is_mx53()
 
 /* Addresses for NFC registers */
 #define NFC_V1_V2_BUF_SIZE             (host->regs + 0x00)
 #define NFC_V3_CONFIG2_2CMD_PHASES             (1 << 4)
 #define NFC_V3_CONFIG2_NUM_ADDR_PHASE0         (1 << 5)
 #define NFC_V3_CONFIG2_ECC_MODE_8              (1 << 6)
-#define NFC_V3_CONFIG2_PPB(x)                  (((x) & 0x3) << 7)
+#define NFC_V3_CONFIG2_PPB(x, shift)           (((x) & 0x3) << shift)
 #define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x)      (((x) & 0x3) << 12)
 #define NFC_V3_CONFIG2_INT_MSK                 (1 << 15)
 #define NFC_V3_CONFIG2_ST_CMD(x)               (((x) & 0xff) << 24)
@@ -174,6 +174,7 @@ struct mxc_nand_devtype_data {
        int spare_len;
        int eccbytes;
        int eccsize;
+       int ppb_shift;
 };
 
 struct mxc_nand_host {
@@ -745,14 +746,6 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
        host->buf_start += n;
 }
 
-/* Used by the upper layer to verify the data in NAND Flash
- * with the data in the buf. */
-static int mxc_nand_verify_buf(struct mtd_info *mtd,
-                               const u_char *buf, int len)
-{
-       return -EFAULT;
-}
-
 /* This function is used by upper layer for select and
  * deselect of the NAND chip */
 static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
@@ -784,7 +777,7 @@ static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
        if (chip == -1) {
                /* Disable the NFC clock */
                if (host->clk_act) {
-                       clk_disable(host->clk);
+                       clk_disable_unprepare(host->clk);
                        host->clk_act = 0;
                }
                return;
@@ -792,7 +785,7 @@ static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
 
        if (!host->clk_act) {
                /* Enable the NFC clock */
-               clk_enable(host->clk);
+               clk_prepare_enable(host->clk);
                host->clk_act = 1;
        }
 
@@ -1021,7 +1014,9 @@ static void preset_v3(struct mtd_info *mtd)
        }
 
        if (mtd->writesize) {
-               config2 |= NFC_V3_CONFIG2_PPB(ffs(mtd->erasesize / mtd->writesize) - 6);
+               config2 |= NFC_V3_CONFIG2_PPB(
+                               ffs(mtd->erasesize / mtd->writesize) - 6,
+                               host->devtype_data->ppb_shift);
                host->eccsize = get_eccsize(mtd);
                if (host->eccsize == 8)
                        config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
@@ -1234,7 +1229,7 @@ static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
        .eccsize = 0,
 };
 
-/* v3: i.MX51, i.MX53 */
+/* v3.2a: i.MX51 */
 static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
        .preset = preset_v3,
        .send_cmd = send_cmd_v3,
@@ -1258,6 +1253,34 @@ static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
        .spare_len = 64,
        .eccbytes = 0,
        .eccsize = 0,
+       .ppb_shift = 7,
+};
+
+/* v3.2b: i.MX53 */
+static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
+       .preset = preset_v3,
+       .send_cmd = send_cmd_v3,
+       .send_addr = send_addr_v3,
+       .send_page = send_page_v3,
+       .send_read_id = send_read_id_v3,
+       .get_dev_status = get_dev_status_v3,
+       .check_int = check_int_v3,
+       .irq_control = irq_control_v3,
+       .get_ecc_status = get_ecc_status_v3,
+       .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
+       .ecclayout_2k = &nandv2_hw_eccoob_largepage,
+       .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
+       .select_chip = mxc_nand_select_chip_v1_v3,
+       .correct_data = mxc_nand_correct_data_v2_v3,
+       .irqpending_quirk = 0,
+       .needs_ip = 1,
+       .regs_offset = 0,
+       .spare0_offset = 0x1000,
+       .axi_offset = 0x1e00,
+       .spare_len = 64,
+       .eccbytes = 0,
+       .eccsize = 0,
+       .ppb_shift = 8,
 };
 
 #ifdef CONFIG_OF_MTD
@@ -1274,6 +1297,9 @@ static const struct of_device_id mxcnd_dt_ids[] = {
        }, {
                .compatible = "fsl,imx51-nand",
                .data = &imx51_nand_devtype_data,
+       }, {
+               .compatible = "fsl,imx53-nand",
+               .data = &imx53_nand_devtype_data,
        },
        { /* sentinel */ }
 };
@@ -1327,15 +1353,17 @@ static int __init mxcnd_probe_pdata(struct mxc_nand_host *host)
                        host->devtype_data = &imx27_nand_devtype_data;
        } else if (nfc_is_v21()) {
                host->devtype_data = &imx25_nand_devtype_data;
-       } else if (nfc_is_v3_2()) {
+       } else if (nfc_is_v3_2a()) {
                host->devtype_data = &imx51_nand_devtype_data;
+       } else if (nfc_is_v3_2b()) {
+               host->devtype_data = &imx53_nand_devtype_data;
        } else
                BUG();
 
        return 0;
 }
 
-static int __init mxcnd_probe(struct platform_device *pdev)
+static int __devinit mxcnd_probe(struct platform_device *pdev)
 {
        struct nand_chip *this;
        struct mtd_info *mtd;
@@ -1344,8 +1372,8 @@ static int __init mxcnd_probe(struct platform_device *pdev)
        int err = 0;
 
        /* Allocate memory for MTD device structure and private data */
-       host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE +
-                       NAND_MAX_OOBSIZE, GFP_KERNEL);
+       host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host) +
+                       NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE, GFP_KERNEL);
        if (!host)
                return -ENOMEM;
 
@@ -1370,36 +1398,38 @@ static int __init mxcnd_probe(struct platform_device *pdev)
        this->read_word = mxc_nand_read_word;
        this->write_buf = mxc_nand_write_buf;
        this->read_buf = mxc_nand_read_buf;
-       this->verify_buf = mxc_nand_verify_buf;
 
-       host->clk = clk_get(&pdev->dev, "nfc");
-       if (IS_ERR(host->clk)) {
-               err = PTR_ERR(host->clk);
-               goto eclk;
-       }
+       host->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(host->clk))
+               return PTR_ERR(host->clk);
 
-       clk_prepare_enable(host->clk);
-       host->clk_act = 1;
+       err = mxcnd_probe_dt(host);
+       if (err > 0)
+               err = mxcnd_probe_pdata(host);
+       if (err < 0)
+               return err;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               err = -ENODEV;
-               goto eres;
-       }
+       if (host->devtype_data->needs_ip) {
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+               if (!res)
+                       return -ENODEV;
+               host->regs_ip = devm_request_and_ioremap(&pdev->dev, res);
+               if (!host->regs_ip)
+                       return -ENOMEM;
 
-       host->base = ioremap(res->start, resource_size(res));
-       if (!host->base) {
-               err = -ENOMEM;
-               goto eres;
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       } else {
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        }
 
-       host->main_area0 = host->base;
+       if (!res)
+               return -ENODEV;
 
-       err = mxcnd_probe_dt(host);
-       if (err > 0)
-               err = mxcnd_probe_pdata(host);
-       if (err < 0)
-               goto eirq;
+       host->base = devm_request_and_ioremap(&pdev->dev, res);
+       if (!host->base)
+               return -ENOMEM;
+
+       host->main_area0 = host->base;
 
        if (host->devtype_data->regs_offset)
                host->regs = host->base + host->devtype_data->regs_offset;
@@ -1414,19 +1444,6 @@ static int __init mxcnd_probe(struct platform_device *pdev)
        this->ecc.size = 512;
        this->ecc.layout = host->devtype_data->ecclayout_512;
 
-       if (host->devtype_data->needs_ip) {
-               res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-               if (!res) {
-                       err = -ENODEV;
-                       goto eirq;
-               }
-               host->regs_ip = ioremap(res->start, resource_size(res));
-               if (!host->regs_ip) {
-                       err = -ENOMEM;
-                       goto eirq;
-               }
-       }
-
        if (host->pdata.hw_ecc) {
                this->ecc.calculate = mxc_nand_calculate_ecc;
                this->ecc.hwctl = mxc_nand_enable_hwecc;
@@ -1458,9 +1475,13 @@ static int __init mxcnd_probe(struct platform_device *pdev)
         */
        host->devtype_data->irq_control(host, 0);
 
-       err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
+       err = devm_request_irq(&pdev->dev, host->irq, mxc_nfc_irq,
+                       IRQF_DISABLED, DRIVER_NAME, host);
        if (err)
-               goto eirq;
+               return err;
+
+       clk_prepare_enable(host->clk);
+       host->clk_act = 1;
 
        /*
         * Now that we "own" the interrupt make sure the interrupt mask bit is
@@ -1512,15 +1533,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
        return 0;
 
 escan:
-       free_irq(host->irq, host);
-eirq:
-       if (host->regs_ip)
-               iounmap(host->regs_ip);
-       iounmap(host->base);
-eres:
-       clk_put(host->clk);
-eclk:
-       kfree(host);
+       clk_disable_unprepare(host->clk);
 
        return err;
 }
@@ -1529,16 +1542,9 @@ static int __devexit mxcnd_remove(struct platform_device *pdev)
 {
        struct mxc_nand_host *host = platform_get_drvdata(pdev);
 
-       clk_put(host->clk);
-
        platform_set_drvdata(pdev, NULL);
 
        nand_release(&host->mtd);
-       free_irq(host->irq, host);
-       if (host->regs_ip)
-               iounmap(host->regs_ip);
-       iounmap(host->base);
-       kfree(host);
 
        return 0;
 }
@@ -1549,22 +1555,10 @@ static struct platform_driver mxcnd_driver = {
                   .owner = THIS_MODULE,
                   .of_match_table = of_match_ptr(mxcnd_dt_ids),
        },
+       .probe = mxcnd_probe,
        .remove = __devexit_p(mxcnd_remove),
 };
-
-static int __init mxc_nd_init(void)
-{
-       return platform_driver_probe(&mxcnd_driver, mxcnd_probe);
-}
-
-static void __exit mxc_nd_cleanup(void)
-{
-       /* Unregister the device structure */
-       platform_driver_unregister(&mxcnd_driver);
-}
-
-module_init(mxc_nd_init);
-module_exit(mxc_nd_cleanup);
+module_platform_driver(mxcnd_driver);
 
 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 MODULE_DESCRIPTION("MXC NAND MTD driver");
index a11253a0fcabd6ef7362b9fcae4972ba06fc4966..ec6841d8e956f74f5224363392632900a39e1f8e 100644 (file)
@@ -242,25 +242,6 @@ static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
                buf[i] = readb(chip->IO_ADDR_R);
 }
 
-/**
- * nand_verify_buf - [DEFAULT] Verify chip data against buffer
- * @mtd: MTD device structure
- * @buf: buffer containing the data to compare
- * @len: number of bytes to compare
- *
- * Default verify function for 8bit buswidth.
- */
-static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
-{
-       int i;
-       struct nand_chip *chip = mtd->priv;
-
-       for (i = 0; i < len; i++)
-               if (buf[i] != readb(chip->IO_ADDR_R))
-                       return -EFAULT;
-       return 0;
-}
-
 /**
  * nand_write_buf16 - [DEFAULT] write buffer to chip
  * @mtd: MTD device structure
@@ -300,28 +281,6 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
                p[i] = readw(chip->IO_ADDR_R);
 }
 
-/**
- * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
- * @mtd: MTD device structure
- * @buf: buffer containing the data to compare
- * @len: number of bytes to compare
- *
- * Default verify function for 16bit buswidth.
- */
-static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
-{
-       int i;
-       struct nand_chip *chip = mtd->priv;
-       u16 *p = (u16 *) buf;
-       len >>= 1;
-
-       for (i = 0; i < len; i++)
-               if (p[i] != readw(chip->IO_ADDR_R))
-                       return -EFAULT;
-
-       return 0;
-}
-
 /**
  * nand_block_bad - [DEFAULT] Read bad block marker from the chip
  * @mtd: MTD device structure
@@ -1525,7 +1484,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                                ret = chip->ecc.read_page_raw(mtd, chip, bufpoi,
                                                              oob_required,
                                                              page);
-                       else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
+                       else if (!aligned && NAND_HAS_SUBPAGE_READ(chip) &&
+                                !oob)
                                ret = chip->ecc.read_subpage(mtd, chip,
                                                        col, bytes, bufpoi);
                        else
@@ -1542,7 +1502,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 
                        /* Transfer not aligned data */
                        if (!aligned) {
-                               if (!NAND_SUBPAGE_READ(chip) && !oob &&
+                               if (!NAND_HAS_SUBPAGE_READ(chip) && !oob &&
                                    !(mtd->ecc_stats.failed - stats.failed) &&
                                    (ops->mode != MTD_OPS_RAW)) {
                                        chip->pagebuf = realpage;
@@ -1565,14 +1525,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                                        oobreadlen -= toread;
                                }
                        }
-
-                       if (!(chip->options & NAND_NO_READRDY)) {
-                               /* Apply delay or wait for ready/busy pin */
-                               if (!chip->dev_ready)
-                                       udelay(chip->chip_delay);
-                               else
-                                       nand_wait_ready(mtd);
-                       }
                } else {
                        memcpy(buf, chip->buffers->databuf + col, bytes);
                        buf += bytes;
@@ -1633,7 +1585,7 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
        ops.len = len;
        ops.datbuf = buf;
        ops.oobbuf = NULL;
-       ops.mode = 0;
+       ops.mode = MTD_OPS_PLACE_OOB;
        ret = nand_do_read_ops(mtd, from, &ops);
        *retlen = ops.retlen;
        nand_release_device(mtd);
@@ -1837,14 +1789,6 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
                len = min(len, readlen);
                buf = nand_transfer_oob(chip, buf, ops, len);
 
-               if (!(chip->options & NAND_NO_READRDY)) {
-                       /* Apply delay or wait for ready/busy pin */
-                       if (!chip->dev_ready)
-                               udelay(chip->chip_delay);
-                       else
-                               nand_wait_ready(mtd);
-               }
-
                readlen -= len;
                if (!readlen)
                        break;
@@ -1927,12 +1871,14 @@ out:
  *
  * Not for syndrome calculating ECC controllers, which use a special oob layout.
  */
-static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
                                const uint8_t *buf, int oob_required)
 {
        chip->write_buf(mtd, buf, mtd->writesize);
        if (oob_required)
                chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       return 0;
 }
 
 /**
@@ -1944,7 +1890,7 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
  *
  * We need a special oob layout and handling even when ECC isn't checked.
  */
-static void nand_write_page_raw_syndrome(struct mtd_info *mtd,
+static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
                                        struct nand_chip *chip,
                                        const uint8_t *buf, int oob_required)
 {
@@ -1974,6 +1920,8 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd,
        size = mtd->oobsize - (oob - chip->oob_poi);
        if (size)
                chip->write_buf(mtd, oob, size);
+
+       return 0;
 }
 /**
  * nand_write_page_swecc - [REPLACEABLE] software ECC based page write function
@@ -1982,7 +1930,7 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd,
  * @buf: data buffer
  * @oob_required: must write chip->oob_poi to OOB
  */
-static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
+static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
                                  const uint8_t *buf, int oob_required)
 {
        int i, eccsize = chip->ecc.size;
@@ -1999,7 +1947,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
        for (i = 0; i < chip->ecc.total; i++)
                chip->oob_poi[eccpos[i]] = ecc_calc[i];
 
-       chip->ecc.write_page_raw(mtd, chip, buf, 1);
+       return chip->ecc.write_page_raw(mtd, chip, buf, 1);
 }
 
 /**
@@ -2009,7 +1957,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
  * @buf: data buffer
  * @oob_required: must write chip->oob_poi to OOB
  */
-static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
+static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
                                  const uint8_t *buf, int oob_required)
 {
        int i, eccsize = chip->ecc.size;
@@ -2029,6 +1977,8 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
                chip->oob_poi[eccpos[i]] = ecc_calc[i];
 
        chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       return 0;
 }
 
 /**
@@ -2041,7 +1991,7 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
  * The hw generator calculates the error syndrome automatically. Therefore we
  * need a special oob layout and handling.
  */
-static void nand_write_page_syndrome(struct mtd_info *mtd,
+static int nand_write_page_syndrome(struct mtd_info *mtd,
                                    struct nand_chip *chip,
                                    const uint8_t *buf, int oob_required)
 {
@@ -2075,6 +2025,8 @@ static void nand_write_page_syndrome(struct mtd_info *mtd,
        i = mtd->oobsize - (oob - chip->oob_poi);
        if (i)
                chip->write_buf(mtd, oob, i);
+
+       return 0;
 }
 
 /**
@@ -2096,9 +2048,12 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
        chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
 
        if (unlikely(raw))
-               chip->ecc.write_page_raw(mtd, chip, buf, oob_required);
+               status = chip->ecc.write_page_raw(mtd, chip, buf, oob_required);
        else
-               chip->ecc.write_page(mtd, chip, buf, oob_required);
+               status = chip->ecc.write_page(mtd, chip, buf, oob_required);
+
+       if (status < 0)
+               return status;
 
        /*
         * Cached progamming disabled for now. Not sure if it's worth the
@@ -2125,16 +2080,6 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                status = chip->waitfunc(mtd, chip);
        }
 
-#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
-       /* Send command to read back the data */
-       chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
-
-       if (chip->verify_buf(mtd, buf, mtd->writesize))
-               return -EIO;
-
-       /* Make sure the next page prog is preceded by a status read */
-       chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
-#endif
        return 0;
 }
 
@@ -2336,7 +2281,7 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
        ops.len = len;
        ops.datbuf = (uint8_t *)buf;
        ops.oobbuf = NULL;
-       ops.mode = 0;
+       ops.mode = MTD_OPS_PLACE_OOB;
 
        ret = nand_do_write_ops(mtd, to, &ops);
 
@@ -2365,7 +2310,7 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
        ops.len = len;
        ops.datbuf = (uint8_t *)buf;
        ops.oobbuf = NULL;
-       ops.mode = 0;
+       ops.mode = MTD_OPS_PLACE_OOB;
        ret = nand_do_write_ops(mtd, to, &ops);
        *retlen = ops.retlen;
        nand_release_device(mtd);
@@ -2754,6 +2699,50 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
        return chip->block_markbad(mtd, ofs);
 }
 
+/**
+ * nand_onfi_set_features- [REPLACEABLE] set features for ONFI nand
+ * @mtd: MTD device structure
+ * @chip: nand chip info structure
+ * @addr: feature address.
+ * @subfeature_param: the subfeature parameters, a four bytes array.
+ */
+static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
+                       int addr, uint8_t *subfeature_param)
+{
+       int status;
+
+       if (!chip->onfi_version)
+               return -EINVAL;
+
+       chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1);
+       chip->write_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN);
+       status = chip->waitfunc(mtd, chip);
+       if (status & NAND_STATUS_FAIL)
+               return -EIO;
+       return 0;
+}
+
+/**
+ * nand_onfi_get_features- [REPLACEABLE] get features for ONFI nand
+ * @mtd: MTD device structure
+ * @chip: nand chip info structure
+ * @addr: feature address.
+ * @subfeature_param: the subfeature parameters, a four bytes array.
+ */
+static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
+                       int addr, uint8_t *subfeature_param)
+{
+       if (!chip->onfi_version)
+               return -EINVAL;
+
+       /* clear the sub feature parameters */
+       memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN);
+
+       chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1);
+       chip->read_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN);
+       return 0;
+}
+
 /**
  * nand_suspend - [MTD Interface] Suspend the NAND flash
  * @mtd: MTD device structure
@@ -2809,8 +2798,6 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
                chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
        if (!chip->read_buf)
                chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
-       if (!chip->verify_buf)
-               chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
        if (!chip->scan_bbt)
                chip->scan_bbt = nand_default_bbt;
 
@@ -2914,13 +2901,249 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
        if (le16_to_cpu(p->features) & 1)
                *busw = NAND_BUSWIDTH_16;
 
-       chip->options &= ~NAND_CHIPOPTIONS_MSK;
-       chip->options |= NAND_NO_READRDY & NAND_CHIPOPTIONS_MSK;
-
        pr_info("ONFI flash detected\n");
        return 1;
 }
 
+/*
+ * nand_id_has_period - Check if an ID string has a given wraparound period
+ * @id_data: the ID string
+ * @arrlen: the length of the @id_data array
+ * @period: the period of repitition
+ *
+ * Check if an ID string is repeated within a given sequence of bytes at
+ * specific repetition interval period (e.g., {0x20,0x01,0x7F,0x20} has a
+ * period of 2). This is a helper function for nand_id_len(). Returns non-zero
+ * if the repetition has a period of @period; otherwise, returns zero.
+ */
+static int nand_id_has_period(u8 *id_data, int arrlen, int period)
+{
+       int i, j;
+       for (i = 0; i < period; i++)
+               for (j = i + period; j < arrlen; j += period)
+                       if (id_data[i] != id_data[j])
+                               return 0;
+       return 1;
+}
+
+/*
+ * nand_id_len - Get the length of an ID string returned by CMD_READID
+ * @id_data: the ID string
+ * @arrlen: the length of the @id_data array
+
+ * Returns the length of the ID string, according to known wraparound/trailing
+ * zero patterns. If no pattern exists, returns the length of the array.
+ */
+static int nand_id_len(u8 *id_data, int arrlen)
+{
+       int last_nonzero, period;
+
+       /* Find last non-zero byte */
+       for (last_nonzero = arrlen - 1; last_nonzero >= 0; last_nonzero--)
+               if (id_data[last_nonzero])
+                       break;
+
+       /* All zeros */
+       if (last_nonzero < 0)
+               return 0;
+
+       /* Calculate wraparound period */
+       for (period = 1; period < arrlen; period++)
+               if (nand_id_has_period(id_data, arrlen, period))
+                       break;
+
+       /* There's a repeated pattern */
+       if (period < arrlen)
+               return period;
+
+       /* There are trailing zeros */
+       if (last_nonzero < arrlen - 1)
+               return last_nonzero + 1;
+
+       /* No pattern detected */
+       return arrlen;
+}
+
+/*
+ * Many new NAND share similar device ID codes, which represent the size of the
+ * chip. The rest of the parameters must be decoded according to generic or
+ * manufacturer-specific "extended ID" decoding patterns.
+ */
+static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
+                               u8 id_data[8], int *busw)
+{
+       int extid, id_len;
+       /* The 3rd id byte holds MLC / multichip data */
+       chip->cellinfo = id_data[2];
+       /* The 4th id byte is the important one */
+       extid = id_data[3];
+
+       id_len = nand_id_len(id_data, 8);
+
+       /*
+        * Field definitions are in the following datasheets:
+        * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
+        * New style   (6 byte ID): Samsung K9GAG08U0F (p.44)
+        * Hynix MLC   (6 byte ID): Hynix H27UBG8T2B (p.22)
+        *
+        * Check for ID length, cell type, and Hynix/Samsung ID to decide what
+        * to do.
+        */
+       if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG) {
+               /* Calc pagesize */
+               mtd->writesize = 2048 << (extid & 0x03);
+               extid >>= 2;
+               /* Calc oobsize */
+               switch (((extid >> 2) & 0x04) | (extid & 0x03)) {
+               case 1:
+                       mtd->oobsize = 128;
+                       break;
+               case 2:
+                       mtd->oobsize = 218;
+                       break;
+               case 3:
+                       mtd->oobsize = 400;
+                       break;
+               case 4:
+                       mtd->oobsize = 436;
+                       break;
+               case 5:
+                       mtd->oobsize = 512;
+                       break;
+               case 6:
+               default: /* Other cases are "reserved" (unknown) */
+                       mtd->oobsize = 640;
+                       break;
+               }
+               extid >>= 2;
+               /* Calc blocksize */
+               mtd->erasesize = (128 * 1024) <<
+                       (((extid >> 1) & 0x04) | (extid & 0x03));
+               *busw = 0;
+       } else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX &&
+                       (chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
+               unsigned int tmp;
+
+               /* Calc pagesize */
+               mtd->writesize = 2048 << (extid & 0x03);
+               extid >>= 2;
+               /* Calc oobsize */
+               switch (((extid >> 2) & 0x04) | (extid & 0x03)) {
+               case 0:
+                       mtd->oobsize = 128;
+                       break;
+               case 1:
+                       mtd->oobsize = 224;
+                       break;
+               case 2:
+                       mtd->oobsize = 448;
+                       break;
+               case 3:
+                       mtd->oobsize = 64;
+                       break;
+               case 4:
+                       mtd->oobsize = 32;
+                       break;
+               case 5:
+                       mtd->oobsize = 16;
+                       break;
+               default:
+                       mtd->oobsize = 640;
+                       break;
+               }
+               extid >>= 2;
+               /* Calc blocksize */
+               tmp = ((extid >> 1) & 0x04) | (extid & 0x03);
+               if (tmp < 0x03)
+                       mtd->erasesize = (128 * 1024) << tmp;
+               else if (tmp == 0x03)
+                       mtd->erasesize = 768 * 1024;
+               else
+                       mtd->erasesize = (64 * 1024) << tmp;
+               *busw = 0;
+       } else {
+               /* Calc pagesize */
+               mtd->writesize = 1024 << (extid & 0x03);
+               extid >>= 2;
+               /* Calc oobsize */
+               mtd->oobsize = (8 << (extid & 0x01)) *
+                       (mtd->writesize >> 9);
+               extid >>= 2;
+               /* Calc blocksize. Blocksize is multiples of 64KiB */
+               mtd->erasesize = (64 * 1024) << (extid & 0x03);
+               extid >>= 2;
+               /* Get buswidth information */
+               *busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
+       }
+}
+
+/*
+ * Old devices have chip data hardcoded in the device ID table. nand_decode_id
+ * decodes a matching ID table entry and assigns the MTD size parameters for
+ * the chip.
+ */
+static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip,
+                               struct nand_flash_dev *type, u8 id_data[8],
+                               int *busw)
+{
+       int maf_id = id_data[0];
+
+       mtd->erasesize = type->erasesize;
+       mtd->writesize = type->pagesize;
+       mtd->oobsize = mtd->writesize / 32;
+       *busw = type->options & NAND_BUSWIDTH_16;
+
+       /*
+        * Check for Spansion/AMD ID + repeating 5th, 6th byte since
+        * some Spansion chips have erasesize that conflicts with size
+        * listed in nand_ids table.
+        * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
+        */
+       if (maf_id == NAND_MFR_AMD && id_data[4] != 0x00 && id_data[5] == 0x00
+                       && id_data[6] == 0x00 && id_data[7] == 0x00
+                       && mtd->writesize == 512) {
+               mtd->erasesize = 128 * 1024;
+               mtd->erasesize <<= ((id_data[3] & 0x03) << 1);
+       }
+}
+
+/*
+ * Set the bad block marker/indicator (BBM/BBI) patterns according to some
+ * heuristic patterns using various detected parameters (e.g., manufacturer,
+ * page size, cell-type information).
+ */
+static void nand_decode_bbm_options(struct mtd_info *mtd,
+                                   struct nand_chip *chip, u8 id_data[8])
+{
+       int maf_id = id_data[0];
+
+       /* Set the bad block position */
+       if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16))
+               chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
+       else
+               chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
+
+       /*
+        * Bad block marker is stored in the last page of each block on Samsung
+        * and Hynix MLC devices; stored in first two pages of each block on
+        * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba,
+        * AMD/Spansion, and Macronix.  All others scan only the first page.
+        */
+       if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+                       (maf_id == NAND_MFR_SAMSUNG ||
+                        maf_id == NAND_MFR_HYNIX))
+               chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
+       else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+                               (maf_id == NAND_MFR_SAMSUNG ||
+                                maf_id == NAND_MFR_HYNIX ||
+                                maf_id == NAND_MFR_TOSHIBA ||
+                                maf_id == NAND_MFR_AMD ||
+                                maf_id == NAND_MFR_MACRONIX)) ||
+                       (mtd->writesize == 2048 &&
+                        maf_id == NAND_MFR_MICRON))
+               chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+}
+
 /*
  * Get the flash and manufacturer id and lookup if the type is supported.
  */
@@ -2932,7 +3155,6 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 {
        int i, maf_idx;
        u8 id_data[8];
-       int ret;
 
        /* Select the device */
        chip->select_chip(mtd, 0);
@@ -2959,7 +3181,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 
        chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
 
-       for (i = 0; i < 2; i++)
+       /* Read entire ID string */
+       for (i = 0; i < 8; i++)
                id_data[i] = chip->read_byte(mtd);
 
        if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
@@ -2979,18 +3202,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
        chip->onfi_version = 0;
        if (!type->name || !type->pagesize) {
                /* Check is chip is ONFI compliant */
-               ret = nand_flash_detect_onfi(mtd, chip, &busw);
-               if (ret)
+               if (nand_flash_detect_onfi(mtd, chip, &busw))
                        goto ident_done;
        }
 
-       chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
-
-       /* Read entire ID string */
-
-       for (i = 0; i < 8; i++)
-               id_data[i] = chip->read_byte(mtd);
-
        if (!type->name)
                return ERR_PTR(-ENODEV);
 
@@ -3003,86 +3218,13 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
                /* Set the pagesize, oobsize, erasesize by the driver */
                busw = chip->init_size(mtd, chip, id_data);
        } else if (!type->pagesize) {
-               int extid;
-               /* The 3rd id byte holds MLC / multichip data */
-               chip->cellinfo = id_data[2];
-               /* The 4th id byte is the important one */
-               extid = id_data[3];
-
-               /*
-                * Field definitions are in the following datasheets:
-                * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
-                * New style   (6 byte ID): Samsung K9GBG08U0M (p.40)
-                *
-                * Check for wraparound + Samsung ID + nonzero 6th byte
-                * to decide what to do.
-                */
-               if (id_data[0] == id_data[6] && id_data[1] == id_data[7] &&
-                               id_data[0] == NAND_MFR_SAMSUNG &&
-                               (chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
-                               id_data[5] != 0x00) {
-                       /* Calc pagesize */
-                       mtd->writesize = 2048 << (extid & 0x03);
-                       extid >>= 2;
-                       /* Calc oobsize */
-                       switch (extid & 0x03) {
-                       case 1:
-                               mtd->oobsize = 128;
-                               break;
-                       case 2:
-                               mtd->oobsize = 218;
-                               break;
-                       case 3:
-                               mtd->oobsize = 400;
-                               break;
-                       default:
-                               mtd->oobsize = 436;
-                               break;
-                       }
-                       extid >>= 2;
-                       /* Calc blocksize */
-                       mtd->erasesize = (128 * 1024) <<
-                               (((extid >> 1) & 0x04) | (extid & 0x03));
-                       busw = 0;
-               } else {
-                       /* Calc pagesize */
-                       mtd->writesize = 1024 << (extid & 0x03);
-                       extid >>= 2;
-                       /* Calc oobsize */
-                       mtd->oobsize = (8 << (extid & 0x01)) *
-                               (mtd->writesize >> 9);
-                       extid >>= 2;
-                       /* Calc blocksize. Blocksize is multiples of 64KiB */
-                       mtd->erasesize = (64 * 1024) << (extid & 0x03);
-                       extid >>= 2;
-                       /* Get buswidth information */
-                       busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
-               }
+               /* Decode parameters from extended ID */
+               nand_decode_ext_id(mtd, chip, id_data, &busw);
        } else {
-               /*
-                * Old devices have chip data hardcoded in the device id table.
-                */
-               mtd->erasesize = type->erasesize;
-               mtd->writesize = type->pagesize;
-               mtd->oobsize = mtd->writesize / 32;
-               busw = type->options & NAND_BUSWIDTH_16;
-
-               /*
-                * Check for Spansion/AMD ID + repeating 5th, 6th byte since
-                * some Spansion chips have erasesize that conflicts with size
-                * listed in nand_ids table.
-                * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
-                */
-               if (*maf_id == NAND_MFR_AMD && id_data[4] != 0x00 &&
-                               id_data[5] == 0x00 && id_data[6] == 0x00 &&
-                               id_data[7] == 0x00 && mtd->writesize == 512) {
-                       mtd->erasesize = 128 * 1024;
-                       mtd->erasesize <<= ((id_data[3] & 0x03) << 1);
-               }
+               nand_decode_id(mtd, chip, type, id_data, &busw);
        }
-       /* Get chip options, preserve non chip based options */
-       chip->options &= ~NAND_CHIPOPTIONS_MSK;
-       chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
+       /* Get chip options */
+       chip->options |= type->options;
 
        /*
         * Check if chip is not a Samsung device. Do not clear the
@@ -3112,6 +3254,8 @@ ident_done:
                return ERR_PTR(-EINVAL);
        }
 
+       nand_decode_bbm_options(mtd, chip, id_data);
+
        /* Calculate the address shift from the page size */
        chip->page_shift = ffs(mtd->writesize) - 1;
        /* Convert chipsize to number of pages per chip -1 */
@@ -3128,33 +3272,6 @@ ident_done:
 
        chip->badblockbits = 8;
 
-       /* Set the bad block position */
-       if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16))
-               chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
-       else
-               chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
-
-       /*
-        * Bad block marker is stored in the last page of each block
-        * on Samsung and Hynix MLC devices; stored in first two pages
-        * of each block on Micron devices with 2KiB pages and on
-        * SLC Samsung, Hynix, Toshiba, AMD/Spansion, and Macronix.
-        * All others scan only the first page.
-        */
-       if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
-                       (*maf_id == NAND_MFR_SAMSUNG ||
-                        *maf_id == NAND_MFR_HYNIX))
-               chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
-       else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
-                               (*maf_id == NAND_MFR_SAMSUNG ||
-                                *maf_id == NAND_MFR_HYNIX ||
-                                *maf_id == NAND_MFR_TOSHIBA ||
-                                *maf_id == NAND_MFR_AMD ||
-                                *maf_id == NAND_MFR_MACRONIX)) ||
-                       (mtd->writesize == 2048 &&
-                        *maf_id == NAND_MFR_MICRON))
-               chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
-
        /* Check for AND chips with 4 page planes */
        if (chip->options & NAND_4PAGE_ARRAY)
                chip->erase_cmd = multi_erase_cmd;
@@ -3284,6 +3401,12 @@ int nand_scan_tail(struct mtd_info *mtd)
        if (!chip->write_page)
                chip->write_page = nand_write_page;
 
+       /* set for ONFI nand */
+       if (!chip->onfi_set_features)
+               chip->onfi_set_features = nand_onfi_set_features;
+       if (!chip->onfi_get_features)
+               chip->onfi_get_features = nand_onfi_get_features;
+
        /*
         * Check ECC mode, default to software if 3byte/512byte hardware ECC is
         * selected and we have 256 byte pagesize fallback to software ECC
@@ -3477,6 +3600,10 @@ int nand_scan_tail(struct mtd_info *mtd)
        /* Invalidate the pagebuffer reference */
        chip->pagebuf = -1;
 
+       /* Large page NAND with SOFT_ECC should support subpage reads */
+       if ((chip->ecc.mode == NAND_ECC_SOFT) && (chip->page_shift > 9))
+               chip->options |= NAND_SUBPAGE_READ;
+
        /* Fill in remaining MTD driver data */
        mtd->type = MTD_NANDFLASH;
        mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM :
index 30d1319ff0657ce75b063023d9eee0c65d2f5873..916d6e9c0ab1d9c5872c0ed66b26832ff4bf9062 100644 (file)
@@ -4,7 +4,7 @@
  *  Overview:
  *   Bad block table support for the NAND driver
  *
- *  Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
+ *  Copyright Â© 2004 Thomas Gleixner (tglx@linutronix.de)
  *
  * 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
@@ -22,7 +22,7 @@
  * BBT on flash. If a BBT is found then the contents are read and the memory
  * based BBT is created. If a mirrored BBT is selected then the mirror is
  * searched too and the versions are compared. If the mirror has a greater
- * version number than the mirror BBT is used to build the memory based BBT.
+ * version number, then the mirror BBT is used to build the memory based BBT.
  * If the tables are not versioned, then we "or" the bad block information.
  * If one of the BBTs is out of date or does not exist it is (re)created.
  * If no BBT exists at all then the device is scanned for factory marked
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/bbm.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
 #include <linux/export.h>
+#include <linux/string.h>
 
 static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
 {
-       int ret;
-
-       ret = memcmp(buf, td->pattern, td->len);
-       if (!ret)
-               return ret;
-       return -1;
+       if (memcmp(buf, td->pattern, td->len))
+               return -1;
+       return 0;
 }
 
 /**
@@ -92,19 +91,16 @@ static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
  */
 static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
 {
-       int i, end = 0;
+       int end = 0;
        uint8_t *p = buf;
 
        if (td->options & NAND_BBT_NO_OOB)
                return check_pattern_no_oob(buf, td);
 
        end = paglen + td->offs;
-       if (td->options & NAND_BBT_SCANEMPTY) {
-               for (i = 0; i < end; i++) {
-                       if (p[i] != 0xff)
-                               return -1;
-               }
-       }
+       if (td->options & NAND_BBT_SCANEMPTY)
+               if (memchr_inv(p, 0xff, end))
+                       return -1;
        p += end;
 
        /* Compare the pattern */
@@ -114,10 +110,8 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc
        if (td->options & NAND_BBT_SCANEMPTY) {
                p += td->len;
                end += td->len;
-               for (i = end; i < len; i++) {
-                       if (*p++ != 0xff)
-                               return -1;
-               }
+               if (memchr_inv(p, 0xff, len - end))
+                       return -1;
        }
        return 0;
 }
@@ -133,14 +127,9 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc
  */
 static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
 {
-       int i;
-       uint8_t *p = buf;
-
        /* Compare the pattern */
-       for (i = 0; i < td->len; i++) {
-               if (p[td->offs + i] != td->pattern[i])
-                       return -1;
-       }
+       if (memcmp(buf + td->offs, td->pattern, td->len))
+               return -1;
        return 0;
 }
 
@@ -288,7 +277,7 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 }
 
 /* BBT marker is in the first page, no OOB */
-static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
+static int scan_read_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
                         struct nand_bbt_descr *td)
 {
        size_t retlen;
@@ -301,14 +290,24 @@ static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
        return mtd_read(mtd, offs, len, &retlen, buf);
 }
 
-/* Scan read raw data from flash */
-static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
+/**
+ * scan_read_oob - [GENERIC] Scan data+OOB region to buffer
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @offs: offset at which to scan
+ * @len: length of data region to read
+ *
+ * Scan read data from data+OOB. May traverse multiple pages, interleaving
+ * page,OOB,page,OOB,... in buf. Completes transfer and returns the "strongest"
+ * ECC condition (error or bitflip). May quit on the first (non-ECC) error.
+ */
+static int scan_read_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
                         size_t len)
 {
        struct mtd_oob_ops ops;
-       int res;
+       int res, ret = 0;
 
-       ops.mode = MTD_OPS_RAW;
+       ops.mode = MTD_OPS_PLACE_OOB;
        ops.ooboffs = 0;
        ops.ooblen = mtd->oobsize;
 
@@ -318,24 +317,27 @@ static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
                ops.oobbuf = buf + ops.len;
 
                res = mtd_read_oob(mtd, offs, &ops);
-
-               if (res)
-                       return res;
+               if (res) {
+                       if (!mtd_is_bitflip_or_eccerr(res))
+                               return res;
+                       else if (mtd_is_eccerr(res) || !ret)
+                               ret = res;
+               }
 
                buf += mtd->oobsize + mtd->writesize;
                len -= mtd->writesize;
                offs += mtd->writesize;
        }
-       return 0;
+       return ret;
 }
 
-static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
+static int scan_read(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
                         size_t len, struct nand_bbt_descr *td)
 {
        if (td->options & NAND_BBT_NO_OOB)
-               return scan_read_raw_data(mtd, buf, offs, td);
+               return scan_read_data(mtd, buf, offs, td);
        else
-               return scan_read_raw_oob(mtd, buf, offs, len);
+               return scan_read_oob(mtd, buf, offs, len);
 }
 
 /* Scan write data with oob to flash */
@@ -373,14 +375,14 @@ static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td)
  * Read the bad block table(s) for all chips starting at a given page. We
  * assume that the bbt bits are in consecutive order.
  */
-static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
-                        struct nand_bbt_descr *td, struct nand_bbt_descr *md)
+static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
+                         struct nand_bbt_descr *td, struct nand_bbt_descr *md)
 {
        struct nand_chip *this = mtd->priv;
 
        /* Read the primary version, if available */
        if (td->options & NAND_BBT_VERSION) {
-               scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift,
+               scan_read(mtd, buf, (loff_t)td->pages[0] << this->page_shift,
                              mtd->writesize, td);
                td->version[0] = buf[bbt_get_ver_offs(mtd, td)];
                pr_info("Bad block table at page %d, version 0x%02X\n",
@@ -389,28 +391,27 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
 
        /* Read the mirror version, if available */
        if (md && (md->options & NAND_BBT_VERSION)) {
-               scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
-                             mtd->writesize, td);
+               scan_read(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
+                             mtd->writesize, md);
                md->version[0] = buf[bbt_get_ver_offs(mtd, md)];
                pr_info("Bad block table at page %d, version 0x%02X\n",
                         md->pages[0], md->version[0]);
        }
-       return 1;
 }
 
 /* Scan a given block full */
 static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
                           loff_t offs, uint8_t *buf, size_t readlen,
-                          int scanlen, int len)
+                          int scanlen, int numpages)
 {
        int ret, j;
 
-       ret = scan_read_raw_oob(mtd, buf, offs, readlen);
+       ret = scan_read_oob(mtd, buf, offs, readlen);
        /* Ignore ECC errors when checking for BBM */
        if (ret && !mtd_is_bitflip_or_eccerr(ret))
                return ret;
 
-       for (j = 0; j < len; j++, buf += scanlen) {
+       for (j = 0; j < numpages; j++, buf += scanlen) {
                if (check_pattern(buf, scanlen, mtd->writesize, bd))
                        return 1;
        }
@@ -419,7 +420,7 @@ static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
 
 /* Scan a given block partially */
 static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
-                          loff_t offs, uint8_t *buf, int len)
+                          loff_t offs, uint8_t *buf, int numpages)
 {
        struct mtd_oob_ops ops;
        int j, ret;
@@ -430,7 +431,7 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
        ops.datbuf = NULL;
        ops.mode = MTD_OPS_PLACE_OOB;
 
-       for (j = 0; j < len; j++) {
+       for (j = 0; j < numpages; j++) {
                /*
                 * Read the full oob until read_oob is fixed to handle single
                 * byte reads for 16 bit buswidth.
@@ -463,7 +464,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
        struct nand_bbt_descr *bd, int chip)
 {
        struct nand_chip *this = mtd->priv;
-       int i, numblocks, len, scanlen;
+       int i, numblocks, numpages, scanlen;
        int startblock;
        loff_t from;
        size_t readlen;
@@ -471,11 +472,11 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
        pr_info("Scanning device for bad blocks\n");
 
        if (bd->options & NAND_BBT_SCANALLPAGES)
-               len = 1 << (this->bbt_erase_shift - this->page_shift);
+               numpages = 1 << (this->bbt_erase_shift - this->page_shift);
        else if (bd->options & NAND_BBT_SCAN2NDPAGE)
-               len = 2;
+               numpages = 2;
        else
-               len = 1;
+               numpages = 1;
 
        if (!(bd->options & NAND_BBT_SCANEMPTY)) {
                /* We need only read few bytes from the OOB area */
@@ -484,7 +485,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
        } else {
                /* Full page content should be read */
                scanlen = mtd->writesize + mtd->oobsize;
-               readlen = len * mtd->writesize;
+               readlen = numpages * mtd->writesize;
        }
 
        if (chip == -1) {
@@ -508,7 +509,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
        }
 
        if (this->bbt_options & NAND_BBT_SCANLASTPAGE)
-               from += mtd->erasesize - (mtd->writesize * len);
+               from += mtd->erasesize - (mtd->writesize * numpages);
 
        for (i = startblock; i < numblocks;) {
                int ret;
@@ -517,9 +518,9 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 
                if (bd->options & NAND_BBT_SCANALLPAGES)
                        ret = scan_block_full(mtd, bd, from, buf, readlen,
-                                             scanlen, len);
+                                             scanlen, numpages);
                else
-                       ret = scan_block_fast(mtd, bd, from, buf, len);
+                       ret = scan_block_fast(mtd, bd, from, buf, numpages);
 
                if (ret < 0)
                        return ret;
@@ -594,7 +595,7 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
                        loff_t offs = (loff_t)actblock << this->bbt_erase_shift;
 
                        /* Read first page */
-                       scan_read_raw(mtd, buf, offs, mtd->writesize, td);
+                       scan_read(mtd, buf, offs, mtd->writesize, td);
                        if (!check_pattern(buf, scanlen, mtd->writesize, td)) {
                                td->pages[i] = actblock << blocktopage;
                                if (td->options & NAND_BBT_VERSION) {
@@ -626,7 +627,9 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
  *
  * Search and read the bad block table(s).
  */
-static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md)
+static void search_read_bbts(struct mtd_info *mtd, uint8_t *buf,
+                            struct nand_bbt_descr *td,
+                            struct nand_bbt_descr *md)
 {
        /* Search the primary table */
        search_bbt(mtd, buf, td);
@@ -634,9 +637,6 @@ static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt
        /* Search the mirror table */
        if (md)
                search_bbt(mtd, buf, md);
-
-       /* Force result check */
-       return 1;
 }
 
 /**
@@ -1162,14 +1162,13 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 
        /* Is the bbt at a given page? */
        if (td->options & NAND_BBT_ABSPAGE) {
-               res = read_abs_bbts(mtd, buf, td, md);
+               read_abs_bbts(mtd, buf, td, md);
        } else {
                /* Search the bad block table using a pattern in oob */
-               res = search_read_bbts(mtd, buf, td, md);
+               search_read_bbts(mtd, buf, td, md);
        }
 
-       if (res)
-               res = check_create(mtd, buf, bd);
+       res = check_create(mtd, buf, bd);
 
        /* Prevent the bbt regions from erasing / writing */
        mark_bbt_region(mtd, td);
@@ -1260,7 +1259,7 @@ static struct nand_bbt_descr bbt_main_descr = {
        .offs = 8,
        .len = 4,
        .veroffs = 12,
-       .maxblocks = 4,
+       .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
        .pattern = bbt_pattern
 };
 
@@ -1270,27 +1269,27 @@ static struct nand_bbt_descr bbt_mirror_descr = {
        .offs = 8,
        .len = 4,
        .veroffs = 12,
-       .maxblocks = 4,
+       .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
        .pattern = mirror_pattern
 };
 
-static struct nand_bbt_descr bbt_main_no_bbt_descr = {
+static struct nand_bbt_descr bbt_main_no_oob_descr = {
        .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
                | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
                | NAND_BBT_NO_OOB,
        .len = 4,
        .veroffs = 4,
-       .maxblocks = 4,
+       .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
        .pattern = bbt_pattern
 };
 
-static struct nand_bbt_descr bbt_mirror_no_bbt_descr = {
+static struct nand_bbt_descr bbt_mirror_no_oob_descr = {
        .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
                | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
                | NAND_BBT_NO_OOB,
        .len = 4,
        .veroffs = 4,
-       .maxblocks = 4,
+       .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
        .pattern = mirror_pattern
 };
 
@@ -1355,8 +1354,8 @@ int nand_default_bbt(struct mtd_info *mtd)
                /* Use the default pattern descriptors */
                if (!this->bbt_td) {
                        if (this->bbt_options & NAND_BBT_NO_OOB) {
-                               this->bbt_td = &bbt_main_no_bbt_descr;
-                               this->bbt_md = &bbt_mirror_no_bbt_descr;
+                               this->bbt_td = &bbt_main_no_oob_descr;
+                               this->bbt_md = &bbt_mirror_no_oob_descr;
                        } else {
                                this->bbt_td = &bbt_main_descr;
                                this->bbt_md = &bbt_mirror_descr;
@@ -1406,3 +1405,4 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 
 EXPORT_SYMBOL(nand_scan_bbt);
 EXPORT_SYMBOL(nand_default_bbt);
+EXPORT_SYMBOL_GPL(nand_update_bbt);
diff --git a/drivers/mtd/nand/nand_bcm_umi.c b/drivers/mtd/nand/nand_bcm_umi.c
deleted file mode 100644 (file)
index 46a6bc9..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*****************************************************************************
-* Copyright 2004 - 2009 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-/* ---- Include Files ---------------------------------------------------- */
-#include <mach/reg_umi.h>
-#include "nand_bcm_umi.h"
-#ifdef BOOT0_BUILD
-#include <uart.h>
-#endif
-
-/* ---- External Variable Declarations ----------------------------------- */
-/* ---- External Function Prototypes ------------------------------------- */
-/* ---- Public Variables ------------------------------------------------- */
-/* ---- Private Constants and Types -------------------------------------- */
-/* ---- Private Function Prototypes -------------------------------------- */
-/* ---- Private Variables ------------------------------------------------ */
-/* ---- Private Functions ------------------------------------------------ */
-
-#if NAND_ECC_BCH
-/****************************************************************************
-*  nand_bch_ecc_flip_bit - Routine to flip an errored bit
-*
-*  PURPOSE:
-*     This is a helper routine that flips the bit (0 -> 1 or 1 -> 0) of the
-*     errored bit specified
-*
-*  PARAMETERS:
-*     datap - Container that holds the 512 byte data
-*     errorLocation - Location of the bit that needs to be flipped
-*
-*  RETURNS:
-*     None
-****************************************************************************/
-static void nand_bcm_umi_bch_ecc_flip_bit(uint8_t *datap, int errorLocation)
-{
-       int locWithinAByte = (errorLocation & REG_UMI_BCH_ERR_LOC_BYTE) >> 0;
-       int locWithinAWord = (errorLocation & REG_UMI_BCH_ERR_LOC_WORD) >> 3;
-       int locWithinAPage = (errorLocation & REG_UMI_BCH_ERR_LOC_PAGE) >> 5;
-
-       uint8_t errorByte = 0;
-       uint8_t byteMask = 1 << locWithinAByte;
-
-       /* BCH uses big endian, need to change the location
-        * bits to little endian */
-       locWithinAWord = 3 - locWithinAWord;
-
-       errorByte = datap[locWithinAPage * sizeof(uint32_t) + locWithinAWord];
-
-#ifdef BOOT0_BUILD
-       puthexs("\nECC Correct Offset: ",
-               locWithinAPage * sizeof(uint32_t) + locWithinAWord);
-       puthexs(" errorByte:", errorByte);
-       puthex8(" Bit: ", locWithinAByte);
-#endif
-
-       if (errorByte & byteMask) {
-               /* bit needs to be cleared */
-               errorByte &= ~byteMask;
-       } else {
-               /* bit needs to be set */
-               errorByte |= byteMask;
-       }
-
-       /* write back the value with the fixed bit */
-       datap[locWithinAPage * sizeof(uint32_t) + locWithinAWord] = errorByte;
-}
-
-/****************************************************************************
-*  nand_correct_page_bch - Routine to correct bit errors when reading NAND
-*
-*  PURPOSE:
-*     This routine reads the BCH registers to determine if there are any bit
-*     errors during the read of the last 512 bytes of data + ECC bytes.  If
-*     errors exists, the routine fixes it.
-*
-*  PARAMETERS:
-*     datap - Container that holds the 512 byte data
-*
-*  RETURNS:
-*     0 or greater = Number of errors corrected
-*                    (No errors are found or errors have been fixed)
-*    -1 = Error(s) cannot be fixed
-****************************************************************************/
-int nand_bcm_umi_bch_correct_page(uint8_t *datap, uint8_t *readEccData,
-                                 int numEccBytes)
-{
-       int numErrors;
-       int errorLocation;
-       int idx;
-       uint32_t regValue;
-
-       /* wait for read ECC to be valid */
-       regValue = nand_bcm_umi_bch_poll_read_ecc_calc();
-
-       /*
-        * read the control status register to determine if there
-        * are error'ed bits
-        * see if errors are correctible
-        */
-       if ((regValue & REG_UMI_BCH_CTRL_STATUS_UNCORR_ERR) > 0) {
-               int i;
-
-               for (i = 0; i < numEccBytes; i++) {
-                       if (readEccData[i] != 0xff) {
-                               /* errors cannot be fixed, return -1 */
-                               return -1;
-                       }
-               }
-               /* If ECC is unprogrammed then we can't correct,
-                * assume everything OK */
-               return 0;
-       }
-
-       if ((regValue & REG_UMI_BCH_CTRL_STATUS_CORR_ERR) == 0) {
-               /* no errors */
-               return 0;
-       }
-
-       /*
-        * Fix errored bits by doing the following:
-        * 1. Read the number of errors in the control and status register
-        * 2. Read the error location registers that corresponds to the number
-        *    of errors reported
-        * 3. Invert the bit in the data
-        */
-       numErrors = (regValue & REG_UMI_BCH_CTRL_STATUS_NB_CORR_ERROR) >> 20;
-
-       for (idx = 0; idx < numErrors; idx++) {
-               errorLocation =
-                   REG_UMI_BCH_ERR_LOC_ADDR(idx) & REG_UMI_BCH_ERR_LOC_MASK;
-
-               /* Flip bit */
-               nand_bcm_umi_bch_ecc_flip_bit(datap, errorLocation);
-       }
-       /* Errors corrected */
-       return numErrors;
-}
-#endif
diff --git a/drivers/mtd/nand/nand_bcm_umi.h b/drivers/mtd/nand/nand_bcm_umi.h
deleted file mode 100644 (file)
index d901866..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-/*****************************************************************************
-* Copyright 2003 - 2009 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-#ifndef NAND_BCM_UMI_H
-#define NAND_BCM_UMI_H
-
-/* ---- Include Files ---------------------------------------------------- */
-#include <mach/reg_umi.h>
-#include <mach/reg_nand.h>
-#include <mach/cfg_global.h>
-
-/* ---- Constants and Types ---------------------------------------------- */
-#if (CFG_GLOBAL_CHIP_FAMILY == CFG_GLOBAL_CHIP_FAMILY_BCMRING)
-#define NAND_ECC_BCH (CFG_GLOBAL_CHIP_REV > 0xA0)
-#else
-#define NAND_ECC_BCH 0
-#endif
-
-#define CFG_GLOBAL_NAND_ECC_BCH_NUM_BYTES      13
-
-#if NAND_ECC_BCH
-#ifdef BOOT0_BUILD
-#define NAND_ECC_NUM_BYTES 13
-#else
-#define NAND_ECC_NUM_BYTES CFG_GLOBAL_NAND_ECC_BCH_NUM_BYTES
-#endif
-#else
-#define NAND_ECC_NUM_BYTES 3
-#endif
-
-#define NAND_DATA_ACCESS_SIZE 512
-
-/* ---- Variable Externs ------------------------------------------ */
-/* ---- Function Prototypes --------------------------------------- */
-int nand_bcm_umi_bch_correct_page(uint8_t *datap, uint8_t *readEccData,
-                                 int numEccBytes);
-
-/* Check in device is ready */
-static inline int nand_bcm_umi_dev_ready(void)
-{
-       return readl(&REG_UMI_NAND_RCSR) & REG_UMI_NAND_RCSR_RDY;
-}
-
-/* Wait until device is ready */
-static inline void nand_bcm_umi_wait_till_ready(void)
-{
-       while (nand_bcm_umi_dev_ready() == 0)
-               ;
-}
-
-/* Enable Hamming ECC */
-static inline void nand_bcm_umi_hamming_enable_hwecc(void)
-{
-       /* disable and reset ECC, 512 byte page */
-       writel(readl(&REG_UMI_NAND_ECC_CSR) & ~(REG_UMI_NAND_ECC_CSR_ECC_ENABLE |
-               REG_UMI_NAND_ECC_CSR_256BYTE), &REG_UMI_NAND_ECC_CSR);
-       /* enable ECC */
-       writel(readl(&REG_UMI_NAND_ECC_CSR) | REG_UMI_NAND_ECC_CSR_ECC_ENABLE,
-               &REG_UMI_NAND_ECC_CSR);
-}
-
-#if NAND_ECC_BCH
-/* BCH ECC specifics */
-#define ECC_BITS_PER_CORRECTABLE_BIT 13
-
-/* Enable BCH Read ECC */
-static inline void nand_bcm_umi_bch_enable_read_hwecc(void)
-{
-       /* disable and reset ECC */
-       writel(REG_UMI_BCH_CTRL_STATUS_RD_ECC_VALID, &REG_UMI_BCH_CTRL_STATUS);
-       /* Turn on ECC */
-       writel(REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN, &REG_UMI_BCH_CTRL_STATUS);
-}
-
-/* Enable BCH Write ECC */
-static inline void nand_bcm_umi_bch_enable_write_hwecc(void)
-{
-       /* disable and reset ECC */
-       writel(REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID, &REG_UMI_BCH_CTRL_STATUS);
-       /* Turn on ECC */
-       writel(REG_UMI_BCH_CTRL_STATUS_ECC_WR_EN, &REG_UMI_BCH_CTRL_STATUS);
-}
-
-/* Config number of BCH ECC bytes */
-static inline void nand_bcm_umi_bch_config_ecc(uint8_t numEccBytes)
-{
-       uint32_t nValue;
-       uint32_t tValue;
-       uint32_t kValue;
-       uint32_t numBits = numEccBytes * 8;
-
-       /* disable and reset ECC */
-       writel(REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID |
-              REG_UMI_BCH_CTRL_STATUS_RD_ECC_VALID,
-              &REG_UMI_BCH_CTRL_STATUS);
-
-       /* Every correctible bit requires 13 ECC bits */
-       tValue = (uint32_t) (numBits / ECC_BITS_PER_CORRECTABLE_BIT);
-
-       /* Total data in number of bits for generating and computing BCH ECC */
-       nValue = (NAND_DATA_ACCESS_SIZE + numEccBytes) * 8;
-
-       /* K parameter is used internally.  K = N - (T * 13) */
-       kValue = nValue - (tValue * ECC_BITS_PER_CORRECTABLE_BIT);
-
-       /* Write the settings */
-       writel(nValue, &REG_UMI_BCH_N);
-       writel(tValue, &REG_UMI_BCH_T);
-       writel(kValue, &REG_UMI_BCH_K);
-}
-
-/* Pause during ECC read calculation to skip bytes in OOB */
-static inline void nand_bcm_umi_bch_pause_read_ecc_calc(void)
-{
-       writel(REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN | REG_UMI_BCH_CTRL_STATUS_PAUSE_ECC_DEC, &REG_UMI_BCH_CTRL_STATUS);
-}
-
-/* Resume during ECC read calculation after skipping bytes in OOB */
-static inline void nand_bcm_umi_bch_resume_read_ecc_calc(void)
-{
-       writel(REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN, &REG_UMI_BCH_CTRL_STATUS);
-}
-
-/* Poll read ECC calc to check when hardware completes */
-static inline uint32_t nand_bcm_umi_bch_poll_read_ecc_calc(void)
-{
-       uint32_t regVal;
-
-       do {
-               /* wait for ECC to be valid */
-               regVal = readl(&REG_UMI_BCH_CTRL_STATUS);
-       } while ((regVal & REG_UMI_BCH_CTRL_STATUS_RD_ECC_VALID) == 0);
-
-       return regVal;
-}
-
-/* Poll write ECC calc to check when hardware completes */
-static inline void nand_bcm_umi_bch_poll_write_ecc_calc(void)
-{
-       /* wait for ECC to be valid */
-       while ((readl(&REG_UMI_BCH_CTRL_STATUS) & REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID)
-              == 0)
-               ;
-}
-
-/* Read the OOB and ECC, for kernel write OOB to a buffer */
-#if defined(__KERNEL__) && !defined(STANDALONE)
-static inline void nand_bcm_umi_bch_read_oobEcc(uint32_t pageSize,
-       uint8_t *eccCalc, int numEccBytes, uint8_t *oobp)
-#else
-static inline void nand_bcm_umi_bch_read_oobEcc(uint32_t pageSize,
-       uint8_t *eccCalc, int numEccBytes)
-#endif
-{
-       int eccPos = 0;
-       int numToRead = 16;     /* There are 16 bytes per sector in the OOB */
-
-       /* ECC is already paused when this function is called */
-       if (pageSize != NAND_DATA_ACCESS_SIZE) {
-               /* skip BI */
-#if defined(__KERNEL__) && !defined(STANDALONE)
-               *oobp++ = readb(&REG_NAND_DATA8);
-#else
-               readb(&REG_NAND_DATA8);
-#endif
-               numToRead--;
-       }
-
-       while (numToRead > numEccBytes) {
-               /* skip free oob region */
-#if defined(__KERNEL__) && !defined(STANDALONE)
-               *oobp++ = readb(&REG_NAND_DATA8);
-#else
-               readb(&REG_NAND_DATA8);
-#endif
-               numToRead--;
-       }
-
-       if (pageSize == NAND_DATA_ACCESS_SIZE) {
-               /* read ECC bytes before BI */
-               nand_bcm_umi_bch_resume_read_ecc_calc();
-
-               while (numToRead > 11) {
-#if defined(__KERNEL__) && !defined(STANDALONE)
-                       *oobp = readb(&REG_NAND_DATA8);
-                       eccCalc[eccPos++] = *oobp;
-                       oobp++;
-#else
-                       eccCalc[eccPos++] = readb(&REG_NAND_DATA8);
-#endif
-                       numToRead--;
-               }
-
-               nand_bcm_umi_bch_pause_read_ecc_calc();
-
-               if (numToRead == 11) {
-                       /* read BI */
-#if defined(__KERNEL__) && !defined(STANDALONE)
-                       *oobp++ = readb(&REG_NAND_DATA8);
-#else
-                       readb(&REG_NAND_DATA8);
-#endif
-                       numToRead--;
-               }
-
-       }
-       /* read ECC bytes */
-       nand_bcm_umi_bch_resume_read_ecc_calc();
-       while (numToRead) {
-#if defined(__KERNEL__) && !defined(STANDALONE)
-               *oobp = readb(&REG_NAND_DATA8);
-               eccCalc[eccPos++] = *oobp;
-               oobp++;
-#else
-               eccCalc[eccPos++] = readb(&REG_NAND_DATA8);
-#endif
-               numToRead--;
-       }
-}
-
-/* Helper function to write ECC */
-static inline void NAND_BCM_UMI_ECC_WRITE(int numEccBytes, int eccBytePos,
-                                         uint8_t *oobp, uint8_t eccVal)
-{
-       if (eccBytePos <= numEccBytes)
-               *oobp = eccVal;
-}
-
-/* Write OOB with ECC */
-static inline void nand_bcm_umi_bch_write_oobEcc(uint32_t pageSize,
-                                                uint8_t *oobp, int numEccBytes)
-{
-       uint32_t eccVal = 0xffffffff;
-
-       /* wait for write ECC to be valid */
-       nand_bcm_umi_bch_poll_write_ecc_calc();
-
-       /*
-        ** Get the hardware ecc from the 32-bit result registers.
-        ** Read after 512 byte accesses. Format B3B2B1B0
-        ** where B3 = ecc3, etc.
-        */
-
-       if (pageSize == NAND_DATA_ACCESS_SIZE) {
-               /* Now fill in the ECC bytes */
-               if (numEccBytes >= 13)
-                       eccVal = readl(&REG_UMI_BCH_WR_ECC_3);
-
-               /* Usually we skip CM in oob[0,1] */
-               NAND_BCM_UMI_ECC_WRITE(numEccBytes, 15, &oobp[0],
-                       (eccVal >> 16) & 0xff);
-               NAND_BCM_UMI_ECC_WRITE(numEccBytes, 14, &oobp[1],
-                       (eccVal >> 8) & 0xff);
-
-               /* Write ECC in oob[2,3,4] */
-               NAND_BCM_UMI_ECC_WRITE(numEccBytes, 13, &oobp[2],
-                       eccVal & 0xff); /* ECC 12 */
-
-               if (numEccBytes >= 9)
-                       eccVal = readl(&REG_UMI_BCH_WR_ECC_2);
-
-               NAND_BCM_UMI_ECC_WRITE(numEccBytes, 12, &oobp[3],
-                       (eccVal >> 24) & 0xff); /* ECC11 */
-               NAND_BCM_UMI_ECC_WRITE(numEccBytes, 11, &oobp[4],
-                       (eccVal >> 16) & 0xff); /* ECC10 */
-
-               /* Always Skip BI in oob[5] */
-       } else {
-               /* Always Skip BI in oob[0] */
-
-               /* Now fill in the ECC bytes */
-               if (numEccBytes >= 13)
-                       eccVal = readl(&REG_UMI_BCH_WR_ECC_3);
-
-               /* Usually skip CM in oob[1,2] */
-               NAND_BCM_UMI_ECC_WRITE(numEccBytes, 15, &oobp[1],
-                       (eccVal >> 16) & 0xff);
-               NAND_BCM_UMI_ECC_WRITE(numEccBytes, 14, &oobp[2],
-                       (eccVal >> 8) & 0xff);
-
-               /* Write ECC in oob[3-15] */
-               NAND_BCM_UMI_ECC_WRITE(numEccBytes, 13, &oobp[3],
-                       eccVal & 0xff); /* ECC12 */
-
-               if (numEccBytes >= 9)
-                       eccVal = readl(&REG_UMI_BCH_WR_ECC_2);
-
-               NAND_BCM_UMI_ECC_WRITE(numEccBytes, 12, &oobp[4],
-                       (eccVal >> 24) & 0xff); /* ECC11 */
-               NAND_BCM_UMI_ECC_WRITE(numEccBytes, 11, &oobp[5],
-                       (eccVal >> 16) & 0xff); /* ECC10 */
-       }
-
-       /* Fill in the remainder of ECC locations */
-       NAND_BCM_UMI_ECC_WRITE(numEccBytes, 10, &oobp[6],
-               (eccVal >> 8) & 0xff);  /* ECC9 */
-       NAND_BCM_UMI_ECC_WRITE(numEccBytes, 9, &oobp[7],
-               eccVal & 0xff); /* ECC8 */
-
-       if (numEccBytes >= 5)
-               eccVal = readl(&REG_UMI_BCH_WR_ECC_1);
-
-       NAND_BCM_UMI_ECC_WRITE(numEccBytes, 8, &oobp[8],
-               (eccVal >> 24) & 0xff); /* ECC7 */
-       NAND_BCM_UMI_ECC_WRITE(numEccBytes, 7, &oobp[9],
-               (eccVal >> 16) & 0xff); /* ECC6 */
-       NAND_BCM_UMI_ECC_WRITE(numEccBytes, 6, &oobp[10],
-               (eccVal >> 8) & 0xff);  /* ECC5 */
-       NAND_BCM_UMI_ECC_WRITE(numEccBytes, 5, &oobp[11],
-               eccVal & 0xff); /* ECC4 */
-
-       if (numEccBytes >= 1)
-               eccVal = readl(&REG_UMI_BCH_WR_ECC_0);
-
-       NAND_BCM_UMI_ECC_WRITE(numEccBytes, 4, &oobp[12],
-               (eccVal >> 24) & 0xff); /* ECC3 */
-       NAND_BCM_UMI_ECC_WRITE(numEccBytes, 3, &oobp[13],
-               (eccVal >> 16) & 0xff); /* ECC2 */
-       NAND_BCM_UMI_ECC_WRITE(numEccBytes, 2, &oobp[14],
-               (eccVal >> 8) & 0xff);  /* ECC1 */
-       NAND_BCM_UMI_ECC_WRITE(numEccBytes, 1, &oobp[15],
-               eccVal & 0xff); /* ECC0 */
-}
-#endif
-
-#endif /* NAND_BCM_UMI_H */
index 621b70b7a159099ffc3060bdf2651a38dc2dae43..e3aa2748a6e7af1cac818aaa170d5f6aff253056 100644 (file)
@@ -70,7 +70,7 @@ struct nand_flash_dev nand_flash_ids[] = {
         * These are the new chips with large page size. The pagesize and the
         * erasesize is determined from the extended id bytes
         */
-#define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY)
+#define LP_OPTIONS NAND_SAMSUNG_LP_OPTIONS
 #define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
 
        /* 512 Megabit */
@@ -157,7 +157,7 @@ struct nand_flash_dev nand_flash_ids[] = {
         * writes possible, but not implemented now
         */
        {"AND 128MiB 3,3V 8-bit",       0x01, 2048, 128, 0x4000,
-        NAND_IS_AND | NAND_NO_READRDY | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH},
+        NAND_IS_AND | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH},
 
        {NULL,}
 };
@@ -174,8 +174,9 @@ struct nand_manufacturers nand_manuf_ids[] = {
        {NAND_MFR_STMICRO, "ST Micro"},
        {NAND_MFR_HYNIX, "Hynix"},
        {NAND_MFR_MICRON, "Micron"},
-       {NAND_MFR_AMD, "AMD"},
+       {NAND_MFR_AMD, "AMD/Spansion"},
        {NAND_MFR_MACRONIX, "Macronix"},
+       {NAND_MFR_EON, "Eon"},
        {0x0, "Unknown"}
 };
 
index cf0cd3146817f9275706f1d4f61b53724d0d5dc1..a932c485eb04f9c7b40c14c924c7aa172be71244 100644 (file)
@@ -447,8 +447,6 @@ static unsigned int rptwear_cnt = 0;
 /* MTD structure for NAND controller */
 static struct mtd_info *nsmtd;
 
-static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE];
-
 /*
  * Allocate array of page pointers, create slab allocation for an array
  * and initialize the array by NULL pointers.
@@ -2189,19 +2187,6 @@ static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
        return;
 }
 
-static int ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
-{
-       ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len);
-
-       if (!memcmp(buf, &ns_verify_buf[0], len)) {
-               NS_DBG("verify_buf: the buffer is OK\n");
-               return 0;
-       } else {
-               NS_DBG("verify_buf: the buffer is wrong\n");
-               return -EFAULT;
-       }
-}
-
 /*
  * Module initialization function
  */
@@ -2236,7 +2221,6 @@ static int __init ns_init_module(void)
        chip->dev_ready  = ns_device_ready;
        chip->write_buf  = ns_nand_write_buf;
        chip->read_buf   = ns_nand_read_buf;
-       chip->verify_buf = ns_nand_verify_buf;
        chip->read_word  = ns_nand_read_word;
        chip->ecc.mode   = NAND_ECC_SOFT;
        /* The NAND_SKIP_BBTSCAN option is necessary for 'overridesize' */
@@ -2333,6 +2317,7 @@ static int __init ns_init_module(void)
                uint64_t new_size = (uint64_t)nsmtd->erasesize << overridesize;
                if (new_size >> overridesize != nsmtd->erasesize) {
                        NS_ERR("overridesize is too big\n");
+                       retval = -EINVAL;
                        goto err_exit;
                }
                /* N.B. This relies on nand_scan not doing anything with the size before we change it */
index 2b6f632cf27429ff691c7007a8a842689a8878d4..5fd3f010e3aef041a89471fd413d9603174d10c1 100644 (file)
@@ -140,18 +140,6 @@ static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
                out_be32(ndfc->ndfcbase + NDFC_DATA, *p++);
 }
 
-static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
-{
-       struct nand_chip *chip = mtd->priv;
-       struct ndfc_controller *ndfc = chip->priv;
-       uint32_t *p = (uint32_t *) buf;
-
-       for(;len > 0; len -= 4)
-               if (*p++ != in_be32(ndfc->ndfcbase + NDFC_DATA))
-                       return -EFAULT;
-       return 0;
-}
-
 /*
  * Initialize chip structure
  */
@@ -172,7 +160,6 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
        chip->controller = &ndfc->ndfc_control;
        chip->read_buf = ndfc_read_buf;
        chip->write_buf = ndfc_write_buf;
-       chip->verify_buf = ndfc_verify_buf;
        chip->ecc.correct = nand_correct_data;
        chip->ecc.hwctl = ndfc_enable_hwecc;
        chip->ecc.calculate = ndfc_calculate_ecc;
index 8febe46e1105e9aad7212dd442e4160d855fe11d..94dc46bc118cf7afac5608a9b3f2483b5719fd6c 100644 (file)
@@ -112,22 +112,6 @@ static void nuc900_nand_write_buf(struct mtd_info *mtd,
                write_data_reg(nand, buf[i]);
 }
 
-static int nuc900_verify_buf(struct mtd_info *mtd,
-                            const unsigned char *buf, int len)
-{
-       int i;
-       struct nuc900_nand *nand;
-
-       nand = container_of(mtd, struct nuc900_nand, mtd);
-
-       for (i = 0; i < len; i++) {
-               if (buf[i] != (unsigned char)read_data_reg(nand))
-                       return -EFAULT;
-       }
-
-       return 0;
-}
-
 static int nuc900_check_rb(struct nuc900_nand *nand)
 {
        unsigned int val;
@@ -292,7 +276,6 @@ static int __devinit nuc900_nand_probe(struct platform_device *pdev)
        chip->read_byte         = nuc900_nand_read_byte;
        chip->write_buf         = nuc900_nand_write_buf;
        chip->read_buf          = nuc900_nand_read_buf;
-       chip->verify_buf        = nuc900_verify_buf;
        chip->chip_delay        = 50;
        chip->options           = 0;
        chip->ecc.mode          = NAND_ECC_SOFT;
index fc8111278d12b11d77cee023c547123ab39e465f..5b3138620646af9b5b7c544529a3ae9250858745 100644 (file)
@@ -425,7 +425,7 @@ static void omap_nand_dma_callback(void *data)
 }
 
 /*
- * omap_nand_dma_transfer: configer and start dma transfer
+ * omap_nand_dma_transfer: configure and start dma transfer
  * @mtd: MTD device structure
  * @addr: virtual address in RAM of source/destination
  * @len: number of data bytes to be transferred
@@ -546,7 +546,7 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd,
 }
 
 /*
- * omap_nand_irq - GMPC irq handler
+ * omap_nand_irq - GPMC irq handler
  * @this_irq: gpmc irq number
  * @dev: omap_nand_info structure pointer is passed here
  */
@@ -697,27 +697,6 @@ out_copy:
                omap_write_buf8(mtd, buf, len);
 }
 
-/**
- * omap_verify_buf - Verify chip data against buffer
- * @mtd: MTD device structure
- * @buf: buffer containing the data to compare
- * @len: number of bytes to compare
- */
-static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
-{
-       struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
-                                                       mtd);
-       u16 *p = (u16 *) buf;
-
-       len >>= 1;
-       while (len--) {
-               if (*p++ != cpu_to_le16(readw(info->nand.IO_ADDR_R)))
-                       return -EFAULT;
-       }
-
-       return 0;
-}
-
 /**
  * gen_true_ecc - This function will generate true ECC value
  * @ecc_buf: buffer to store ecc code
@@ -1326,8 +1305,8 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 
        /*
         * If RDY/BSY line is connected to OMAP then use the omap ready
-        * funcrtion and the generic nand_wait function which reads the status
-        * register after monitoring the RDY/BSY line.Otherwise use a standard
+        * function and the generic nand_wait function which reads the status
+        * register after monitoring the RDY/BSY line. Otherwise use a standard
         * chip delay which is slightly more than tR (AC Timing) of the NAND
         * device and read status register until you get a failure or success
         */
@@ -1428,9 +1407,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
                goto out_release_mem_region;
        }
 
-       info->nand.verify_buf = omap_verify_buf;
-
-       /* selsect the ecc type */
+       /* select the ecc type */
        if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_DEFAULT)
                info->nand.ecc.mode = NAND_ECC_SOFT;
        else if ((pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW) ||
@@ -1536,7 +1513,8 @@ static int omap_nand_remove(struct platform_device *pdev)
        /* Release NAND device, its internal structures and partitions */
        nand_release(&info->mtd);
        iounmap(info->nand.IO_ADDR_R);
-       kfree(&info->mtd);
+       release_mem_region(info->phys_base, NAND_IO_SIZE);
+       kfree(info);
        return 0;
 }
 
index 131b58a133f148b2f70cdb711c708f529d84c87d..aefaf8cd31ef86f802e09273760fb47638067292 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/err.h>
 #include <asm/io.h>
 #include <asm/sizes.h>
-#include <mach/hardware.h>
 #include <linux/platform_data/mtd-orion_nand.h>
 
 static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
index 1bcb520404228ba2d8fe9cec1d29d9a6c535eac7..a47ee68a0cfac4467c4282f5981abb434b5ece09 100644 (file)
@@ -37,6 +37,11 @@ static int __devinit plat_nand_probe(struct platform_device *pdev)
        const char **part_types;
        int err = 0;
 
+       if (!pdata) {
+               dev_err(&pdev->dev, "platform_nand_data is missing\n");
+               return -EINVAL;
+       }
+
        if (pdata->chip.nr_chips < 1) {
                dev_err(&pdev->dev, "invalid number of chips specified\n");
                return -EINVAL;
index c45227173efd15dfb2cce4acce676318126830c1..37ee75c7bacb9d3200925a56a8caa9490c913dda 100644 (file)
@@ -683,11 +683,13 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
        info->state = STATE_IDLE;
 }
 
-static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
+static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
                struct nand_chip *chip, const uint8_t *buf, int oob_required)
 {
        chip->write_buf(mtd, buf, mtd->writesize);
        chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       return 0;
 }
 
 static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
@@ -771,12 +773,6 @@ static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
        info->buf_start += real_len;
 }
 
-static int pxa3xx_nand_verify_buf(struct mtd_info *mtd,
-               const uint8_t *buf, int len)
-{
-       return 0;
-}
-
 static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip)
 {
        return;
@@ -1007,7 +1003,6 @@ KEEP_CONFIG:
        chip->ecc.size = host->page_size;
        chip->ecc.strength = 1;
 
-       chip->options |= NAND_NO_READRDY;
        if (host->reg_ndcr & NDCR_DWIDTH_M)
                chip->options |= NAND_BUSWIDTH_16;
 
@@ -1070,7 +1065,6 @@ static int alloc_nand_resource(struct platform_device *pdev)
                chip->read_byte         = pxa3xx_nand_read_byte;
                chip->read_buf          = pxa3xx_nand_read_buf;
                chip->write_buf         = pxa3xx_nand_write_buf;
-               chip->verify_buf        = pxa3xx_nand_verify_buf;
        }
 
        spin_lock_init(&chip->controller->lock);
index 8cb627751c9c9658c5a3d6ac7c0a9cf1f78fb6af..4495f8551fa093fc6f30117475d624691e918430 100644 (file)
@@ -309,27 +309,6 @@ static uint8_t r852_read_byte(struct mtd_info *mtd)
        return r852_read_reg(dev, R852_DATALINE);
 }
 
-
-/*
- * Readback the buffer to verify it
- */
-int r852_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
-{
-       struct r852_device *dev = r852_get_dev(mtd);
-
-       /* We can't be sure about anything here... */
-       if (dev->card_unstable)
-               return -1;
-
-       /* This will never happen, unless you wired up a nand chip
-               with > 512 bytes page size to the reader */
-       if (len > SM_SECTOR_SIZE)
-               return 0;
-
-       r852_read_buf(mtd, dev->tmp_buffer, len);
-       return memcmp(buf, dev->tmp_buffer, len);
-}
-
 /*
  * Control several chip lines & send commands
  */
@@ -882,7 +861,6 @@ int  r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
        chip->read_byte = r852_read_byte;
        chip->read_buf = r852_read_buf;
        chip->write_buf = r852_write_buf;
-       chip->verify_buf = r852_verify_buf;
 
        /* ecc */
        chip->ecc.mode = NAND_ECC_HW_SYNDROME;
index d8040619ad8dfca48fc460305b782cc771a06008..295e4bedad960a0efe653dc893fe0f1e0270f2f1 100644 (file)
@@ -21,6 +21,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
+#define pr_fmt(fmt) "nand-s3c2410: " fmt
+
 #ifdef CONFIG_MTD_NAND_S3C2410_DEBUG
 #define DEBUG
 #endif
@@ -30,6 +32,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
+#include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
-#include <asm/io.h>
-
 #include <plat/regs-nand.h>
 #include <linux/platform_data/mtd-nand-s3c2410.h>
 
-#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
-static int hardware_ecc = 1;
-#else
-static int hardware_ecc = 0;
-#endif
-
-#ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
-static const int clock_stop = 1;
-#else
-static const int clock_stop = 0;
-#endif
-
-
 /* new oob placement block for use with hardware ecc generation
  */
 
@@ -109,9 +97,8 @@ enum s3c_nand_clk_state {
  * @mtds: An array of MTD instances on this controoler.
  * @platform: The platform data for this board.
  * @device: The platform device we bound to.
- * @area: The IO area resource that came from request_mem_region().
  * @clk: The clock resource for this controller.
- * @regs: The area mapped for the hardware registers described by @area.
+ * @regs: The area mapped for the hardware registers.
  * @sel_reg: Pointer to the register controlling the NAND selection.
  * @sel_bit: The bit in @sel_reg to select the NAND chip.
  * @mtd_count: The number of MTDs created from this controller.
@@ -128,7 +115,6 @@ struct s3c2410_nand_info {
 
        /* device info */
        struct device                   *device;
-       struct resource                 *area;
        struct clk                      *clk;
        void __iomem                    *regs;
        void __iomem                    *sel_reg;
@@ -169,7 +155,11 @@ static struct s3c2410_platform_nand *to_nand_plat(struct platform_device *dev)
 
 static inline int allow_clk_suspend(struct s3c2410_nand_info *info)
 {
-       return clock_stop;
+#ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
+       return 1;
+#else
+       return 0;
+#endif
 }
 
 /**
@@ -215,7 +205,8 @@ static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
        pr_debug("result %d from %ld, %d\n", result, clk, wanted);
 
        if (result > max) {
-               printk("%d ns is too big for current clock rate %ld\n", wanted, clk);
+               pr_err("%d ns is too big for current clock rate %ld\n",
+                       wanted, clk);
                return -1;
        }
 
@@ -225,7 +216,7 @@ static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
        return result;
 }
 
-#define to_ns(ticks,clk) (((ticks) * NS_IN_KHZ) / (unsigned int)(clk))
+#define to_ns(ticks, clk) (((ticks) * NS_IN_KHZ) / (unsigned int)(clk))
 
 /* controller setup */
 
@@ -268,7 +259,8 @@ static int s3c2410_nand_setrate(struct s3c2410_nand_info *info)
        }
 
        dev_info(info->device, "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n",
-              tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate));
+               tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate),
+                                               twrph1, to_ns(twrph1, clkrate));
 
        switch (info->cpu_type) {
        case TYPE_S3C2410:
@@ -325,13 +317,13 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info)
        if (ret < 0)
                return ret;
 
-       switch (info->cpu_type) {
-       case TYPE_S3C2410:
+       switch (info->cpu_type) {
+       case TYPE_S3C2410:
        default:
                break;
 
-       case TYPE_S3C2440:
-       case TYPE_S3C2412:
+       case TYPE_S3C2440:
+       case TYPE_S3C2412:
                /* enable the controller and de-assert nFCE */
 
                writel(S3C2440_NFCONT_ENABLE, info->regs + S3C2440_NFCONT);
@@ -450,6 +442,7 @@ static int s3c2412_nand_devready(struct mtd_info *mtd)
 
 /* ECC handling functions */
 
+#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
 static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
                                     u_char *read_ecc, u_char *calc_ecc)
 {
@@ -463,10 +456,8 @@ static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
        diff1 = read_ecc[1] ^ calc_ecc[1];
        diff2 = read_ecc[2] ^ calc_ecc[2];
 
-       pr_debug("%s: rd %02x%02x%02x calc %02x%02x%02x diff %02x%02x%02x\n",
-                __func__,
-                read_ecc[0], read_ecc[1], read_ecc[2],
-                calc_ecc[0], calc_ecc[1], calc_ecc[2],
+       pr_debug("%s: rd %*phN calc %*phN diff %02x%02x%02x\n",
+                __func__, 3, read_ecc, 3, calc_ecc,
                 diff0, diff1, diff2);
 
        if (diff0 == 0 && diff1 == 0 && diff2 == 0)
@@ -546,7 +537,8 @@ static void s3c2412_nand_enable_hwecc(struct mtd_info *mtd, int mode)
        unsigned long ctrl;
 
        ctrl = readl(info->regs + S3C2440_NFCONT);
-       writel(ctrl | S3C2412_NFCONT_INIT_MAIN_ECC, info->regs + S3C2440_NFCONT);
+       writel(ctrl | S3C2412_NFCONT_INIT_MAIN_ECC,
+              info->regs + S3C2440_NFCONT);
 }
 
 static void s3c2440_nand_enable_hwecc(struct mtd_info *mtd, int mode)
@@ -558,7 +550,8 @@ static void s3c2440_nand_enable_hwecc(struct mtd_info *mtd, int mode)
        writel(ctrl | S3C2440_NFCONT_INITECC, info->regs + S3C2440_NFCONT);
 }
 
-static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
+static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+                                     u_char *ecc_code)
 {
        struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 
@@ -566,13 +559,13 @@ static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
        ecc_code[1] = readb(info->regs + S3C2410_NFECC + 1);
        ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2);
 
-       pr_debug("%s: returning ecc %02x%02x%02x\n", __func__,
-                ecc_code[0], ecc_code[1], ecc_code[2]);
+       pr_debug("%s: returning ecc %*phN\n", __func__, 3, ecc_code);
 
        return 0;
 }
 
-static int s3c2412_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
+static int s3c2412_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+                                     u_char *ecc_code)
 {
        struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
        unsigned long ecc = readl(info->regs + S3C2412_NFMECC0);
@@ -581,12 +574,13 @@ static int s3c2412_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
        ecc_code[1] = ecc >> 8;
        ecc_code[2] = ecc >> 16;
 
-       pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
+       pr_debug("%s: returning ecc %*phN\n", __func__, 3, ecc_code);
 
        return 0;
 }
 
-static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
+static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+                                     u_char *ecc_code)
 {
        struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
        unsigned long ecc = readl(info->regs + S3C2440_NFMECC0);
@@ -599,6 +593,7 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
 
        return 0;
 }
+#endif
 
 /* over-ride the standard functions for a little more speed. We can
  * use read/write block to move the data buffers to/from the controller
@@ -625,13 +620,15 @@ static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
        }
 }
 
-static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf,
+                                  int len)
 {
        struct nand_chip *this = mtd->priv;
        writesb(this->IO_ADDR_W, buf, len);
 }
 
-static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf,
+                                  int len)
 {
        struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 
@@ -675,7 +672,8 @@ static inline int s3c2410_nand_cpufreq_register(struct s3c2410_nand_info *info)
                                         CPUFREQ_TRANSITION_NOTIFIER);
 }
 
-static inline void s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
+static inline void
+s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
 {
        cpufreq_unregister_notifier(&info->freq_transition,
                                    CPUFREQ_TRANSITION_NOTIFIER);
@@ -687,7 +685,8 @@ static inline int s3c2410_nand_cpufreq_register(struct s3c2410_nand_info *info)
        return 0;
 }
 
-static inline void s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
+static inline void
+s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
 {
 }
 #endif
@@ -717,29 +716,12 @@ static int s3c24xx_nand_remove(struct platform_device *pdev)
                        pr_debug("releasing mtd %d (%p)\n", mtdno, ptr);
                        nand_release(&ptr->mtd);
                }
-
-               kfree(info->mtds);
        }
 
        /* free the common resources */
 
-       if (!IS_ERR(info->clk)) {
+       if (!IS_ERR(info->clk))
                s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
-               clk_put(info->clk);
-       }
-
-       if (info->regs != NULL) {
-               iounmap(info->regs);
-               info->regs = NULL;
-       }
-
-       if (info->area != NULL) {
-               release_resource(info->area);
-               kfree(info->area);
-               info->area = NULL;
-       }
-
-       kfree(info);
 
        return 0;
 }
@@ -810,7 +792,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
                        dev_info(info->device, "System booted from NAND\n");
 
                break;
-       }
+       }
 
        chip->IO_ADDR_R = chip->IO_ADDR_W;
 
@@ -819,32 +801,31 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
        nmtd->mtd.owner    = THIS_MODULE;
        nmtd->set          = set;
 
-       if (hardware_ecc) {
+#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
+       chip->ecc.calculate = s3c2410_nand_calculate_ecc;
+       chip->ecc.correct   = s3c2410_nand_correct_data;
+       chip->ecc.mode      = NAND_ECC_HW;
+       chip->ecc.strength  = 1;
+
+       switch (info->cpu_type) {
+       case TYPE_S3C2410:
+               chip->ecc.hwctl     = s3c2410_nand_enable_hwecc;
                chip->ecc.calculate = s3c2410_nand_calculate_ecc;
-               chip->ecc.correct   = s3c2410_nand_correct_data;
-               chip->ecc.mode      = NAND_ECC_HW;
-               chip->ecc.strength  = 1;
-
-               switch (info->cpu_type) {
-               case TYPE_S3C2410:
-                       chip->ecc.hwctl     = s3c2410_nand_enable_hwecc;
-                       chip->ecc.calculate = s3c2410_nand_calculate_ecc;
-                       break;
-
-               case TYPE_S3C2412:
-                       chip->ecc.hwctl     = s3c2412_nand_enable_hwecc;
-                       chip->ecc.calculate = s3c2412_nand_calculate_ecc;
-                       break;
-
-               case TYPE_S3C2440:
-                       chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
-                       chip->ecc.calculate = s3c2440_nand_calculate_ecc;
-                       break;
+               break;
 
-               }
-       } else {
-               chip->ecc.mode      = NAND_ECC_SOFT;
+       case TYPE_S3C2412:
+               chip->ecc.hwctl     = s3c2412_nand_enable_hwecc;
+               chip->ecc.calculate = s3c2412_nand_calculate_ecc;
+               break;
+
+       case TYPE_S3C2440:
+               chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
+               chip->ecc.calculate = s3c2440_nand_calculate_ecc;
+               break;
        }
+#else
+       chip->ecc.mode      = NAND_ECC_SOFT;
+#endif
 
        if (set->ecc_layout != NULL)
                chip->ecc.layout = set->ecc_layout;
@@ -921,7 +902,7 @@ static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
 static int s3c24xx_nand_probe(struct platform_device *pdev)
 {
        struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
-       enum s3c_cpu_type cpu_type; 
+       enum s3c_cpu_type cpu_type;
        struct s3c2410_nand_info *info;
        struct s3c2410_nand_mtd *nmtd;
        struct s3c2410_nand_set *sets;
@@ -935,7 +916,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 
        pr_debug("s3c2410_nand_probe(%p)\n", pdev);
 
-       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
        if (info == NULL) {
                dev_err(&pdev->dev, "no memory for flash info\n");
                err = -ENOMEM;
@@ -949,7 +930,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 
        /* get the clock source and enable it */
 
-       info->clk = clk_get(&pdev->dev, "nand");
+       info->clk = devm_clk_get(&pdev->dev, "nand");
        if (IS_ERR(info->clk)) {
                dev_err(&pdev->dev, "failed to get clock\n");
                err = -ENOENT;
@@ -961,22 +942,14 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
        /* allocate and map the resource */
 
        /* currently we assume we have the one resource */
-       res  = pdev->resource;
+       res = pdev->resource;
        size = resource_size(res);
 
-       info->area = request_mem_region(res->start, size, pdev->name);
-
-       if (info->area == NULL) {
-               dev_err(&pdev->dev, "cannot reserve register region\n");
-               err = -ENOENT;
-               goto exit_error;
-       }
-
-       info->device     = &pdev->dev;
-       info->platform   = plat;
-       info->regs       = ioremap(res->start, size);
-       info->cpu_type   = cpu_type;
+       info->device    = &pdev->dev;
+       info->platform  = plat;
+       info->cpu_type  = cpu_type;
 
+       info->regs      = devm_request_and_ioremap(&pdev->dev, res);
        if (info->regs == NULL) {
                dev_err(&pdev->dev, "cannot reserve register region\n");
                err = -EIO;
@@ -999,7 +972,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
        /* allocate our information */
 
        size = nr_sets * sizeof(*info->mtds);
-       info->mtds = kzalloc(size, GFP_KERNEL);
+       info->mtds = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
        if (info->mtds == NULL) {
                dev_err(&pdev->dev, "failed to allocate mtd storage\n");
                err = -ENOMEM;
@@ -1011,7 +984,8 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
        nmtd = info->mtds;
 
        for (setno = 0; setno < nr_sets; setno++, nmtd++) {
-               pr_debug("initialising set %d (%p, info %p)\n", setno, nmtd, info);
+               pr_debug("initialising set %d (%p, info %p)\n",
+                        setno, nmtd, info);
 
                s3c2410_nand_init_chip(info, nmtd, sets);
 
@@ -1134,20 +1108,7 @@ static struct platform_driver s3c24xx_nand_driver = {
        },
 };
 
-static int __init s3c2410_nand_init(void)
-{
-       printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics\n");
-
-       return platform_driver_register(&s3c24xx_nand_driver);
-}
-
-static void __exit s3c2410_nand_exit(void)
-{
-       platform_driver_unregister(&s3c24xx_nand_driver);
-}
-
-module_init(s3c2410_nand_init);
-module_exit(s3c2410_nand_exit);
+module_platform_driver(s3c24xx_nand_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
index aa9b8a5e0b8f94b66f6356b4346000feeea0e6d8..4fbfe96e37a1f93dd58dd2b9dae063e8568cb0a9 100644 (file)
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -43,11 +45,17 @@ static struct nand_ecclayout flctl_4secc_oob_16 = {
 };
 
 static struct nand_ecclayout flctl_4secc_oob_64 = {
-       .eccbytes = 10,
-       .eccpos = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57},
+       .eccbytes = 4 * 10,
+       .eccpos = {
+                6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+               22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+               38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+               54, 55, 56, 57, 58, 59, 60, 61, 62, 63 },
        .oobfree = {
-               {.offset = 60,
-               . length = 4} },
+               {.offset =  2, .length = 4},
+               {.offset = 16, .length = 6},
+               {.offset = 32, .length = 6},
+               {.offset = 48, .length = 6} },
 };
 
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
@@ -61,15 +69,15 @@ static struct nand_bbt_descr flctl_4secc_smallpage = {
 
 static struct nand_bbt_descr flctl_4secc_largepage = {
        .options = NAND_BBT_SCAN2NDPAGE,
-       .offs = 58,
+       .offs = 0,
        .len = 2,
        .pattern = scan_ff_pattern,
 };
 
 static void empty_fifo(struct sh_flctl *flctl)
 {
-       writel(0x000c0000, FLINTDMACR(flctl));  /* FIFO Clear */
-       writel(0x00000000, FLINTDMACR(flctl));  /* Clear Error flags */
+       writel(flctl->flintdmacr_base | AC1CLR | AC0CLR, FLINTDMACR(flctl));
+       writel(flctl->flintdmacr_base, FLINTDMACR(flctl));
 }
 
 static void start_translation(struct sh_flctl *flctl)
@@ -158,27 +166,56 @@ static void wait_wfifo_ready(struct sh_flctl *flctl)
        timeout_error(flctl, __func__);
 }
 
-static int wait_recfifo_ready(struct sh_flctl *flctl, int sector_number)
+static enum flctl_ecc_res_t wait_recfifo_ready
+               (struct sh_flctl *flctl, int sector_number)
 {
        uint32_t timeout = LOOP_TIMEOUT_MAX;
-       int checked[4];
        void __iomem *ecc_reg[4];
        int i;
+       int state = FL_SUCCESS;
        uint32_t data, size;
 
-       memset(checked, 0, sizeof(checked));
-
+       /*
+        * First this loops checks in FLDTCNTR if we are ready to read out the
+        * oob data. This is the case if either all went fine without errors or
+        * if the bottom part of the loop corrected the errors or marked them as
+        * uncorrectable and the controller is given time to push the data into
+        * the FIFO.
+        */
        while (timeout--) {
+               /* check if all is ok and we can read out the OOB */
                size = readl(FLDTCNTR(flctl)) >> 24;
-               if (size & 0xFF)
-                       return 0;       /* success */
+               if ((size & 0xFF) == 4)
+                       return state;
+
+               /* check if a correction code has been calculated */
+               if (!(readl(FL4ECCCR(flctl)) & _4ECCEND)) {
+                       /*
+                        * either we wait for the fifo to be filled or a
+                        * correction pattern is being generated
+                        */
+                       udelay(1);
+                       continue;
+               }
 
-               if (readl(FL4ECCCR(flctl)) & _4ECCFA)
-                       return 1;       /* can't correct */
+               /* check for an uncorrectable error */
+               if (readl(FL4ECCCR(flctl)) & _4ECCFA) {
+                       /* check if we face a non-empty page */
+                       for (i = 0; i < 512; i++) {
+                               if (flctl->done_buff[i] != 0xff) {
+                                       state = FL_ERROR; /* can't correct */
+                                       break;
+                               }
+                       }
 
-               udelay(1);
-               if (!(readl(FL4ECCCR(flctl)) & _4ECCEND))
+                       if (state == FL_SUCCESS)
+                               dev_dbg(&flctl->pdev->dev,
+                               "reading empty sector %d, ecc error ignored\n",
+                               sector_number);
+
+                       writel(0, FL4ECCCR(flctl));
                        continue;
+               }
 
                /* start error correction */
                ecc_reg[0] = FL4ECCRESULT0(flctl);
@@ -187,28 +224,26 @@ static int wait_recfifo_ready(struct sh_flctl *flctl, int sector_number)
                ecc_reg[3] = FL4ECCRESULT3(flctl);
 
                for (i = 0; i < 3; i++) {
+                       uint8_t org;
+                       int index;
+
                        data = readl(ecc_reg[i]);
-                       if (data != INIT_FL4ECCRESULT_VAL && !checked[i]) {
-                               uint8_t org;
-                               int index;
-
-                               if (flctl->page_size)
-                                       index = (512 * sector_number) +
-                                               (data >> 16);
-                               else
-                                       index = data >> 16;
-
-                               org = flctl->done_buff[index];
-                               flctl->done_buff[index] = org ^ (data & 0xFF);
-                               checked[i] = 1;
-                       }
-               }
 
+                       if (flctl->page_size)
+                               index = (512 * sector_number) +
+                                       (data >> 16);
+                       else
+                               index = data >> 16;
+
+                       org = flctl->done_buff[index];
+                       flctl->done_buff[index] = org ^ (data & 0xFF);
+               }
+               state = FL_REPAIRABLE;
                writel(0, FL4ECCCR(flctl));
        }
 
        timeout_error(flctl, __func__);
-       return 1;       /* timeout */
+       return FL_TIMEOUT;      /* timeout */
 }
 
 static void wait_wecfifo_ready(struct sh_flctl *flctl)
@@ -241,31 +276,33 @@ static void read_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
 {
        int i, len_4align;
        unsigned long *buf = (unsigned long *)&flctl->done_buff[offset];
-       void *fifo_addr = (void *)FLDTFIFO(flctl);
 
        len_4align = (rlen + 3) / 4;
 
        for (i = 0; i < len_4align; i++) {
                wait_rfifo_ready(flctl);
-               buf[i] = readl(fifo_addr);
+               buf[i] = readl(FLDTFIFO(flctl));
                buf[i] = be32_to_cpu(buf[i]);
        }
 }
 
-static int read_ecfiforeg(struct sh_flctl *flctl, uint8_t *buff, int sector)
+static enum flctl_ecc_res_t read_ecfiforeg
+               (struct sh_flctl *flctl, uint8_t *buff, int sector)
 {
        int i;
+       enum flctl_ecc_res_t res;
        unsigned long *ecc_buf = (unsigned long *)buff;
-       void *fifo_addr = (void *)FLECFIFO(flctl);
 
-       for (i = 0; i < 4; i++) {
-               if (wait_recfifo_ready(flctl , sector))
-                       return 1;
-               ecc_buf[i] = readl(fifo_addr);
-               ecc_buf[i] = be32_to_cpu(ecc_buf[i]);
+       res = wait_recfifo_ready(flctl , sector);
+
+       if (res != FL_ERROR) {
+               for (i = 0; i < 4; i++) {
+                       ecc_buf[i] = readl(FLECFIFO(flctl));
+                       ecc_buf[i] = be32_to_cpu(ecc_buf[i]);
+               }
        }
 
-       return 0;
+       return res;
 }
 
 static void write_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
@@ -281,6 +318,18 @@ static void write_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
        }
 }
 
+static void write_ec_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
+{
+       int i, len_4align;
+       unsigned long *data = (unsigned long *)&flctl->done_buff[offset];
+
+       len_4align = (rlen + 3) / 4;
+       for (i = 0; i < len_4align; i++) {
+               wait_wecfifo_ready(flctl);
+               writel(cpu_to_be32(data[i]), FLECFIFO(flctl));
+       }
+}
+
 static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_val)
 {
        struct sh_flctl *flctl = mtd_to_flctl(mtd);
@@ -346,73 +395,65 @@ static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_va
 static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
                                uint8_t *buf, int oob_required, int page)
 {
-       int i, eccsize = chip->ecc.size;
-       int eccbytes = chip->ecc.bytes;
-       int eccsteps = chip->ecc.steps;
-       uint8_t *p = buf;
-       struct sh_flctl *flctl = mtd_to_flctl(mtd);
-
-       for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
-               chip->read_buf(mtd, p, eccsize);
-
-       for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
-               if (flctl->hwecc_cant_correct[i])
-                       mtd->ecc_stats.failed++;
-               else
-                       mtd->ecc_stats.corrected += 0; /* FIXME */
-       }
-
+       chip->read_buf(mtd, buf, mtd->writesize);
+       if (oob_required)
+               chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
        return 0;
 }
 
-static void flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
+static int flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
                                   const uint8_t *buf, int oob_required)
 {
-       int i, eccsize = chip->ecc.size;
-       int eccbytes = chip->ecc.bytes;
-       int eccsteps = chip->ecc.steps;
-       const uint8_t *p = buf;
-
-       for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
-               chip->write_buf(mtd, p, eccsize);
+       chip->write_buf(mtd, buf, mtd->writesize);
+       chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+       return 0;
 }
 
 static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr)
 {
        struct sh_flctl *flctl = mtd_to_flctl(mtd);
        int sector, page_sectors;
+       enum flctl_ecc_res_t ecc_result;
 
-       if (flctl->page_size)
-               page_sectors = 4;
-       else
-               page_sectors = 1;
-
-       writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE | _4ECCCORRECT,
-                FLCMNCR(flctl));
+       page_sectors = flctl->page_size ? 4 : 1;
 
        set_cmd_regs(mtd, NAND_CMD_READ0,
                (NAND_CMD_READSTART << 8) | NAND_CMD_READ0);
 
-       for (sector = 0; sector < page_sectors; sector++) {
-               int ret;
+       writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE | _4ECCCORRECT,
+                FLCMNCR(flctl));
+       writel(readl(FLCMDCR(flctl)) | page_sectors, FLCMDCR(flctl));
+       writel(page_addr << 2, FLADR(flctl));
 
-               empty_fifo(flctl);
-               writel(readl(FLCMDCR(flctl)) | 1, FLCMDCR(flctl));
-               writel(page_addr << 2 | sector, FLADR(flctl));
+       empty_fifo(flctl);
+       start_translation(flctl);
 
-               start_translation(flctl);
+       for (sector = 0; sector < page_sectors; sector++) {
                read_fiforeg(flctl, 512, 512 * sector);
 
-               ret = read_ecfiforeg(flctl,
+               ecc_result = read_ecfiforeg(flctl,
                        &flctl->done_buff[mtd->writesize + 16 * sector],
                        sector);
 
-               if (ret)
-                       flctl->hwecc_cant_correct[sector] = 1;
-
-               writel(0x0, FL4ECCCR(flctl));
-               wait_completion(flctl);
+               switch (ecc_result) {
+               case FL_REPAIRABLE:
+                       dev_info(&flctl->pdev->dev,
+                               "applied ecc on page 0x%x", page_addr);
+                       flctl->mtd.ecc_stats.corrected++;
+                       break;
+               case FL_ERROR:
+                       dev_warn(&flctl->pdev->dev,
+                               "page 0x%x contains corrupted data\n",
+                               page_addr);
+                       flctl->mtd.ecc_stats.failed++;
+                       break;
+               default:
+                       ;
+               }
        }
+
+       wait_completion(flctl);
+
        writel(readl(FLCMNCR(flctl)) & ~(ACM_SACCES_MODE | _4ECCCORRECT),
                        FLCMNCR(flctl));
 }
@@ -420,30 +461,20 @@ static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr)
 static void execmd_read_oob(struct mtd_info *mtd, int page_addr)
 {
        struct sh_flctl *flctl = mtd_to_flctl(mtd);
+       int page_sectors = flctl->page_size ? 4 : 1;
+       int i;
 
        set_cmd_regs(mtd, NAND_CMD_READ0,
                (NAND_CMD_READSTART << 8) | NAND_CMD_READ0);
 
        empty_fifo(flctl);
-       if (flctl->page_size) {
-               int i;
-               /* In case that the page size is 2k */
-               for (i = 0; i < 16 * 3; i++)
-                       flctl->done_buff[i] = 0xFF;
-
-               set_addr(mtd, 3 * 528 + 512, page_addr);
-               writel(16, FLDTCNTR(flctl));
 
-               start_translation(flctl);
-               read_fiforeg(flctl, 16, 16 * 3);
-               wait_completion(flctl);
-       } else {
-               /* In case that the page size is 512b */
-               set_addr(mtd, 512, page_addr);
+       for (i = 0; i < page_sectors; i++) {
+               set_addr(mtd, (512 + 16) * i + 512 , page_addr);
                writel(16, FLDTCNTR(flctl));
 
                start_translation(flctl);
-               read_fiforeg(flctl, 16, 0);
+               read_fiforeg(flctl, 16, 16 * i);
                wait_completion(flctl);
        }
 }
@@ -451,34 +482,26 @@ static void execmd_read_oob(struct mtd_info *mtd, int page_addr)
 static void execmd_write_page_sector(struct mtd_info *mtd)
 {
        struct sh_flctl *flctl = mtd_to_flctl(mtd);
-       int i, page_addr = flctl->seqin_page_addr;
+       int page_addr = flctl->seqin_page_addr;
        int sector, page_sectors;
 
-       if (flctl->page_size)
-               page_sectors = 4;
-       else
-               page_sectors = 1;
-
-       writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE, FLCMNCR(flctl));
+       page_sectors = flctl->page_size ? 4 : 1;
 
        set_cmd_regs(mtd, NAND_CMD_PAGEPROG,
                        (NAND_CMD_PAGEPROG << 8) | NAND_CMD_SEQIN);
 
-       for (sector = 0; sector < page_sectors; sector++) {
-               empty_fifo(flctl);
-               writel(readl(FLCMDCR(flctl)) | 1, FLCMDCR(flctl));
-               writel(page_addr << 2 | sector, FLADR(flctl));
+       empty_fifo(flctl);
+       writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE, FLCMNCR(flctl));
+       writel(readl(FLCMDCR(flctl)) | page_sectors, FLCMDCR(flctl));
+       writel(page_addr << 2, FLADR(flctl));
+       start_translation(flctl);
 
-               start_translation(flctl);
+       for (sector = 0; sector < page_sectors; sector++) {
                write_fiforeg(flctl, 512, 512 * sector);
-
-               for (i = 0; i < 4; i++) {
-                       wait_wecfifo_ready(flctl); /* wait for write ready */
-                       writel(0xFFFFFFFF, FLECFIFO(flctl));
-               }
-               wait_completion(flctl);
+               write_ec_fiforeg(flctl, 16, mtd->writesize + 16 * sector);
        }
 
+       wait_completion(flctl);
        writel(readl(FLCMNCR(flctl)) & ~ACM_SACCES_MODE, FLCMNCR(flctl));
 }
 
@@ -488,18 +511,12 @@ static void execmd_write_oob(struct mtd_info *mtd)
        int page_addr = flctl->seqin_page_addr;
        int sector, page_sectors;
 
-       if (flctl->page_size) {
-               sector = 3;
-               page_sectors = 4;
-       } else {
-               sector = 0;
-               page_sectors = 1;
-       }
+       page_sectors = flctl->page_size ? 4 : 1;
 
        set_cmd_regs(mtd, NAND_CMD_PAGEPROG,
                        (NAND_CMD_PAGEPROG << 8) | NAND_CMD_SEQIN);
 
-       for (; sector < page_sectors; sector++) {
+       for (sector = 0; sector < page_sectors; sector++) {
                empty_fifo(flctl);
                set_addr(mtd, sector * 528 + 512, page_addr);
                writel(16, FLDTCNTR(flctl));    /* set read size */
@@ -731,10 +748,9 @@ static void flctl_select_chip(struct mtd_info *mtd, int chipnr)
 static void flctl_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
        struct sh_flctl *flctl = mtd_to_flctl(mtd);
-       int i, index = flctl->index;
+       int index = flctl->index;
 
-       for (i = 0; i < len; i++)
-               flctl->done_buff[index + i] = buf[i];
+       memcpy(&flctl->done_buff[index], buf, len);
        flctl->index += len;
 }
 
@@ -763,20 +779,11 @@ static uint16_t flctl_read_word(struct mtd_info *mtd)
 
 static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-       int i;
-
-       for (i = 0; i < len; i++)
-               buf[i] = flctl_read_byte(mtd);
-}
-
-static int flctl_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
-{
-       int i;
+       struct sh_flctl *flctl = mtd_to_flctl(mtd);
+       int index = flctl->index;
 
-       for (i = 0; i < len; i++)
-               if (buf[i] != flctl_read_byte(mtd))
-                       return -EFAULT;
-       return 0;
+       memcpy(buf, &flctl->done_buff[index], len);
+       flctl->index += len;
 }
 
 static int flctl_chip_init_tail(struct mtd_info *mtd)
@@ -831,7 +838,7 @@ static int flctl_chip_init_tail(struct mtd_info *mtd)
                chip->ecc.mode = NAND_ECC_HW;
 
                /* 4 symbols ECC enabled */
-               flctl->flcmncr_base |= _4ECCEN | ECCPOS2 | ECCPOS_02;
+               flctl->flcmncr_base |= _4ECCEN;
        } else {
                chip->ecc.mode = NAND_ECC_SOFT;
        }
@@ -839,6 +846,16 @@ static int flctl_chip_init_tail(struct mtd_info *mtd)
        return 0;
 }
 
+static irqreturn_t flctl_handle_flste(int irq, void *dev_id)
+{
+       struct sh_flctl *flctl = dev_id;
+
+       dev_err(&flctl->pdev->dev, "flste irq: %x\n", readl(FLINTDMACR(flctl)));
+       writel(flctl->flintdmacr_base, FLINTDMACR(flctl));
+
+       return IRQ_HANDLED;
+}
+
 static int __devinit flctl_probe(struct platform_device *pdev)
 {
        struct resource *res;
@@ -847,6 +864,7 @@ static int __devinit flctl_probe(struct platform_device *pdev)
        struct nand_chip *nand;
        struct sh_flctl_platform_data *pdata;
        int ret = -ENXIO;
+       int irq;
 
        pdata = pdev->dev.platform_data;
        if (pdata == NULL) {
@@ -872,14 +890,27 @@ static int __devinit flctl_probe(struct platform_device *pdev)
                goto err_iomap;
        }
 
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "failed to get flste irq data\n");
+               goto err_flste;
+       }
+
+       ret = request_irq(irq, flctl_handle_flste, IRQF_SHARED, "flste", flctl);
+       if (ret) {
+               dev_err(&pdev->dev, "request interrupt failed.\n");
+               goto err_flste;
+       }
+
        platform_set_drvdata(pdev, flctl);
        flctl_mtd = &flctl->mtd;
        nand = &flctl->chip;
        flctl_mtd->priv = nand;
        flctl->pdev = pdev;
-       flctl->flcmncr_base = pdata->flcmncr_val;
        flctl->hwecc = pdata->has_hwecc;
        flctl->holden = pdata->use_holden;
+       flctl->flcmncr_base = pdata->flcmncr_val;
+       flctl->flintdmacr_base = flctl->hwecc ? (STERINTE | ECERB) : STERINTE;
 
        /* Set address of hardware control function */
        /* 20 us command delay time */
@@ -888,7 +919,6 @@ static int __devinit flctl_probe(struct platform_device *pdev)
        nand->read_byte = flctl_read_byte;
        nand->write_buf = flctl_write_buf;
        nand->read_buf = flctl_read_buf;
-       nand->verify_buf = flctl_verify_buf;
        nand->select_chip = flctl_select_chip;
        nand->cmdfunc = flctl_cmdfunc;
 
@@ -918,6 +948,9 @@ static int __devinit flctl_probe(struct platform_device *pdev)
 
 err_chip:
        pm_runtime_disable(&pdev->dev);
+       free_irq(irq, flctl);
+err_flste:
+       iounmap(flctl->reg);
 err_iomap:
        kfree(flctl);
        return ret;
@@ -929,6 +962,8 @@ static int __devexit flctl_remove(struct platform_device *pdev)
 
        nand_release(&flctl->mtd);
        pm_runtime_disable(&pdev->dev);
+       free_irq(platform_get_irq(pdev, 0), flctl);
+       iounmap(flctl->reg);
        kfree(flctl);
 
        return 0;
index e02b08bcf0c044e7cd845b046f81d013ec8140cc..f3f28fafbf7ae85b72311a46dfe437f4739a78e9 100644 (file)
@@ -98,24 +98,6 @@ static uint16_t socrates_nand_read_word(struct mtd_info *mtd)
        return word;
 }
 
-/**
- * socrates_nand_verify_buf -  Verify chip data against buffer
- * @mtd:       MTD device structure
- * @buf:       buffer containing the data to compare
- * @len:       number of bytes to compare
- */
-static int socrates_nand_verify_buf(struct mtd_info *mtd, const u8 *buf,
-               int len)
-{
-       int i;
-
-       for (i = 0; i < len; i++) {
-               if (buf[i] != socrates_nand_read_byte(mtd))
-                       return -EFAULT;
-       }
-       return 0;
-}
-
 /*
  * Hardware specific access to control-lines
  */
@@ -201,7 +183,6 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
        nand_chip->read_word = socrates_nand_read_word;
        nand_chip->write_buf = socrates_nand_write_buf;
        nand_chip->read_buf = socrates_nand_read_buf;
-       nand_chip->verify_buf = socrates_nand_verify_buf;
        nand_chip->dev_ready = socrates_nand_device_ready;
 
        nand_chip->ecc.mode = NAND_ECC_SOFT;    /* enable ECC */
index 5aa518081c513454e0fedb70f907cdeffcbaecd2..508e9e04b0926a5b16c4620dc1f2a821e945680d 100644 (file)
@@ -256,18 +256,6 @@ static void tmio_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
        tmio_ioread16_rep(tmio->fcr + FCR_DATA, buf, len >> 1);
 }
 
-static int
-tmio_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
-{
-       struct tmio_nand *tmio = mtd_to_tmio(mtd);
-       u16                             *p = (u16 *) buf;
-
-       for (len >>= 1; len; len--)
-               if (*(p++) != tmio_ioread16(tmio->fcr + FCR_DATA))
-                       return -EFAULT;
-       return 0;
-}
-
 static void tmio_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 {
        struct tmio_nand *tmio = mtd_to_tmio(mtd);
@@ -424,7 +412,6 @@ static int tmio_probe(struct platform_device *dev)
        nand_chip->read_byte = tmio_nand_read_byte;
        nand_chip->write_buf = tmio_nand_write_buf;
        nand_chip->read_buf = tmio_nand_read_buf;
-       nand_chip->verify_buf = tmio_nand_verify_buf;
 
        /* set eccmode using hardware ECC */
        nand_chip->ecc.mode = NAND_ECC_HW;
index 26398dcf21cfdccb606c923a7e0d96eefbd370de..e3d7266e256f2f5601aa6117bab6669964c0d604 100644 (file)
@@ -131,18 +131,6 @@ static void txx9ndfmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
                *buf++ = __raw_readl(ndfdtr);
 }
 
-static int txx9ndfmc_verify_buf(struct mtd_info *mtd, const uint8_t *buf,
-                               int len)
-{
-       struct platform_device *dev = mtd_to_platdev(mtd);
-       void __iomem *ndfdtr = ndregaddr(dev, TXX9_NDFDTR);
-
-       while (len--)
-               if (*buf++ != (uint8_t)__raw_readl(ndfdtr))
-                       return -EFAULT;
-       return 0;
-}
-
 static void txx9ndfmc_cmd_ctrl(struct mtd_info *mtd, int cmd,
                               unsigned int ctrl)
 {
@@ -346,7 +334,6 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
                chip->read_byte = txx9ndfmc_read_byte;
                chip->read_buf = txx9ndfmc_read_buf;
                chip->write_buf = txx9ndfmc_write_buf;
-               chip->verify_buf = txx9ndfmc_verify_buf;
                chip->cmd_ctrl = txx9ndfmc_cmd_ctrl;
                chip->dev_ready = txx9ndfmc_dev_ready;
                chip->ecc.calculate = txx9ndfmc_calculate_ecc;
diff --git a/drivers/mtd/nand/xway_nand.c b/drivers/mtd/nand/xway_nand.c
new file mode 100644 (file)
index 0000000..3f81dc8
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ *  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.
+ *
+ *  Copyright Â© 2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/mtd/nand.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+
+#include <lantiq_soc.h>
+
+/* nand registers */
+#define EBU_ADDSEL1            0x24
+#define EBU_NAND_CON           0xB0
+#define EBU_NAND_WAIT          0xB4
+#define EBU_NAND_ECC0          0xB8
+#define EBU_NAND_ECC_AC                0xBC
+
+/* nand commands */
+#define NAND_CMD_ALE           (1 << 2)
+#define NAND_CMD_CLE           (1 << 3)
+#define NAND_CMD_CS            (1 << 4)
+#define NAND_WRITE_CMD_RESET   0xff
+#define NAND_WRITE_CMD         (NAND_CMD_CS | NAND_CMD_CLE)
+#define NAND_WRITE_ADDR                (NAND_CMD_CS | NAND_CMD_ALE)
+#define NAND_WRITE_DATA                (NAND_CMD_CS)
+#define NAND_READ_DATA         (NAND_CMD_CS)
+#define NAND_WAIT_WR_C         (1 << 3)
+#define NAND_WAIT_RD           (0x1)
+
+/* we need to tel the ebu which addr we mapped the nand to */
+#define ADDSEL1_MASK(x)                (x << 4)
+#define ADDSEL1_REGEN          1
+
+/* we need to tell the EBU that we have nand attached and set it up properly */
+#define BUSCON1_SETUP          (1 << 22)
+#define BUSCON1_BCGEN_RES      (0x3 << 12)
+#define BUSCON1_WAITWRC2       (2 << 8)
+#define BUSCON1_WAITRDC2       (2 << 6)
+#define BUSCON1_HOLDC1         (1 << 4)
+#define BUSCON1_RECOVC1                (1 << 2)
+#define BUSCON1_CMULT4         1
+
+#define NAND_CON_CE            (1 << 20)
+#define NAND_CON_OUT_CS1       (1 << 10)
+#define NAND_CON_IN_CS1                (1 << 8)
+#define NAND_CON_PRE_P         (1 << 7)
+#define NAND_CON_WP_P          (1 << 6)
+#define NAND_CON_SE_P          (1 << 5)
+#define NAND_CON_CS_P          (1 << 4)
+#define NAND_CON_CSMUX         (1 << 1)
+#define NAND_CON_NANDM         1
+
+static void xway_reset_chip(struct nand_chip *chip)
+{
+       unsigned long nandaddr = (unsigned long) chip->IO_ADDR_W;
+       unsigned long flags;
+
+       nandaddr &= ~NAND_WRITE_ADDR;
+       nandaddr |= NAND_WRITE_CMD;
+
+       /* finish with a reset */
+       spin_lock_irqsave(&ebu_lock, flags);
+       writeb(NAND_WRITE_CMD_RESET, (void __iomem *) nandaddr);
+       while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
+               ;
+       spin_unlock_irqrestore(&ebu_lock, flags);
+}
+
+static void xway_select_chip(struct mtd_info *mtd, int chip)
+{
+
+       switch (chip) {
+       case -1:
+               ltq_ebu_w32_mask(NAND_CON_CE, 0, EBU_NAND_CON);
+               ltq_ebu_w32_mask(NAND_CON_NANDM, 0, EBU_NAND_CON);
+               break;
+       case 0:
+               ltq_ebu_w32_mask(0, NAND_CON_NANDM, EBU_NAND_CON);
+               ltq_ebu_w32_mask(0, NAND_CON_CE, EBU_NAND_CON);
+               break;
+       default:
+               BUG();
+       }
+}
+
+static void xway_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+       struct nand_chip *this = mtd->priv;
+       unsigned long nandaddr = (unsigned long) this->IO_ADDR_W;
+       unsigned long flags;
+
+       if (ctrl & NAND_CTRL_CHANGE) {
+               nandaddr &= ~(NAND_WRITE_CMD | NAND_WRITE_ADDR);
+               if (ctrl & NAND_CLE)
+                       nandaddr |= NAND_WRITE_CMD;
+               else
+                       nandaddr |= NAND_WRITE_ADDR;
+               this->IO_ADDR_W = (void __iomem *) nandaddr;
+       }
+
+       if (cmd != NAND_CMD_NONE) {
+               spin_lock_irqsave(&ebu_lock, flags);
+               writeb(cmd, this->IO_ADDR_W);
+               while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
+                       ;
+               spin_unlock_irqrestore(&ebu_lock, flags);
+       }
+}
+
+static int xway_dev_ready(struct mtd_info *mtd)
+{
+       return ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_RD;
+}
+
+static unsigned char xway_read_byte(struct mtd_info *mtd)
+{
+       struct nand_chip *this = mtd->priv;
+       unsigned long nandaddr = (unsigned long) this->IO_ADDR_R;
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&ebu_lock, flags);
+       ret = ltq_r8((void __iomem *)(nandaddr + NAND_READ_DATA));
+       spin_unlock_irqrestore(&ebu_lock, flags);
+
+       return ret;
+}
+
+static int xway_nand_probe(struct platform_device *pdev)
+{
+       struct nand_chip *this = platform_get_drvdata(pdev);
+       unsigned long nandaddr = (unsigned long) this->IO_ADDR_W;
+       const __be32 *cs = of_get_property(pdev->dev.of_node,
+                                       "lantiq,cs", NULL);
+       u32 cs_flag = 0;
+
+       /* load our CS from the DT. Either we find a valid 1 or default to 0 */
+       if (cs && (*cs == 1))
+               cs_flag = NAND_CON_IN_CS1 | NAND_CON_OUT_CS1;
+
+       /* setup the EBU to run in NAND mode on our base addr */
+       ltq_ebu_w32(CPHYSADDR(nandaddr)
+               | ADDSEL1_MASK(3) | ADDSEL1_REGEN, EBU_ADDSEL1);
+
+       ltq_ebu_w32(BUSCON1_SETUP | BUSCON1_BCGEN_RES | BUSCON1_WAITWRC2
+               | BUSCON1_WAITRDC2 | BUSCON1_HOLDC1 | BUSCON1_RECOVC1
+               | BUSCON1_CMULT4, LTQ_EBU_BUSCON1);
+
+       ltq_ebu_w32(NAND_CON_NANDM | NAND_CON_CSMUX | NAND_CON_CS_P
+               | NAND_CON_SE_P | NAND_CON_WP_P | NAND_CON_PRE_P
+               | cs_flag, EBU_NAND_CON);
+
+       /* finish with a reset */
+       xway_reset_chip(this);
+
+       return 0;
+}
+
+/* allow users to override the partition in DT using the cmdline */
+static const char *part_probes[] = { "cmdlinepart", "ofpart", NULL };
+
+static struct platform_nand_data xway_nand_data = {
+       .chip = {
+               .nr_chips               = 1,
+               .chip_delay             = 30,
+               .part_probe_types       = part_probes,
+       },
+       .ctrl = {
+               .probe          = xway_nand_probe,
+               .cmd_ctrl       = xway_cmd_ctrl,
+               .dev_ready      = xway_dev_ready,
+               .select_chip    = xway_select_chip,
+               .read_byte      = xway_read_byte,
+       }
+};
+
+/*
+ * Try to find the node inside the DT. If it is available attach out
+ * platform_nand_data
+ */
+static int __init xway_register_nand(void)
+{
+       struct device_node *node;
+       struct platform_device *pdev;
+
+       node = of_find_compatible_node(NULL, NULL, "lantiq,nand-xway");
+       if (!node)
+               return -ENOENT;
+       pdev = of_find_device_by_node(node);
+       if (!pdev)
+               return -EINVAL;
+       pdev->dev.platform_data = &xway_nand_data;
+       of_node_put(node);
+       return 0;
+}
+
+subsys_initcall(xway_register_nand);
index 9e2dfd517aa51c68e15e80d864d1a12f80c1fbe8..8dd6ba52404a390c57462bb90f25f470c1d32687 100644 (file)
@@ -346,7 +346,6 @@ static int sm_write_sector(struct sm_ftl *ftl,
        ret = mtd_write_oob(mtd, sm_mkoffset(ftl, zone, block, boffset), &ops);
 
        /* Now we assume that hardware will catch write bitflip errors */
-       /* If you are paranoid, use CONFIG_MTD_NAND_VERIFY_WRITE */
 
        if (ret) {
                dbg("write to block %d at zone %d, failed with error %d",
index b44dcab940d889346c4dfa3f22a8af348f32062c..bd0065c0d359f7e207523ca06f2aa0221dc78fad 100644 (file)
@@ -6,3 +6,4 @@ obj-$(CONFIG_MTD_TESTS) += mtd_stresstest.o
 obj-$(CONFIG_MTD_TESTS) += mtd_subpagetest.o
 obj-$(CONFIG_MTD_TESTS) += mtd_torturetest.o
 obj-$(CONFIG_MTD_TESTS) += mtd_nandecctest.o
+obj-$(CONFIG_MTD_TESTS) += mtd_nandbiterrs.o
diff --git a/drivers/mtd/tests/mtd_nandbiterrs.c b/drivers/mtd/tests/mtd_nandbiterrs.c
new file mode 100644 (file)
index 0000000..cc8d62c
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ * Copyright Â© 2012 NetCommWireless
+ * Iwo Mergler <Iwo.Mergler@netcommwireless.com.au>
+ *
+ * Test for multi-bit error recovery on a NAND page This mostly tests the
+ * ECC controller / driver.
+ *
+ * There are two test modes:
+ *
+ *     0 - artificially inserting bit errors until the ECC fails
+ *         This is the default method and fairly quick. It should
+ *         be independent of the quality of the FLASH.
+ *
+ *     1 - re-writing the same pattern repeatedly until the ECC fails.
+ *         This method relies on the physics of NAND FLASH to eventually
+ *         generate '0' bits if '1' has been written sufficient times.
+ *         Depending on the NAND, the first bit errors will appear after
+ *         1000 or more writes and then will usually snowball, reaching the
+ *         limits of the ECC quickly.
+ *
+ *         The test stops after 10000 cycles, should your FLASH be
+ *         exceptionally good and not generate bit errors before that. Try
+ *         a different page in that case.
+ *
+ * Please note that neither of these tests will significantly 'use up' any
+ * FLASH endurance. Only a maximum of two erase operations will be performed.
+ *
+ *
+ * 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; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/mtd/mtd.h>
+#include <linux/err.h>
+#include <linux/mtd/nand.h>
+#include <linux/slab.h>
+
+#define msg(FMT, VA...) pr_info("mtd_nandbiterrs: "FMT, ##VA)
+
+static int dev;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static unsigned page_offset;
+module_param(page_offset, uint, S_IRUGO);
+MODULE_PARM_DESC(page_offset, "Page number relative to dev start");
+
+static unsigned seed;
+module_param(seed, uint, S_IRUGO);
+MODULE_PARM_DESC(seed, "Random seed");
+
+static int mode;
+module_param(mode, int, S_IRUGO);
+MODULE_PARM_DESC(mode, "0=incremental errors, 1=overwrite test");
+
+static unsigned max_overwrite = 10000;
+
+static loff_t   offset;     /* Offset of the page we're using. */
+static unsigned eraseblock; /* Eraseblock number for our page. */
+
+/* We assume that the ECC can correct up to a certain number
+ * of biterrors per subpage. */
+static unsigned subsize;  /* Size of subpages */
+static unsigned subcount; /* Number of subpages per page */
+
+static struct mtd_info *mtd;   /* MTD device */
+
+static uint8_t *wbuffer; /* One page write / compare buffer */
+static uint8_t *rbuffer; /* One page read buffer */
+
+/* 'random' bytes from known offsets */
+static uint8_t hash(unsigned offset)
+{
+       unsigned v = offset;
+       unsigned char c;
+       v ^= 0x7f7edfd3;
+       v = v ^ (v >> 3);
+       v = v ^ (v >> 5);
+       v = v ^ (v >> 13);
+       c = v & 0xFF;
+       /* Reverse bits of result. */
+       c = (c & 0x0F) << 4 | (c & 0xF0) >> 4;
+       c = (c & 0x33) << 2 | (c & 0xCC) >> 2;
+       c = (c & 0x55) << 1 | (c & 0xAA) >> 1;
+       return c;
+}
+
+static int erase_block(void)
+{
+       int err;
+       struct erase_info ei;
+       loff_t addr = eraseblock * mtd->erasesize;
+
+       msg("erase_block\n");
+
+       memset(&ei, 0, sizeof(struct erase_info));
+       ei.mtd  = mtd;
+       ei.addr = addr;
+       ei.len  = mtd->erasesize;
+
+       err = mtd_erase(mtd, &ei);
+       if (err || ei.state == MTD_ERASE_FAILED) {
+               msg("error %d while erasing\n", err);
+               if (!err)
+                       err = -EIO;
+               return err;
+       }
+
+       return 0;
+}
+
+/* Writes wbuffer to page */
+static int write_page(int log)
+{
+       int err = 0;
+       size_t written;
+
+       if (log)
+               msg("write_page\n");
+
+       err = mtd_write(mtd, offset, mtd->writesize, &written, wbuffer);
+       if (err || written != mtd->writesize) {
+               msg("error: write failed at %#llx\n", (long long)offset);
+               if (!err)
+                       err = -EIO;
+       }
+
+       return err;
+}
+
+/* Re-writes the data area while leaving the OOB alone. */
+static int rewrite_page(int log)
+{
+       int err = 0;
+       struct mtd_oob_ops ops;
+
+       if (log)
+               msg("rewrite page\n");
+
+       ops.mode      = MTD_OPS_RAW; /* No ECC */
+       ops.len       = mtd->writesize;
+       ops.retlen    = 0;
+       ops.ooblen    = 0;
+       ops.oobretlen = 0;
+       ops.ooboffs   = 0;
+       ops.datbuf    = wbuffer;
+       ops.oobbuf    = NULL;
+
+       err = mtd_write_oob(mtd, offset, &ops);
+       if (err || ops.retlen != mtd->writesize) {
+               msg("error: write_oob failed (%d)\n", err);
+               if (!err)
+                       err = -EIO;
+       }
+
+       return err;
+}
+
+/* Reads page into rbuffer. Returns number of corrected bit errors (>=0)
+ * or error (<0) */
+static int read_page(int log)
+{
+       int err = 0;
+       size_t read;
+       struct mtd_ecc_stats oldstats;
+
+       if (log)
+               msg("read_page\n");
+
+       /* Saving last mtd stats */
+       memcpy(&oldstats, &mtd->ecc_stats, sizeof(oldstats));
+
+       err = mtd_read(mtd, offset, mtd->writesize, &read, rbuffer);
+       if (err == -EUCLEAN)
+               err = mtd->ecc_stats.corrected - oldstats.corrected;
+
+       if (err < 0 || read != mtd->writesize) {
+               msg("error: read failed at %#llx\n", (long long)offset);
+               if (err >= 0)
+                       err = -EIO;
+       }
+
+       return err;
+}
+
+/* Verifies rbuffer against random sequence */
+static int verify_page(int log)
+{
+       unsigned i, errs = 0;
+
+       if (log)
+               msg("verify_page\n");
+
+       for (i = 0; i < mtd->writesize; i++) {
+               if (rbuffer[i] != hash(i+seed)) {
+                       msg("Error: page offset %u, expected %02x, got %02x\n",
+                               i, hash(i+seed), rbuffer[i]);
+                       errs++;
+               }
+       }
+
+       if (errs)
+               return -EIO;
+       else
+               return 0;
+}
+
+#define CBIT(v, n) ((v) & (1 << (n)))
+#define BCLR(v, n) ((v) = (v) & ~(1 << (n)))
+
+/* Finds the first '1' bit in wbuffer starting at offset 'byte'
+ * and sets it to '0'. */
+static int insert_biterror(unsigned byte)
+{
+       int bit;
+
+       while (byte < mtd->writesize) {
+               for (bit = 7; bit >= 0; bit--) {
+                       if (CBIT(wbuffer[byte], bit)) {
+                               BCLR(wbuffer[byte], bit);
+                               msg("Inserted biterror @ %u/%u\n", byte, bit);
+                               return 0;
+                       }
+               }
+               byte++;
+       }
+       msg("biterror: Failed to find a '1' bit\n");
+       return -EIO;
+}
+
+/* Writes 'random' data to page and then introduces deliberate bit
+ * errors into the page, while verifying each step. */
+static int incremental_errors_test(void)
+{
+       int err = 0;
+       unsigned i;
+       unsigned errs_per_subpage = 0;
+
+       msg("incremental biterrors test\n");
+
+       for (i = 0; i < mtd->writesize; i++)
+               wbuffer[i] = hash(i+seed);
+
+       err = write_page(1);
+       if (err)
+               goto exit;
+
+       while (1) {
+
+               err = rewrite_page(1);
+               if (err)
+                       goto exit;
+
+               err = read_page(1);
+               if (err > 0)
+                       msg("Read reported %d corrected bit errors\n", err);
+               if (err < 0) {
+                       msg("After %d biterrors per subpage, read reported error %d\n",
+                               errs_per_subpage, err);
+                       err = 0;
+                       goto exit;
+               }
+
+               err = verify_page(1);
+               if (err) {
+                       msg("ECC failure, read data is incorrect despite read success\n");
+                       goto exit;
+               }
+
+               msg("Successfully corrected %d bit errors per subpage\n",
+                       errs_per_subpage);
+
+               for (i = 0; i < subcount; i++) {
+                       err = insert_biterror(i * subsize);
+                       if (err < 0)
+                               goto exit;
+               }
+               errs_per_subpage++;
+       }
+
+exit:
+       return err;
+}
+
+
+/* Writes 'random' data to page and then re-writes that same data repeatedly.
+   This eventually develops bit errors (bits written as '1' will slowly become
+   '0'), which are corrected as far as the ECC is capable of. */
+static int overwrite_test(void)
+{
+       int err = 0;
+       unsigned i;
+       unsigned max_corrected = 0;
+       unsigned opno = 0;
+       /* We don't expect more than this many correctable bit errors per
+        * page. */
+       #define MAXBITS 512
+       static unsigned bitstats[MAXBITS]; /* bit error histogram. */
+
+       memset(bitstats, 0, sizeof(bitstats));
+
+       msg("overwrite biterrors test\n");
+
+       for (i = 0; i < mtd->writesize; i++)
+               wbuffer[i] = hash(i+seed);
+
+       err = write_page(1);
+       if (err)
+               goto exit;
+
+       while (opno < max_overwrite) {
+
+               err = rewrite_page(0);
+               if (err)
+                       break;
+
+               err = read_page(0);
+               if (err >= 0) {
+                       if (err >= MAXBITS) {
+                               msg("Implausible number of bit errors corrected\n");
+                               err = -EIO;
+                               break;
+                       }
+                       bitstats[err]++;
+                       if (err > max_corrected) {
+                               max_corrected = err;
+                               msg("Read reported %d corrected bit errors\n",
+                                       err);
+                       }
+               } else { /* err < 0 */
+                       msg("Read reported error %d\n", err);
+                       err = 0;
+                       break;
+               }
+
+               err = verify_page(0);
+               if (err) {
+                       bitstats[max_corrected] = opno;
+                       msg("ECC failure, read data is incorrect despite read success\n");
+                       break;
+               }
+
+               opno++;
+       }
+
+       /* At this point bitstats[0] contains the number of ops with no bit
+        * errors, bitstats[1] the number of ops with 1 bit error, etc. */
+       msg("Bit error histogram (%d operations total):\n", opno);
+       for (i = 0; i < max_corrected; i++)
+               msg("Page reads with %3d corrected bit errors: %d\n",
+                       i, bitstats[i]);
+
+exit:
+       return err;
+}
+
+static int __init mtd_nandbiterrs_init(void)
+{
+       int err = 0;
+
+       msg("\n");
+       msg("==================================================\n");
+       msg("MTD device: %d\n", dev);
+
+       mtd = get_mtd_device(NULL, dev);
+       if (IS_ERR(mtd)) {
+               err = PTR_ERR(mtd);
+               msg("error: cannot get MTD device\n");
+               goto exit_mtddev;
+       }
+
+       if (mtd->type != MTD_NANDFLASH) {
+               msg("this test requires NAND flash\n");
+               err = -ENODEV;
+               goto exit_nand;
+       }
+
+       msg("MTD device size %llu, eraseblock=%u, page=%u, oob=%u\n",
+               (unsigned long long)mtd->size, mtd->erasesize,
+               mtd->writesize, mtd->oobsize);
+
+       subsize  = mtd->writesize >> mtd->subpage_sft;
+       subcount = mtd->writesize / subsize;
+
+       msg("Device uses %d subpages of %d bytes\n", subcount, subsize);
+
+       offset     = page_offset * mtd->writesize;
+       eraseblock = mtd_div_by_eb(offset, mtd);
+
+       msg("Using page=%u, offset=%llu, eraseblock=%u\n",
+               page_offset, offset, eraseblock);
+
+       wbuffer = kmalloc(mtd->writesize, GFP_KERNEL);
+       if (!wbuffer) {
+               err = -ENOMEM;
+               goto exit_wbuffer;
+       }
+
+       rbuffer = kmalloc(mtd->writesize, GFP_KERNEL);
+       if (!rbuffer) {
+               err = -ENOMEM;
+               goto exit_rbuffer;
+       }
+
+       err = erase_block();
+       if (err)
+               goto exit_error;
+
+       if (mode == 0)
+               err = incremental_errors_test();
+       else
+               err = overwrite_test();
+
+       if (err)
+               goto exit_error;
+
+       /* We leave the block un-erased in case of test failure. */
+       err = erase_block();
+       if (err)
+               goto exit_error;
+
+       err = -EIO;
+       msg("finished successfully.\n");
+       msg("==================================================\n");
+
+exit_error:
+       kfree(rbuffer);
+exit_rbuffer:
+       kfree(wbuffer);
+exit_wbuffer:
+       /* Nothing */
+exit_nand:
+       put_mtd_device(mtd);
+exit_mtddev:
+       return err;
+}
+
+static void __exit mtd_nandbiterrs_exit(void)
+{
+       return;
+}
+
+module_init(mtd_nandbiterrs_init);
+module_exit(mtd_nandbiterrs_exit);
+
+MODULE_DESCRIPTION("NAND bit error recovery test");
+MODULE_AUTHOR("Iwo Mergler");
+MODULE_LICENSE("GPL");
index 70d6d7d0d65696b5cae7b5a1dd2aa57674a6f264..b437fa425077db48d4bb76da8d343e9739e56205 100644 (file)
 #include <linux/random.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
-#include <linux/jiffies.h>
+#include <linux/slab.h>
 #include <linux/mtd/nand_ecc.h>
 
+/*
+ * Test the implementation for software ECC
+ *
+ * No actual MTD device is needed, So we don't need to warry about losing
+ * important data by human error.
+ *
+ * This covers possible patterns of corruption which can be reliably corrected
+ * or detected.
+ */
+
 #if defined(CONFIG_MTD_NAND) || defined(CONFIG_MTD_NAND_MODULE)
 
-static void inject_single_bit_error(void *data, size_t size)
+struct nand_ecc_test {
+       const char *name;
+       void (*prepare)(void *, void *, void *, void *, const size_t);
+       int (*verify)(void *, void *, void *, const size_t);
+};
+
+/*
+ * The reason for this __change_bit_le() instead of __change_bit() is to inject
+ * bit error properly within the region which is not a multiple of
+ * sizeof(unsigned long) on big-endian systems
+ */
+#ifdef __LITTLE_ENDIAN
+#define __change_bit_le(nr, addr) __change_bit(nr, addr)
+#elif defined(__BIG_ENDIAN)
+#define __change_bit_le(nr, addr) \
+               __change_bit((nr) ^ ((BITS_PER_LONG - 1) & ~0x7), addr)
+#else
+#error "Unknown byte order"
+#endif
+
+static void single_bit_error_data(void *error_data, void *correct_data,
+                               size_t size)
 {
-       unsigned long offset = random32() % (size * BITS_PER_BYTE);
+       unsigned int offset = random32() % (size * BITS_PER_BYTE);
 
-       __change_bit(offset, data);
+       memcpy(error_data, correct_data, size);
+       __change_bit_le(offset, error_data);
 }
 
-static unsigned char data[512];
-static unsigned char error_data[512];
+static void double_bit_error_data(void *error_data, void *correct_data,
+                               size_t size)
+{
+       unsigned int offset[2];
+
+       offset[0] = random32() % (size * BITS_PER_BYTE);
+       do {
+               offset[1] = random32() % (size * BITS_PER_BYTE);
+       } while (offset[0] == offset[1]);
 
-static int nand_ecc_test(const size_t size)
+       memcpy(error_data, correct_data, size);
+
+       __change_bit_le(offset[0], error_data);
+       __change_bit_le(offset[1], error_data);
+}
+
+static unsigned int random_ecc_bit(size_t size)
 {
-       unsigned char code[3];
-       unsigned char error_code[3];
-       char testname[30];
+       unsigned int offset = random32() % (3 * BITS_PER_BYTE);
+
+       if (size == 256) {
+               /*
+                * Don't inject a bit error into the insignificant bits (16th
+                * and 17th bit) in ECC code for 256 byte data block
+                */
+               while (offset == 16 || offset == 17)
+                       offset = random32() % (3 * BITS_PER_BYTE);
+       }
 
-       BUG_ON(sizeof(data) < size);
+       return offset;
+}
 
-       sprintf(testname, "nand-ecc-%zu", size);
+static void single_bit_error_ecc(void *error_ecc, void *correct_ecc,
+                               size_t size)
+{
+       unsigned int offset = random_ecc_bit(size);
 
-       get_random_bytes(data, size);
+       memcpy(error_ecc, correct_ecc, 3);
+       __change_bit_le(offset, error_ecc);
+}
 
-       memcpy(error_data, data, size);
-       inject_single_bit_error(error_data, size);
+static void double_bit_error_ecc(void *error_ecc, void *correct_ecc,
+                               size_t size)
+{
+       unsigned int offset[2];
 
-       __nand_calculate_ecc(data, size, code);
-       __nand_calculate_ecc(error_data, size, error_code);
-       __nand_correct_data(error_data, code, error_code, size);
+       offset[0] = random_ecc_bit(size);
+       do {
+               offset[1] = random_ecc_bit(size);
+       } while (offset[0] == offset[1]);
 
-       if (!memcmp(data, error_data, size)) {
-               printk(KERN_INFO "mtd_nandecctest: ok - %s\n", testname);
+       memcpy(error_ecc, correct_ecc, 3);
+       __change_bit_le(offset[0], error_ecc);
+       __change_bit_le(offset[1], error_ecc);
+}
+
+static void no_bit_error(void *error_data, void *error_ecc,
+               void *correct_data, void *correct_ecc, const size_t size)
+{
+       memcpy(error_data, correct_data, size);
+       memcpy(error_ecc, correct_ecc, 3);
+}
+
+static int no_bit_error_verify(void *error_data, void *error_ecc,
+                               void *correct_data, const size_t size)
+{
+       unsigned char calc_ecc[3];
+       int ret;
+
+       __nand_calculate_ecc(error_data, size, calc_ecc);
+       ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size);
+       if (ret == 0 && !memcmp(correct_data, error_data, size))
                return 0;
-       }
 
-       printk(KERN_ERR "mtd_nandecctest: not ok - %s\n", testname);
+       return -EINVAL;
+}
+
+static void single_bit_error_in_data(void *error_data, void *error_ecc,
+               void *correct_data, void *correct_ecc, const size_t size)
+{
+       single_bit_error_data(error_data, correct_data, size);
+       memcpy(error_ecc, correct_ecc, 3);
+}
+
+static void single_bit_error_in_ecc(void *error_data, void *error_ecc,
+               void *correct_data, void *correct_ecc, const size_t size)
+{
+       memcpy(error_data, correct_data, size);
+       single_bit_error_ecc(error_ecc, correct_ecc, size);
+}
+
+static int single_bit_error_correct(void *error_data, void *error_ecc,
+                               void *correct_data, const size_t size)
+{
+       unsigned char calc_ecc[3];
+       int ret;
 
-       printk(KERN_DEBUG "hexdump of data:\n");
-       print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4,
-                       data, size, false);
-       printk(KERN_DEBUG "hexdump of error data:\n");
-       print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4,
+       __nand_calculate_ecc(error_data, size, calc_ecc);
+       ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size);
+       if (ret == 1 && !memcmp(correct_data, error_data, size))
+               return 0;
+
+       return -EINVAL;
+}
+
+static void double_bit_error_in_data(void *error_data, void *error_ecc,
+               void *correct_data, void *correct_ecc, const size_t size)
+{
+       double_bit_error_data(error_data, correct_data, size);
+       memcpy(error_ecc, correct_ecc, 3);
+}
+
+static void single_bit_error_in_data_and_ecc(void *error_data, void *error_ecc,
+               void *correct_data, void *correct_ecc, const size_t size)
+{
+       single_bit_error_data(error_data, correct_data, size);
+       single_bit_error_ecc(error_ecc, correct_ecc, size);
+}
+
+static void double_bit_error_in_ecc(void *error_data, void *error_ecc,
+               void *correct_data, void *correct_ecc, const size_t size)
+{
+       memcpy(error_data, correct_data, size);
+       double_bit_error_ecc(error_ecc, correct_ecc, size);
+}
+
+static int double_bit_error_detect(void *error_data, void *error_ecc,
+                               void *correct_data, const size_t size)
+{
+       unsigned char calc_ecc[3];
+       int ret;
+
+       __nand_calculate_ecc(error_data, size, calc_ecc);
+       ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size);
+
+       return (ret == -1) ? 0 : -EINVAL;
+}
+
+static const struct nand_ecc_test nand_ecc_test[] = {
+       {
+               .name = "no-bit-error",
+               .prepare = no_bit_error,
+               .verify = no_bit_error_verify,
+       },
+       {
+               .name = "single-bit-error-in-data-correct",
+               .prepare = single_bit_error_in_data,
+               .verify = single_bit_error_correct,
+       },
+       {
+               .name = "single-bit-error-in-ecc-correct",
+               .prepare = single_bit_error_in_ecc,
+               .verify = single_bit_error_correct,
+       },
+       {
+               .name = "double-bit-error-in-data-detect",
+               .prepare = double_bit_error_in_data,
+               .verify = double_bit_error_detect,
+       },
+       {
+               .name = "single-bit-error-in-data-and-ecc-detect",
+               .prepare = single_bit_error_in_data_and_ecc,
+               .verify = double_bit_error_detect,
+       },
+       {
+               .name = "double-bit-error-in-ecc-detect",
+               .prepare = double_bit_error_in_ecc,
+               .verify = double_bit_error_detect,
+       },
+};
+
+static void dump_data_ecc(void *error_data, void *error_ecc, void *correct_data,
+                       void *correct_ecc, const size_t size)
+{
+       pr_info("hexdump of error data:\n");
+       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
                        error_data, size, false);
+       print_hex_dump(KERN_INFO, "hexdump of error ecc: ",
+                       DUMP_PREFIX_NONE, 16, 1, error_ecc, 3, false);
+
+       pr_info("hexdump of correct data:\n");
+       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
+                       correct_data, size, false);
+       print_hex_dump(KERN_INFO, "hexdump of correct ecc: ",
+                       DUMP_PREFIX_NONE, 16, 1, correct_ecc, 3, false);
+}
+
+static int nand_ecc_test_run(const size_t size)
+{
+       int i;
+       int err = 0;
+       void *error_data;
+       void *error_ecc;
+       void *correct_data;
+       void *correct_ecc;
 
-       return -1;
+       error_data = kmalloc(size, GFP_KERNEL);
+       error_ecc = kmalloc(3, GFP_KERNEL);
+       correct_data = kmalloc(size, GFP_KERNEL);
+       correct_ecc = kmalloc(3, GFP_KERNEL);
+
+       if (!error_data || !error_ecc || !correct_data || !correct_ecc) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       get_random_bytes(correct_data, size);
+       __nand_calculate_ecc(correct_data, size, correct_ecc);
+
+       for (i = 0; i < ARRAY_SIZE(nand_ecc_test); i++) {
+               nand_ecc_test[i].prepare(error_data, error_ecc,
+                               correct_data, correct_ecc, size);
+               err = nand_ecc_test[i].verify(error_data, error_ecc,
+                                               correct_data, size);
+
+               if (err) {
+                       pr_err("mtd_nandecctest: not ok - %s-%zd\n",
+                               nand_ecc_test[i].name, size);
+                       dump_data_ecc(error_data, error_ecc,
+                               correct_data, correct_ecc, size);
+                       break;
+               }
+               pr_info("mtd_nandecctest: ok - %s-%zd\n",
+                       nand_ecc_test[i].name, size);
+       }
+error:
+       kfree(error_data);
+       kfree(error_ecc);
+       kfree(correct_data);
+       kfree(correct_ecc);
+
+       return err;
 }
 
 #else
 
-static int nand_ecc_test(const size_t size)
+static int nand_ecc_test_run(const size_t size)
 {
        return 0;
 }
@@ -66,12 +293,13 @@ static int nand_ecc_test(const size_t size)
 
 static int __init ecc_test_init(void)
 {
-       srandom32(jiffies);
+       int err;
 
-       nand_ecc_test(256);
-       nand_ecc_test(512);
+       err = nand_ecc_test_run(256);
+       if (err)
+               return err;
 
-       return 0;
+       return nand_ecc_test_run(512);
 }
 
 static void __exit ecc_test_exit(void)
index 2aec4f3b72be3d9975ce92d83b1fdd063872a95b..42b0f7456fc4a4876d94ed1131c5dab1c7ff7dee 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/random.h>
 
 #define PRINT_PREF KERN_INFO "mtd_speedtest: "
 
@@ -47,25 +48,13 @@ static int ebcnt;
 static int pgcnt;
 static int goodebcnt;
 static struct timeval start, finish;
-static unsigned long next = 1;
-
-static inline unsigned int simple_rand(void)
-{
-       next = next * 1103515245 + 12345;
-       return (unsigned int)((next / 65536) % 32768);
-}
-
-static inline void simple_srand(unsigned long seed)
-{
-       next = seed;
-}
 
 static void set_random_data(unsigned char *buf, size_t len)
 {
        size_t i;
 
        for (i = 0; i < len; ++i)
-               buf[i] = simple_rand();
+               buf[i] = random32();
 }
 
 static int erase_eraseblock(int ebnum)
@@ -407,7 +396,6 @@ static int __init mtd_speedtest_init(void)
                goto out;
        }
 
-       simple_srand(1);
        set_random_data(iobuf, mtd->erasesize);
 
        err = scan_for_bad_eraseblocks();
index 7b33f22d0b583196ae0a7fb5ccd6563293e239af..cb268cebf01ae0c7fec1c3951975bc22bde34daa 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/vmalloc.h>
+#include <linux/random.h>
 
 #define PRINT_PREF KERN_INFO "mtd_stresstest: "
 
@@ -48,28 +49,13 @@ static int pgsize;
 static int bufsize;
 static int ebcnt;
 static int pgcnt;
-static unsigned long next = 1;
-
-static inline unsigned int simple_rand(void)
-{
-       next = next * 1103515245 + 12345;
-       return (unsigned int)((next / 65536) % 32768);
-}
-
-static inline void simple_srand(unsigned long seed)
-{
-       next = seed;
-}
 
 static int rand_eb(void)
 {
-       int eb;
+       unsigned int eb;
 
 again:
-       if (ebcnt < 32768)
-               eb = simple_rand();
-       else
-               eb = (simple_rand() << 15) | simple_rand();
+       eb = random32();
        /* Read or write up 2 eraseblocks at a time - hence 'ebcnt - 1' */
        eb %= (ebcnt - 1);
        if (bbt[eb])
@@ -79,24 +65,18 @@ again:
 
 static int rand_offs(void)
 {
-       int offs;
+       unsigned int offs;
 
-       if (bufsize < 32768)
-               offs = simple_rand();
-       else
-               offs = (simple_rand() << 15) | simple_rand();
+       offs = random32();
        offs %= bufsize;
        return offs;
 }
 
 static int rand_len(int offs)
 {
-       int len;
+       unsigned int len;
 
-       if (bufsize < 32768)
-               len = simple_rand();
-       else
-               len = (simple_rand() << 15) | simple_rand();
+       len = random32();
        len %= (bufsize - offs);
        return len;
 }
@@ -211,7 +191,7 @@ static int do_write(void)
 
 static int do_operation(void)
 {
-       if (simple_rand() & 1)
+       if (random32() & 1)
                return do_read();
        else
                return do_write();
@@ -302,9 +282,8 @@ static int __init mtd_stresstest_init(void)
        }
        for (i = 0; i < ebcnt; i++)
                offsets[i] = mtd->erasesize;
-       simple_srand(current->pid);
        for (i = 0; i < bufsize; i++)
-               writebuf[i] = simple_rand();
+               writebuf[i] = random32();
 
        err = scan_for_bad_eraseblocks();
        if (err)
index 64d0d9c1afa271c9ae73cb1818cdb6b7318d36f4..3491d4312fc9252639a082f7897643a2ee6f3c0a 100644 (file)
@@ -1845,6 +1845,7 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
        if((pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM))==0){
                printk(KERN_ERR "amd8111e: No Power Management capability, "
                       "exiting.\n");
+               err = -ENODEV;
                goto err_free_reg;
        }
 
@@ -1852,6 +1853,7 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
        if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) < 0) {
                printk(KERN_ERR "amd8111e: DMA not supported,"
                        "exiting.\n");
+               err = -ENODEV;
                goto err_free_reg;
        }
 
index 397596b078d9415d7b3431f78b140542da88e2be..f195acfa2df7dc4efcc5368173be475e6cd5b72f 100644 (file)
@@ -1174,8 +1174,10 @@ static int __devinit au1000_probe(struct platform_device *pdev)
        snprintf(aup->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
                pdev->name, aup->mac_id);
        aup->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
-       if (aup->mii_bus->irq == NULL)
+       if (aup->mii_bus->irq == NULL) {
+               err = -ENOMEM;
                goto err_out;
+       }
 
        for (i = 0; i < PHY_MAX_ADDR; ++i)
                aup->mii_bus->irq[i] = PHY_POLL;
@@ -1190,7 +1192,8 @@ static int __devinit au1000_probe(struct platform_device *pdev)
                goto err_mdiobus_reg;
        }
 
-       if (au1000_mii_probe(dev) != 0)
+       err = au1000_mii_probe(dev);
+       if (err != 0)
                goto err_out;
 
        pDBfree = NULL;
@@ -1205,6 +1208,7 @@ static int __devinit au1000_probe(struct platform_device *pdev)
        }
        aup->pDBfree = pDBfree;
 
+       err = -ENODEV;
        for (i = 0; i < NUM_RX_DMA; i++) {
                pDB = au1000_GetFreeDB(aup);
                if (!pDB)
@@ -1213,6 +1217,8 @@ static int __devinit au1000_probe(struct platform_device *pdev)
                aup->rx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
                aup->rx_db_inuse[i] = pDB;
        }
+
+       err = -ENODEV;
        for (i = 0; i < NUM_TX_DMA; i++) {
                pDB = au1000_GetFreeDB(aup);
                if (!pDB)
index 2b4b4f529ab4db6627f558ff16f0059d216f7ddb..16814b34d4b66ae8a39414a14e2bec0a72f89029 100644 (file)
@@ -375,7 +375,6 @@ struct xgmac_priv {
        unsigned int tx_tail;
 
        void __iomem *base;
-       struct sk_buff_head rx_recycle;
        unsigned int dma_buf_sz;
        dma_addr_t dma_rx_phy;
        dma_addr_t dma_tx_phy;
@@ -672,9 +671,7 @@ static void xgmac_rx_refill(struct xgmac_priv *priv)
                p = priv->dma_rx + entry;
 
                if (priv->rx_skbuff[entry] == NULL) {
-                       skb = __skb_dequeue(&priv->rx_recycle);
-                       if (skb == NULL)
-                               skb = netdev_alloc_skb(priv->dev, priv->dma_buf_sz);
+                       skb = netdev_alloc_skb(priv->dev, priv->dma_buf_sz);
                        if (unlikely(skb == NULL))
                                break;
 
@@ -887,17 +884,7 @@ static void xgmac_tx_complete(struct xgmac_priv *priv)
                                       desc_get_buf_len(p), DMA_TO_DEVICE);
                }
 
-               /*
-                * If there's room in the queue (limit it to size)
-                * we add this skb back into the pool,
-                * if it's the right size.
-                */
-               if ((skb_queue_len(&priv->rx_recycle) <
-                       DMA_RX_RING_SZ) &&
-                       skb_recycle_check(skb, priv->dma_buf_sz))
-                       __skb_queue_head(&priv->rx_recycle, skb);
-               else
-                       dev_kfree_skb(skb);
+               dev_kfree_skb(skb);
        }
 
        if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) >
@@ -1016,7 +1003,6 @@ static int xgmac_open(struct net_device *dev)
                        dev->dev_addr);
        }
 
-       skb_queue_head_init(&priv->rx_recycle);
        memset(&priv->xstats, 0, sizeof(struct xgmac_extra_stats));
 
        /* Initialize the XGMAC and descriptors */
@@ -1053,7 +1039,6 @@ static int xgmac_stop(struct net_device *dev)
                napi_disable(&priv->napi);
 
        writel(0, priv->base + XGMAC_DMA_INTR_ENA);
-       skb_queue_purge(&priv->rx_recycle);
 
        /* Disable the MAC core */
        xgmac_mac_disable(priv->base);
index 31752b24434eaafc348665be8b2be6104bb5c018..a4da893ac1e15cfd02a2d071503afaa21838e51c 100644 (file)
@@ -696,6 +696,7 @@ int t4_seeprom_wp(struct adapter *adapter, bool enable);
 int get_vpd_params(struct adapter *adapter, struct vpd_params *p);
 int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
 unsigned int t4_flash_cfg_addr(struct adapter *adapter);
+int t4_load_cfg(struct adapter *adapter, const u8 *cfg_data, unsigned int size);
 int t4_check_fw_version(struct adapter *adapter);
 int t4_prep_adapter(struct adapter *adapter);
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
index 6b9f6bb2f7edb9e505c69f8ce40507b2093df131..604f4f87f550c879a087fd128892d97450aa2d19 100644 (file)
@@ -443,7 +443,10 @@ int dbfifo_int_thresh = 10; /* 10 == 640 entry threshold */
 module_param(dbfifo_int_thresh, int, 0644);
 MODULE_PARM_DESC(dbfifo_int_thresh, "doorbell fifo interrupt threshold");
 
-int dbfifo_drain_delay = 1000; /* usecs to sleep while draining the dbfifo */
+/*
+ * usecs to sleep while draining the dbfifo
+ */
+static int dbfifo_drain_delay = 1000;
 module_param(dbfifo_drain_delay, int, 0644);
 MODULE_PARM_DESC(dbfifo_drain_delay,
                 "usecs to sleep while draining the dbfifo");
@@ -636,7 +639,7 @@ static void name_msix_vecs(struct adapter *adap)
 static int request_msix_queue_irqs(struct adapter *adap)
 {
        struct sge *s = &adap->sge;
-       int err, ethqidx, ofldqidx = 0, rdmaqidx = 0, msi = 2;
+       int err, ethqidx, ofldqidx = 0, rdmaqidx = 0, msi_index = 2;
 
        err = request_irq(adap->msix_info[1].vec, t4_sge_intr_msix, 0,
                          adap->msix_info[1].desc, &s->fw_evtq);
@@ -644,56 +647,60 @@ static int request_msix_queue_irqs(struct adapter *adap)
                return err;
 
        for_each_ethrxq(s, ethqidx) {
-               err = request_irq(adap->msix_info[msi].vec, t4_sge_intr_msix, 0,
-                                 adap->msix_info[msi].desc,
+               err = request_irq(adap->msix_info[msi_index].vec,
+                                 t4_sge_intr_msix, 0,
+                                 adap->msix_info[msi_index].desc,
                                  &s->ethrxq[ethqidx].rspq);
                if (err)
                        goto unwind;
-               msi++;
+               msi_index++;
        }
        for_each_ofldrxq(s, ofldqidx) {
-               err = request_irq(adap->msix_info[msi].vec, t4_sge_intr_msix, 0,
-                                 adap->msix_info[msi].desc,
+               err = request_irq(adap->msix_info[msi_index].vec,
+                                 t4_sge_intr_msix, 0,
+                                 adap->msix_info[msi_index].desc,
                                  &s->ofldrxq[ofldqidx].rspq);
                if (err)
                        goto unwind;
-               msi++;
+               msi_index++;
        }
        for_each_rdmarxq(s, rdmaqidx) {
-               err = request_irq(adap->msix_info[msi].vec, t4_sge_intr_msix, 0,
-                                 adap->msix_info[msi].desc,
+               err = request_irq(adap->msix_info[msi_index].vec,
+                                 t4_sge_intr_msix, 0,
+                                 adap->msix_info[msi_index].desc,
                                  &s->rdmarxq[rdmaqidx].rspq);
                if (err)
                        goto unwind;
-               msi++;
+               msi_index++;
        }
        return 0;
 
 unwind:
        while (--rdmaqidx >= 0)
-               free_irq(adap->msix_info[--msi].vec,
+               free_irq(adap->msix_info[--msi_index].vec,
                         &s->rdmarxq[rdmaqidx].rspq);
        while (--ofldqidx >= 0)
-               free_irq(adap->msix_info[--msi].vec,
+               free_irq(adap->msix_info[--msi_index].vec,
                         &s->ofldrxq[ofldqidx].rspq);
        while (--ethqidx >= 0)
-               free_irq(adap->msix_info[--msi].vec, &s->ethrxq[ethqidx].rspq);
+               free_irq(adap->msix_info[--msi_index].vec,
+                        &s->ethrxq[ethqidx].rspq);
        free_irq(adap->msix_info[1].vec, &s->fw_evtq);
        return err;
 }
 
 static void free_msix_queue_irqs(struct adapter *adap)
 {
-       int i, msi = 2;
+       int i, msi_index = 2;
        struct sge *s = &adap->sge;
 
        free_irq(adap->msix_info[1].vec, &s->fw_evtq);
        for_each_ethrxq(s, i)
-               free_irq(adap->msix_info[msi++].vec, &s->ethrxq[i].rspq);
+               free_irq(adap->msix_info[msi_index++].vec, &s->ethrxq[i].rspq);
        for_each_ofldrxq(s, i)
-               free_irq(adap->msix_info[msi++].vec, &s->ofldrxq[i].rspq);
+               free_irq(adap->msix_info[msi_index++].vec, &s->ofldrxq[i].rspq);
        for_each_rdmarxq(s, i)
-               free_irq(adap->msix_info[msi++].vec, &s->rdmarxq[i].rspq);
+               free_irq(adap->msix_info[msi_index++].vec, &s->rdmarxq[i].rspq);
 }
 
 /**
@@ -2535,9 +2542,8 @@ static int read_eq_indices(struct adapter *adap, u16 qid, u16 *pidx, u16 *cidx)
 
        ret = t4_mem_win_read_len(adap, addr, (__be32 *)&indices, 8);
        if (!ret) {
-               indices = be64_to_cpu(indices);
-               *cidx = (indices >> 25) & 0xffff;
-               *pidx = (indices >> 9) & 0xffff;
+               *cidx = (be64_to_cpu(indices) >> 25) & 0xffff;
+               *pidx = (be64_to_cpu(indices) >> 9) & 0xffff;
        }
        return ret;
 }
@@ -3634,10 +3640,10 @@ static int adap_init0_no_config(struct adapter *adapter, int reset)
         * field selections will fit in the 36-bit budget.
         */
        if (tp_vlan_pri_map != TP_VLAN_PRI_MAP_DEFAULT) {
-               int i, bits = 0;
+               int j, bits = 0;
 
-               for (i = TP_VLAN_PRI_MAP_FIRST; i <= TP_VLAN_PRI_MAP_LAST; i++)
-                       switch (tp_vlan_pri_map & (1 << i)) {
+               for (j = TP_VLAN_PRI_MAP_FIRST; j <= TP_VLAN_PRI_MAP_LAST; j++)
+                       switch (tp_vlan_pri_map & (1 << j)) {
                        case 0:
                                /* compressed filter field not enabled */
                                break;
index 137a24438d9c76532d691158913a9066d38146f0..32eec15fe4c2cd8425f89661231797e96007c5b1 100644 (file)
@@ -380,9 +380,11 @@ static int t4_mem_win_rw(struct adapter *adap, u32 addr, __be32 *data, int dir)
        /* Collecting data 4 bytes at a time upto MEMWIN0_APERTURE */
        for (i = 0; i < MEMWIN0_APERTURE; i = i+0x4) {
                if (dir)
-                       *data++ = t4_read_reg(adap, (MEMWIN0_BASE + i));
+                       *data++ = (__force __be32) t4_read_reg(adap,
+                                                       (MEMWIN0_BASE + i));
                else
-                       t4_write_reg(adap, (MEMWIN0_BASE + i), *data++);
+                       t4_write_reg(adap, (MEMWIN0_BASE + i),
+                                    (__force u32) *data++);
        }
 
        return 0;
@@ -417,7 +419,7 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len,
        if ((addr & 0x3) || (len & 0x3))
                return -EINVAL;
 
-       data = vmalloc(MEMWIN0_APERTURE/sizeof(__be32));
+       data = vmalloc(MEMWIN0_APERTURE);
        if (!data)
                return -ENOMEM;
 
@@ -744,7 +746,7 @@ static int t4_read_flash(struct adapter *adapter, unsigned int addr,
                if (ret)
                        return ret;
                if (byte_oriented)
-                       *data = htonl(*data);
+                       *data = (__force __u32) (htonl(*data));
        }
        return 0;
 }
@@ -992,7 +994,7 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size)
        int ret, addr;
        unsigned int i;
        u8 first_page[SF_PAGE_SIZE];
-       const u32 *p = (const u32 *)fw_data;
+       const __be32 *p = (const __be32 *)fw_data;
        const struct fw_hdr *hdr = (const struct fw_hdr *)fw_data;
        unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
        unsigned int fw_img_start = adap->params.sf_fw_start;
@@ -2315,7 +2317,8 @@ int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len)
        t4_read_reg(adap, PCIE_MEM_ACCESS_OFFSET);
 
        for (i = 0; i < len; i += 4)
-               *data++ = t4_read_reg(adap, (MEMWIN0_BASE + off + i));
+               *data++ = (__force __be32) t4_read_reg(adap,
+                                               (MEMWIN0_BASE + off + i));
 
        return 0;
 }
index 4d6fe604fa64b920d58b05f3989a365355f951c3..d23755ea9bc79c68b793af65c824dfd6477ddb78 100644 (file)
@@ -446,13 +446,17 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
        /* Allocate Tx/Rx descriptor memory */
        db->desc_pool_ptr = pci_alloc_consistent(pdev, sizeof(struct tx_desc) *
                        DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr);
-       if (!db->desc_pool_ptr)
+       if (!db->desc_pool_ptr) {
+               err = -ENOMEM;
                goto err_out_res;
+       }
 
        db->buf_pool_ptr = pci_alloc_consistent(pdev, TX_BUF_ALLOC *
                        TX_DESC_CNT + 4, &db->buf_pool_dma_ptr);
-       if (!db->buf_pool_ptr)
+       if (!db->buf_pool_ptr) {
+               err = -ENOMEM;
                goto err_out_free_desc;
+       }
 
        db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
        db->first_tx_desc_dma = db->desc_pool_dma_ptr;
@@ -462,8 +466,10 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
        db->chip_id = ent->driver_data;
        /* IO type range. */
        db->ioaddr = pci_iomap(pdev, 0, 0);
-       if (!db->ioaddr)
+       if (!db->ioaddr) {
+               err = -ENOMEM;
                goto err_out_free_buf;
+       }
 
        db->chip_revision = pdev->revision;
        db->wol_mode = 0;
index eb3f2cb3b93bbef296948f8479ab229783c01a94..d1b6cc5876393cc598a5d473fab158bb13477bdd 100644 (file)
@@ -2129,8 +2129,11 @@ void be_detect_error(struct be_adapter *adapter)
                ue_hi = (ue_hi & ~ue_hi_mask);
        }
 
-       if (ue_lo || ue_hi ||
-               sliport_status & SLIPORT_STATUS_ERR_MASK) {
+       /* On certain platforms BE hardware can indicate spurious UEs.
+        * Allow the h/w to stop working completely in case of a real UE.
+        * Hence not setting the hw_error for UE detection.
+        */
+       if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
                adapter->hw_error = true;
                dev_err(&adapter->pdev->dev,
                        "Error detected in the card\n");
index a1b52ec3b930981e240cad7ba4d3522936ed2eab..1d03dcdd5e5686bb6e76cb71069607a44d8d4eb2 100644 (file)
@@ -1765,7 +1765,6 @@ static void free_skb_resources(struct gfar_private *priv)
                          sizeof(struct rxbd8) * priv->total_rx_ring_size,
                          priv->tx_queue[0]->tx_bd_base,
                          priv->tx_queue[0]->tx_bd_dma_base);
-       skb_queue_purge(&priv->rx_recycle);
 }
 
 void gfar_start(struct net_device *dev)
@@ -1943,8 +1942,6 @@ static int gfar_enet_open(struct net_device *dev)
 
        enable_napi(priv);
 
-       skb_queue_head_init(&priv->rx_recycle);
-
        /* Initialize a bunch of registers */
        init_registers(dev);
 
@@ -2533,16 +2530,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
 
                bytes_sent += skb->len;
 
-               /* If there's room in the queue (limit it to rx_buffer_size)
-                * we add this skb back into the pool, if it's the right size
-                */
-               if (skb_queue_len(&priv->rx_recycle) < rx_queue->rx_ring_size &&
-                   skb_recycle_check(skb, priv->rx_buffer_size +
-                                     RXBUF_ALIGNMENT)) {
-                       gfar_align_skb(skb);
-                       skb_queue_head(&priv->rx_recycle, skb);
-               } else
-                       dev_kfree_skb_any(skb);
+               dev_kfree_skb_any(skb);
 
                tx_queue->tx_skbuff[skb_dirtytx] = NULL;
 
@@ -2608,7 +2596,7 @@ static void gfar_new_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp,
 static struct sk_buff *gfar_alloc_skb(struct net_device *dev)
 {
        struct gfar_private *priv = netdev_priv(dev);
-       struct sk_buff *skb = NULL;
+       struct sk_buff *skb;
 
        skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT);
        if (!skb)
@@ -2621,14 +2609,7 @@ static struct sk_buff *gfar_alloc_skb(struct net_device *dev)
 
 struct sk_buff *gfar_new_skb(struct net_device *dev)
 {
-       struct gfar_private *priv = netdev_priv(dev);
-       struct sk_buff *skb = NULL;
-
-       skb = skb_dequeue(&priv->rx_recycle);
-       if (!skb)
-               skb = gfar_alloc_skb(dev);
-
-       return skb;
+       return gfar_alloc_skb(dev);
 }
 
 static inline void count_errors(unsigned short status, struct net_device *dev)
@@ -2787,7 +2768,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
                        if (unlikely(!newskb))
                                newskb = skb;
                        else if (skb)
-                               skb_queue_head(&priv->rx_recycle, skb);
+                               dev_kfree_skb(skb);
                } else {
                        /* Increment the number of packets */
                        rx_queue->stats.rx_packets++;
index 4141ef2ddafc3974563b2e16e433d312bd1cb894..22eabc13ca99df900587678c24003167636446d3 100644 (file)
@@ -1080,8 +1080,6 @@ struct gfar_private {
 
        u32 cur_filer_idx;
 
-       struct sk_buff_head rx_recycle;
-
        /* RX queue filer rule set*/
        struct ethtool_rx_list rx_list;
        struct mutex rx_queue_access;
index 164288439220c69f59f755c091afb2c53289c420..0a70bb55d1b0fb624cf4202c855055f5969f5154 100644 (file)
@@ -209,14 +209,12 @@ static struct list_head *dequeue(struct list_head *lh)
 static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth,
                u8 __iomem *bd)
 {
-       struct sk_buff *skb = NULL;
+       struct sk_buff *skb;
 
-       skb = __skb_dequeue(&ugeth->rx_recycle);
+       skb = netdev_alloc_skb(ugeth->ndev,
+                              ugeth->ug_info->uf_info.max_rx_buf_length +
+                              UCC_GETH_RX_DATA_BUF_ALIGNMENT);
        if (!skb)
-               skb = netdev_alloc_skb(ugeth->ndev,
-                                     ugeth->ug_info->uf_info.max_rx_buf_length +
-                                     UCC_GETH_RX_DATA_BUF_ALIGNMENT);
-       if (skb == NULL)
                return NULL;
 
        /* We need the data buffer to be aligned properly.  We will reserve
@@ -2020,8 +2018,6 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
                iounmap(ugeth->ug_regs);
                ugeth->ug_regs = NULL;
        }
-
-       skb_queue_purge(&ugeth->rx_recycle);
 }
 
 static void ucc_geth_set_multi(struct net_device *dev)
@@ -2230,8 +2226,6 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
                return -ENOMEM;
        }
 
-       skb_queue_head_init(&ugeth->rx_recycle);
-
        return 0;
 }
 
@@ -3274,12 +3268,7 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
                        if (netif_msg_rx_err(ugeth))
                                ugeth_err("%s, %d: ERROR!!! skb - 0x%08x",
                                           __func__, __LINE__, (u32) skb);
-                       if (skb) {
-                               skb->data = skb->head + NET_SKB_PAD;
-                               skb->len = 0;
-                               skb_reset_tail_pointer(skb);
-                               __skb_queue_head(&ugeth->rx_recycle, skb);
-                       }
+                       dev_kfree_skb(skb);
 
                        ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = NULL;
                        dev->stats.rx_dropped++;
@@ -3349,13 +3338,7 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
 
                dev->stats.tx_packets++;
 
-               if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN &&
-                            skb_recycle_check(skb,
-                                   ugeth->ug_info->uf_info.max_rx_buf_length +
-                                   UCC_GETH_RX_DATA_BUF_ALIGNMENT))
-                       __skb_queue_head(&ugeth->rx_recycle, skb);
-               else
-                       dev_kfree_skb(skb);
+               dev_kfree_skb(skb);
 
                ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL;
                ugeth->skb_dirtytx[txQ] =
index f71b3e7b12defe7c92489ca967fbfe72819ab382..75f337163ce3c685fab0909516d5cb44055fcfa1 100644 (file)
@@ -1214,8 +1214,6 @@ struct ucc_geth_private {
        /* index of the first skb which hasn't been transmitted yet. */
        u16 skb_dirtytx[NUM_TX_QUEUES];
 
-       struct sk_buff_head rx_recycle;
-
        struct ugeth_mii_info *mii_info;
        struct phy_device *phydev;
        phy_interface_t phy_interface;
index cb3356c9af803509efb2c58ff4f7d0667e689e1c..04668b47a1df1a65f98eef94bea619d7a0c0c71d 100644 (file)
@@ -175,13 +175,13 @@ struct e1000_info;
 /*
  * in the case of WTHRESH, it appears at least the 82571/2 hardware
  * writes back 4 descriptors when WTHRESH=5, and 3 descriptors when
- * WTHRESH=4, and since we want 64 bytes at a time written back, set
- * it to 5
+ * WTHRESH=4, so a setting of 5 gives the most efficient bus
+ * utilization but to avoid possible Tx stalls, set it to 1
  */
 #define E1000_TXDCTL_DMA_BURST_ENABLE                          \
        (E1000_TXDCTL_GRAN | /* set descriptor granularity */  \
         E1000_TXDCTL_COUNT_DESC |                             \
-        (5 << 16) | /* wthresh must be +1 more than desired */\
+        (1 << 16) | /* wthresh must be +1 more than desired */\
         (1 << 8)  | /* hthresh */                             \
         0x1f)       /* pthresh */
 
index ed5b40985edb10ccccbd6c216110e0830d6085f7..d37bfd96c987277980d4ec7b2e2db85f7e1dcf36 100644 (file)
@@ -412,6 +412,8 @@ enum e1e_registers {
 #define E1000_DEV_ID_PCH2_LV_V                 0x1503
 #define E1000_DEV_ID_PCH_LPT_I217_LM           0x153A
 #define E1000_DEV_ID_PCH_LPT_I217_V            0x153B
+#define E1000_DEV_ID_PCH_LPTLP_I218_LM         0x155A
+#define E1000_DEV_ID_PCH_LPTLP_I218_V          0x1559
 
 #define E1000_REVISION_4 4
 
index fb659dd8db038941842e9eb937b94eed8640d98e..f444eb0b76d8d9c0c7147b8dc4a9fa7266d517b9 100644 (file)
@@ -2831,7 +2831,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
                 * set up some performance related parameters to encourage the
                 * hardware to use the bus more efficiently in bursts, depends
                 * on the tx_int_delay to be enabled,
-                * wthresh = 5 ==> burst write a cacheline (64 bytes) at a time
+                * wthresh = 1 ==> burst write is disabled to avoid Tx stalls
                 * hthresh = 1 ==> prefetch when one or more available
                 * pthresh = 0x1f ==> prefetch if internal cache 31 or less
                 * BEWARE: this seems to work but should be considered first if
@@ -6558,6 +6558,8 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
 
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPT_I217_LM), board_pch_lpt },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPT_I217_V), board_pch_lpt },
+       { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPTLP_I218_LM), board_pch_lpt },
+       { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPTLP_I218_V), board_pch_lpt },
 
        { 0, 0, 0, 0, 0, 0, 0 } /* terminate list */
 };
index 5bd26763554c8926282739bf18d308d92c892990..30efc9f0f47a3cea7cf5aee5438b5ad70c208f30 100644 (file)
@@ -410,7 +410,7 @@ static inline u16 ixgbe_desc_unused(struct ixgbe_ring *ring)
 #define IXGBE_TX_CTXTDESC(R, i)            \
        (&(((struct ixgbe_adv_tx_context_desc *)((R)->desc))[i]))
 
-#define IXGBE_MAX_JUMBO_FRAME_SIZE        16128
+#define IXGBE_MAX_JUMBO_FRAME_SIZE     9728 /* Maximum Supported Size 9.5KB */
 #ifdef IXGBE_FCOE
 /* Use 3K as the baby jumbo frame size for FCoE */
 #define IXGBE_FCOE_JUMBO_FRAME_SIZE       3072
index 383b4e1cd17532682c9dfc087d7d9a08a969b81a..4a9c9c285685294df5b5531c689f0e11171056be 100644 (file)
@@ -175,7 +175,7 @@ struct ixgbevf_q_vector {
 #define IXGBEVF_TX_CTXTDESC(R, i)          \
        (&(((struct ixgbe_adv_tx_context_desc *)((R)->desc))[i]))
 
-#define IXGBE_MAX_JUMBO_FRAME_SIZE        16128
+#define IXGBE_MAX_JUMBO_FRAME_SIZE     9728 /* Maximum Supported Size 9.5KB */
 
 #define OTHER_VECTOR 1
 #define NON_Q_VECTORS (OTHER_VECTOR)
index 0ee9bd4819f444b392d087403da514db125af0bd..de1ad506665d6a33c223c8a73fbada54f39df832 100644 (file)
@@ -1747,6 +1747,7 @@ err_tx_ring_allocation:
  **/
 static int ixgbevf_set_interrupt_capability(struct ixgbevf_adapter *adapter)
 {
+       struct net_device *netdev = adapter->netdev;
        int err = 0;
        int vector, v_budget;
 
@@ -1775,6 +1776,12 @@ static int ixgbevf_set_interrupt_capability(struct ixgbevf_adapter *adapter)
 
        ixgbevf_acquire_msix_vectors(adapter, v_budget);
 
+       err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues);
+       if (err)
+               goto out;
+
+       err = netif_set_real_num_rx_queues(netdev, adapter->num_rx_queues);
+
 out:
        return err;
 }
index c911d883c27e6fbd922eab405aa2457db25be782..f8064df10cc4ca1d1c6bcf05b42858ae5c9071fc 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/pci-aspm.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -2973,6 +2974,9 @@ jme_init_one(struct pci_dev *pdev,
        /*
         * set up PCI device basics
         */
+       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+                              PCIE_LINK_STATE_CLKPM);
+
        rc = pci_enable_device(pdev);
        if (rc) {
                pr_err("Cannot enable PCI device\n");
index 087b9e0669f181c5832a3e51d08c0b785ed8134f..84c13263c514c988e44d4335d3ccae0147c220d6 100644 (file)
@@ -412,7 +412,6 @@ struct mv643xx_eth_private {
        u8 work_rx_refill;
 
        int skb_size;
-       struct sk_buff_head rx_recycle;
 
        /*
         * RX state.
@@ -673,9 +672,7 @@ static int rxq_refill(struct rx_queue *rxq, int budget)
                struct rx_desc *rx_desc;
                int size;
 
-               skb = __skb_dequeue(&mp->rx_recycle);
-               if (skb == NULL)
-                       skb = netdev_alloc_skb(mp->dev, mp->skb_size);
+               skb = netdev_alloc_skb(mp->dev, mp->skb_size);
 
                if (skb == NULL) {
                        mp->oom = 1;
@@ -989,14 +986,7 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
                                       desc->byte_cnt, DMA_TO_DEVICE);
                }
 
-               if (skb != NULL) {
-                       if (skb_queue_len(&mp->rx_recycle) <
-                                       mp->rx_ring_size &&
-                           skb_recycle_check(skb, mp->skb_size))
-                               __skb_queue_head(&mp->rx_recycle, skb);
-                       else
-                               dev_kfree_skb(skb);
-               }
+               dev_kfree_skb(skb);
        }
 
        __netif_tx_unlock(nq);
@@ -2349,8 +2339,6 @@ static int mv643xx_eth_open(struct net_device *dev)
 
        napi_enable(&mp->napi);
 
-       skb_queue_head_init(&mp->rx_recycle);
-
        mp->int_mask = INT_EXT;
 
        for (i = 0; i < mp->rxq_count; i++) {
@@ -2445,8 +2433,6 @@ static int mv643xx_eth_stop(struct net_device *dev)
        mib_counters_update(mp);
        del_timer_sync(&mp->mib_counters_timer);
 
-       skb_queue_purge(&mp->rx_recycle);
-
        for (i = 0; i < mp->rxq_count; i++)
                rxq_deinit(mp->rxq + i);
        for (i = 0; i < mp->txq_count; i++)
index 5a30bf823099a00b8c5d230f4d2172775b85c967..9b9c2ac5c4c214d65366782c05d6406a1859cb17 100644 (file)
@@ -3189,7 +3189,7 @@ static int skge_poll(struct napi_struct *napi, int to_do)
        if (work_done < to_do) {
                unsigned long flags;
 
-               napi_gro_flush(napi);
+               napi_gro_flush(napi, false);
                spin_lock_irqsave(&hw->hw_lock, flags);
                __napi_complete(napi);
                hw->intr_mask |= napimask[skge->port];
@@ -3945,8 +3945,10 @@ static int __devinit skge_probe(struct pci_dev *pdev,
                skge_board_name(hw), hw->chip_rev);
 
        dev = skge_devinit(hw, 0, using_dac);
-       if (!dev)
+       if (!dev) {
+               err = -ENOMEM;
                goto err_out_led_off;
+       }
 
        /* Some motherboards are broken and has zero in ROM. */
        if (!is_valid_ether_addr(dev->dev_addr))
@@ -4153,6 +4155,13 @@ static struct dmi_system_id skge_32bit_dma_boards[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "nForce"),
                },
        },
+       {
+               .ident = "ASUS P5NSLI",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+                       DMI_MATCH(DMI_BOARD_NAME, "P5NSLI")
+               },
+       },
        {}
 };
 
index 2b0748dba8b874544c935df9b7ba224141b1a2b3..78946feab4a2de4c187138d02c01418cf8b4fb6f 100644 (file)
@@ -4924,6 +4924,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
 
        if (~reg == 0) {
                dev_err(&pdev->dev, "PCI configuration read error\n");
+               err = -EIO;
                goto err_out;
        }
 
@@ -4993,8 +4994,10 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
        hw->st_size = hw->ports * roundup_pow_of_two(3*RX_MAX_PENDING + TX_MAX_PENDING);
        hw->st_le = pci_alloc_consistent(pdev, hw->st_size * sizeof(struct sky2_status_le),
                                         &hw->st_dma);
-       if (!hw->st_le)
+       if (!hw->st_le) {
+               err = -ENOMEM;
                goto err_out_reset;
+       }
 
        dev_info(&pdev->dev, "Yukon-2 %s chip revision %d\n",
                 sky2_name(hw->chip_id, buf1, sizeof(buf1)), hw->chip_rev);
index 5b61d12f8b91127a3439de1ad71ae6d7b27e6e2c..dbaaa99a0d43fb81f14f7d3a4c6c8b2f3caabd80 100644 (file)
@@ -947,8 +947,8 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
        i = register_netdev(dev);
        if (i)
                goto err_register_netdev;
-
-       if (NATSEMI_CREATE_FILE(pdev, dspcfg_workaround))
+       i = NATSEMI_CREATE_FILE(pdev, dspcfg_workaround);
+       if (i)
                goto err_create_file;
 
        if (netif_msg_drv(np)) {
index e01c0a07a93ac15f490021b34e321f64433537b6..7dfe88398d7d3937cd6f308fb6d08b6943ee58d5 100644 (file)
@@ -205,6 +205,7 @@ static int __init sonic_probe1(struct net_device *dev)
        if (lp->descriptors == NULL) {
                printk(KERN_ERR "%s: couldn't alloc DMA memory for "
                                " descriptors.\n", dev_name(lp->device));
+               err = -ENOMEM;
                goto out;
        }
 
index 97302419a377e82021e4ccb7330a210504db0f48..5296cc8d3cbaaf2dc20994a71a200b2d6e547cb7 100644 (file)
@@ -26,6 +26,9 @@ if PCH_GBE
 config PCH_PTP
        bool "PCH PTP clock support"
        default n
+       depends on EXPERIMENTAL
+       select PPS
+       select PTP_1588_CLOCK
        select PTP_1588_CLOCK_PCH
        ---help---
          Say Y here if you want to use Precision Time Protocol (PTP) in the
index 473ce134ca63d83c42ac115be60ca6e32aec04dc..24ad17ec7fcde46a6f11491873546f8ffbb3cef2 100644 (file)
@@ -1601,7 +1601,8 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        adapter->netdev  = netdev;
        adapter->pdev    = pdev;
 
-       if (qlcnic_alloc_adapter_resources(adapter))
+       err = qlcnic_alloc_adapter_resources(adapter);
+       if (err)
                goto err_out_free_netdev;
 
        adapter->dev_rst_time = jiffies;
index 995d0cfc4c065658ad47279a3705beb27b8c43f0..1c818254b7bec650da02fc352625570a3937b6f8 100644 (file)
@@ -563,7 +563,7 @@ rx_next:
                if (cpr16(IntrStatus) & cp_rx_intr_mask)
                        goto rx_status_loop;
 
-               napi_gro_flush(napi);
+               napi_gro_flush(napi, false);
                spin_lock_irqsave(&cp->lock, flags);
                __napi_complete(napi);
                cpw16_f(IntrMask, cp_intr_mask);
index bad8f2eec9b46f652298a3d9f0b48edbef1ac6b8..c8bfea0524dd304408642b5df86c3119d7a6a65c 100644 (file)
@@ -2438,6 +2438,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
                rtsu = platform_get_resource(pdev, IORESOURCE_MEM, 1);
                if (!rtsu) {
                        dev_err(&pdev->dev, "Not found TSU resource\n");
+                       ret = -ENODEV;
                        goto out_release;
                }
                mdp->tsu_addr = ioremap(rtsu->start,
index 5b3dd028ce852a267833254bf4c5f28fcf9acf7e..0767043f44a42866d545a8ff843604a3d717af48 100644 (file)
@@ -640,8 +640,7 @@ static void efx_ptp_drop_time_expired_events(struct efx_nic *efx)
                        evt = list_entry(cursor, struct efx_ptp_event_rx,
                                         link);
                        if (time_after(jiffies, evt->expiry)) {
-                               list_del(&evt->link);
-                               list_add(&evt->link, &ptp->evt_free_list);
+                               list_move(&evt->link, &ptp->evt_free_list);
                                netif_warn(efx, hw, efx->net_dev,
                                           "PTP rx event dropped\n");
                        }
@@ -684,8 +683,7 @@ static enum ptp_packet_state efx_ptp_match_rx(struct efx_nic *efx,
 
                        match->state = PTP_PACKET_STATE_MATCHED;
                        rc = PTP_PACKET_STATE_MATCHED;
-                       list_del(&evt->link);
-                       list_add(&evt->link, &ptp->evt_free_list);
+                       list_move(&evt->link, &ptp->evt_free_list);
                        break;
                }
        }
@@ -820,8 +818,7 @@ static int efx_ptp_stop(struct efx_nic *efx)
        /* Drop any pending receive events */
        spin_lock_bh(&efx->ptp_data->evt_lock);
        list_for_each_safe(cursor, next, &efx->ptp_data->evt_list) {
-               list_del(cursor);
-               list_add(cursor, &efx->ptp_data->evt_free_list);
+               list_move(cursor, &efx->ptp_data->evt_free_list);
        }
        spin_unlock_bh(&efx->ptp_data->evt_lock);
 
index 203d9c6ec23a109cd9f941d2709257a2058930a4..fb9f6b38511f97beddbff380c2ae7d31878e4ff4 100644 (file)
@@ -478,8 +478,10 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
 
        /* IO region. */
        ioaddr = pci_iomap(pci_dev, 0, 0);
-       if (!ioaddr)
+       if (!ioaddr) {
+               ret = -ENOMEM;
                goto err_out_cleardev;
+       }
 
        sis_priv = netdev_priv(net_dev);
        sis_priv->ioaddr = ioaddr;
index e872e1da3137cef68265e845188bb8544acb988e..7d51a65ab09960ac34baa8baa0b2a3a640a9dfc5 100644 (file)
@@ -50,7 +50,6 @@ struct stmmac_priv {
        unsigned int dirty_rx;
        struct sk_buff **rx_skbuff;
        dma_addr_t *rx_skbuff_dma;
-       struct sk_buff_head rx_recycle;
 
        struct net_device *dev;
        dma_addr_t dma_rx_phy;
index 3be88331d17ab0e690b71f06b2ac30f50d7a7f77..c6cdbc4eb05e613cd499cc35af4ee56300cafcf8 100644 (file)
@@ -747,18 +747,7 @@ static void stmmac_tx(struct stmmac_priv *priv)
                priv->hw->ring->clean_desc3(p);
 
                if (likely(skb != NULL)) {
-                       /*
-                        * If there's room in the queue (limit it to size)
-                        * we add this skb back into the pool,
-                        * if it's the right size.
-                        */
-                       if ((skb_queue_len(&priv->rx_recycle) <
-                               priv->dma_rx_size) &&
-                               skb_recycle_check(skb, priv->dma_buf_sz))
-                               __skb_queue_head(&priv->rx_recycle, skb);
-                       else
-                               dev_kfree_skb(skb);
-
+                       dev_kfree_skb(skb);
                        priv->tx_skbuff[entry] = NULL;
                }
 
@@ -1169,7 +1158,6 @@ static int stmmac_open(struct net_device *dev)
        priv->eee_enabled = stmmac_eee_init(priv);
 
        napi_enable(&priv->napi);
-       skb_queue_head_init(&priv->rx_recycle);
        netif_start_queue(dev);
 
        return 0;
@@ -1222,7 +1210,6 @@ static int stmmac_release(struct net_device *dev)
                kfree(priv->tm);
 #endif
        napi_disable(&priv->napi);
-       skb_queue_purge(&priv->rx_recycle);
 
        /* Free the IRQ lines */
        free_irq(dev->irq, dev);
@@ -1388,10 +1375,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
                if (likely(priv->rx_skbuff[entry] == NULL)) {
                        struct sk_buff *skb;
 
-                       skb = __skb_dequeue(&priv->rx_recycle);
-                       if (skb == NULL)
-                               skb = netdev_alloc_skb_ip_align(priv->dev,
-                                                               bfsize);
+                       skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
 
                        if (unlikely(skb == NULL))
                                break;
index 8419bf385e08b89633948c237e4cce6821e40e77..275b430aeb75daebc70cdaeec7695954168d6a04 100644 (file)
@@ -9788,6 +9788,7 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev,
 
        if (!pci_is_pcie(pdev)) {
                dev_err(&pdev->dev, "Cannot find PCI Express capability, aborting\n");
+               err = -ENODEV;
                goto err_out_free_res;
        }
 
index 9ae12d0c963212b332bd0a69e35e134dad560ab1..6c8695ec7cb9846fc0a53bbff830ce839fa95a21 100644 (file)
@@ -2963,7 +2963,8 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
                goto err_out_iounmap;
        }
 
-       if (gem_get_device_address(gp))
+       err = gem_get_device_address(gp);
+       if (err)
                goto err_out_free_consistent;
 
        dev->netdev_ops = &gem_netdev_ops;
index 30087ca23a0fc7e6c33c75fcb80f020aae42186c..6e4d4b62c9a849326edae6598611328b110233be 100644 (file)
@@ -459,8 +459,10 @@ static int irtty_open(struct tty_struct *tty)
 
        /* allocate private device info block */
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv)
+       if (!priv) {
+               ret = -ENOMEM;
                goto out_put;
+       }
 
        priv->magic = IRTTY_MAGIC;
        priv->tty = tty;
index 1a00b5990cb8a0ec7beec4e5f6efe24b591cb263..f07c340990da570303a25a0e44cbf7ca4b21efa8 100644 (file)
@@ -920,8 +920,10 @@ static int mcs_probe(struct usb_interface *intf,
 
        ndev->netdev_ops = &mcs_netdev_ops;
 
-       if (!intf->cur_altsetting)
+       if (!intf->cur_altsetting) {
+               ret = -ENOMEM;
                goto error2;
+       }
 
        ret = mcs_find_endpoints(mcs, intf->cur_altsetting->endpoint,
                                 intf->cur_altsetting->desc.bNumEndpoints);
index 002a442bf73fab057bb74ba2d2509b421abd5fe6..858de05bdb7dc171012374ac02998c1fd111349c 100644 (file)
@@ -846,8 +846,10 @@ static int pxa_irda_probe(struct platform_device *pdev)
                goto err_mem_2;
 
        dev = alloc_irdadev(sizeof(struct pxa_irda));
-       if (!dev)
+       if (!dev) {
+               err = -ENOMEM;
                goto err_mem_3;
+       }
 
        SET_NETDEV_DEV(dev, &pdev->dev);
        si = netdev_priv(dev);
index e25067552b209327763da3f381a41e85be5e22a2..42fde9ed23e153fbb8f7e3295fca7e81da23a626 100644 (file)
@@ -940,8 +940,10 @@ static int sa1100_irda_probe(struct platform_device *pdev)
                goto err_mem_3;
 
        dev = alloc_irdadev(sizeof(struct sa1100_irda));
-       if (!dev)
+       if (!dev) {
+               err = -ENOMEM;
                goto err_mem_4;
+       }
 
        SET_NETDEV_DEV(dev, &pdev->dev);
 
index eb315b8d07a3c448822dabe8a0df5dfae3dcc13f..4b746d9bd8e7e74b227e0ea6bea63193c9942c21 100644 (file)
@@ -808,8 +808,8 @@ static int __devinit sh_irda_probe(struct platform_device *pdev)
                goto err_mem_4;
 
        platform_set_drvdata(pdev, ndev);
-
-       if (request_irq(irq, sh_irda_irq, IRQF_DISABLED, "sh_irda", self)) {
+       err = request_irq(irq, sh_irda_irq, IRQF_DISABLED, "sh_irda", self);
+       if (err) {
                dev_warn(&pdev->dev, "Unable to attach sh_irda interrupt\n");
                goto err_mem_4;
        }
index 795109425568623977428b1a62bffc7d11c6fa14..624ac1939e857a90a71d66d6dd22e5bddffe71f9 100644 (file)
@@ -741,6 +741,7 @@ static int __devinit sh_sir_probe(struct platform_device *pdev)
        self->clk = clk_get(&pdev->dev, clk_name);
        if (IS_ERR(self->clk)) {
                dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
+               err = -ENODEV;
                goto err_mem_3;
        }
 
@@ -760,8 +761,8 @@ static int __devinit sh_sir_probe(struct platform_device *pdev)
                goto err_mem_4;
 
        platform_set_drvdata(pdev, ndev);
-
-       if (request_irq(irq, sh_sir_irq, IRQF_DISABLED, "sh_sir", self)) {
+       err = request_irq(irq, sh_sir_irq, IRQF_DISABLED, "sh_sir", self);
+       if (err) {
                dev_warn(&pdev->dev, "Unable to attach sh_sir interrupt\n");
                goto err_mem_4;
        }
index 170eb411ab5d92dceb1b302a4a3eb3a159dd8c69..c1ef3000ea6065a9c394ae1fef99e0fa76bd852f 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/of_device.h>
+#include <linux/of_mdio.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
index 434d5af8e6fba0bdddcf6245945f7d3cfbb40c6c..c81e278629ff8595b6e246878e805ed51874a5c7 100644 (file)
@@ -244,8 +244,12 @@ static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                         *  - suspend: peripheral ready to suspend
                         *  - response: suggest N millisec polling
                         *  - response complete: suggest N sec polling
+                        *
+                        * Suspend is reported and maybe heeded.
                         */
                        case 2:         /* Suspend hint */
+                               usbnet_device_suggests_idle(dev);
+                               continue;
                        case 3:         /* Response hint */
                        case 4:         /* Response complete hint */
                                continue;
index c75e11e1b385f3f5654605959b1a6db5ba44641a..afb117c16d2d3688b62952ec2251f29c29eee06c 100644 (file)
@@ -424,7 +424,7 @@ static int kaweth_download_firmware(struct kaweth_device *kaweth,
 
        netdev_dbg(kaweth->net,
                   "Downloading firmware at %p to kaweth device at %p\n",
-                  fw->data, kaweth);
+                  kaweth->firmware_buf, kaweth);
        netdev_dbg(kaweth->net, "Firmware length: %d\n", data_len);
 
        return kaweth_control(kaweth,
index 03c2d8d653df1afa52ee90744f0b33ec4d7baec5..cc7e72010ac383f1d0981302df50dc7f388ab40c 100644 (file)
@@ -117,6 +117,7 @@ enum {
 struct mcs7830_data {
        u8 multi_filter[8];
        u8 config;
+       u8 link_counter;
 };
 
 static const char driver_name[] = "MOSCHIP usb-ethernet driver";
@@ -632,20 +633,31 @@ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 static void mcs7830_status(struct usbnet *dev, struct urb *urb)
 {
        u8 *buf = urb->transfer_buffer;
-       bool link;
+       bool link, link_changed;
+       struct mcs7830_data *data = mcs7830_get_data(dev);
 
        if (urb->actual_length < 16)
                return;
 
        link = !(buf[1] & 0x20);
-       if (netif_carrier_ok(dev->net) != link) {
-               if (link) {
-                       netif_carrier_on(dev->net);
-                       usbnet_defer_kevent(dev, EVENT_LINK_RESET);
-               } else
-                       netif_carrier_off(dev->net);
-               netdev_dbg(dev->net, "Link Status is: %d\n", link);
-       }
+       link_changed = netif_carrier_ok(dev->net) != link;
+       if (link_changed) {
+               data->link_counter++;
+               /*
+                  track link state 20 times to guard against erroneous
+                  link state changes reported sometimes by the chip
+                */
+               if (data->link_counter > 20) {
+                       data->link_counter = 0;
+                       if (link) {
+                               netif_carrier_on(dev->net);
+                               usbnet_defer_kevent(dev, EVENT_LINK_RESET);
+                       } else
+                               netif_carrier_off(dev->net);
+                       netdev_dbg(dev->net, "Link Status is: %d\n", link);
+               }
+       } else
+               data->link_counter = 0;
 }
 
 static const struct driver_info moschip_info = {
index fc9f578a1e253a781b9406b1e4a43ed2de2688d1..f9819d10b1f9d41f864dc710e6799ffed9f9d5f0 100644 (file)
@@ -1588,10 +1588,27 @@ int usbnet_resume (struct usb_interface *intf)
                        tasklet_schedule (&dev->bh);
                }
        }
+
+       if (test_and_clear_bit(EVENT_DEVICE_REPORT_IDLE, &dev->flags))
+               usb_autopm_get_interface_no_resume(intf);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(usbnet_resume);
 
+/*
+ * Either a subdriver implements manage_power, then it is assumed to always
+ * be ready to be suspended or it reports the readiness to be suspended
+ * explicitly
+ */
+void usbnet_device_suggests_idle(struct usbnet *dev)
+{
+       if (!test_and_set_bit(EVENT_DEVICE_REPORT_IDLE, &dev->flags)) {
+               dev->intf->needs_remote_wakeup = 1;
+               usb_autopm_put_interface_async(dev->intf);
+       }
+}
+EXPORT_SYMBOL(usbnet_device_suggests_idle);
 
 /*-------------------------------------------------------------------------*/
 
index 51de9edb55f55d7eca5fe9a9956632ca5c403452..607976c001626a75afbf590411bf6ec1bbff26c0 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/igmp.h>
 #include <linux/etherdevice.h>
 #include <linux/if_ether.h>
-#include <linux/version.h>
 #include <linux/hash.h>
 #include <net/ip.h>
 #include <net/icmp.h>
@@ -107,6 +106,8 @@ struct vxlan_dev {
        __be32            gaddr;        /* multicast group */
        __be32            saddr;        /* source address */
        unsigned int      link;         /* link to multicast over */
+       __u16             port_min;     /* source port range */
+       __u16             port_max;
        __u8              tos;          /* TOS override */
        __u8              ttl;
        bool              learn;
@@ -229,9 +230,9 @@ static u32 eth_hash(const unsigned char *addr)
 
        /* only want 6 bytes */
 #ifdef __BIG_ENDIAN
-       value <<= 16;
-#else
        value >>= 16;
+#else
+       value <<= 16;
 #endif
        return hash_64(value, FDB_HASH_BITS);
 }
@@ -536,7 +537,6 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
        }
 
        __skb_pull(skb, sizeof(struct vxlanhdr));
-       skb_postpull_rcsum(skb, eth_hdr(skb), sizeof(struct vxlanhdr));
 
        /* Is this VNI defined? */
        vni = ntohl(vxh->vx_vni) >> 8;
@@ -555,7 +555,6 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
        /* Re-examine inner Ethernet packet */
        oip = ip_hdr(skb);
        skb->protocol = eth_type_trans(skb, vxlan->dev);
-       skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
 
        /* Ignore packet loops (and multicast echo) */
        if (compare_ether_addr(eth_hdr(skb)->h_source,
@@ -567,6 +566,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 
        __skb_tunnel_rx(skb, vxlan->dev);
        skb_reset_network_header(skb);
+       skb->ip_summed = CHECKSUM_NONE;
 
        err = IP_ECN_decapsulate(oip, skb);
        if (unlikely(err)) {
@@ -622,46 +622,89 @@ static inline u8 vxlan_ecn_encap(u8 tos,
        return INET_ECN_encapsulate(tos, inner);
 }
 
+static __be32 vxlan_find_dst(struct vxlan_dev *vxlan, struct sk_buff *skb)
+{
+       const struct ethhdr *eth = (struct ethhdr *) skb->data;
+       const struct vxlan_fdb *f;
+
+       if (is_multicast_ether_addr(eth->h_dest))
+               return vxlan->gaddr;
+
+       f = vxlan_find_mac(vxlan, eth->h_dest);
+       if (f)
+               return f->remote_ip;
+       else
+               return vxlan->gaddr;
+
+}
+
+static void vxlan_sock_free(struct sk_buff *skb)
+{
+       sock_put(skb->sk);
+}
+
+/* On transmit, associate with the tunnel socket */
+static void vxlan_set_owner(struct net_device *dev, struct sk_buff *skb)
+{
+       struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
+       struct sock *sk = vn->sock->sk;
+
+       skb_orphan(skb);
+       sock_hold(sk);
+       skb->sk = sk;
+       skb->destructor = vxlan_sock_free;
+}
+
+/* Compute source port for outgoing packet
+ *   first choice to use L4 flow hash since it will spread
+ *     better and maybe available from hardware
+ *   secondary choice is to use jhash on the Ethernet header
+ */
+static u16 vxlan_src_port(const struct vxlan_dev *vxlan, struct sk_buff *skb)
+{
+       unsigned int range = (vxlan->port_max - vxlan->port_min) + 1;
+       u32 hash;
+
+       hash = skb_get_rxhash(skb);
+       if (!hash)
+               hash = jhash(skb->data, 2 * ETH_ALEN,
+                            (__force u32) skb->protocol);
+
+       return (((u64) hash * range) >> 32) + vxlan->port_min;
+}
+
 /* Transmit local packets over Vxlan
  *
  * Outer IP header inherits ECN and DF from inner header.
  * Outer UDP destination is the VXLAN assigned port.
- *           source port is based on hash of flow if available
- *                       otherwise use a random value
+ *           source port is based on hash of flow
  */
 static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct vxlan_dev *vxlan = netdev_priv(dev);
        struct rtable *rt;
-       const struct ethhdr *eth;
        const struct iphdr *old_iph;
        struct iphdr *iph;
        struct vxlanhdr *vxh;
        struct udphdr *uh;
        struct flowi4 fl4;
-       struct vxlan_fdb *f;
        unsigned int pkt_len = skb->len;
-       u32 hash;
        __be32 dst;
+       __u16 src_port;
        __be16 df = 0;
        __u8 tos, ttl;
        int err;
 
+       dst = vxlan_find_dst(vxlan, skb);
+       if (!dst)
+               goto drop;
+
        /* Need space for new headers (invalidates iph ptr) */
        if (skb_cow_head(skb, VXLAN_HEADROOM))
                goto drop;
 
-       eth = (void *)skb->data;
        old_iph = ip_hdr(skb);
 
-       if (!is_multicast_ether_addr(eth->h_dest) &&
-           (f = vxlan_find_mac(vxlan, eth->h_dest)))
-               dst = f->remote_ip;
-       else if (vxlan->gaddr) {
-               dst = vxlan->gaddr;
-       } else
-               goto drop;
-
        ttl = vxlan->ttl;
        if (!ttl && IN_MULTICAST(ntohl(dst)))
                ttl = 1;
@@ -670,11 +713,15 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
        if (tos == 1)
                tos = vxlan_get_dsfield(old_iph, skb);
 
-       hash = skb_get_rxhash(skb);
+       src_port = vxlan_src_port(vxlan, skb);
+
+       memset(&fl4, 0, sizeof(fl4));
+       fl4.flowi4_oif = vxlan->link;
+       fl4.flowi4_tos = RT_TOS(tos);
+       fl4.daddr = dst;
+       fl4.saddr = vxlan->saddr;
 
-       rt = ip_route_output_gre(dev_net(dev), &fl4, dst,
-                                vxlan->saddr, vxlan->vni,
-                                RT_TOS(tos), vxlan->link);
+       rt = ip_route_output_key(dev_net(dev), &fl4);
        if (IS_ERR(rt)) {
                netdev_dbg(dev, "no route to %pI4\n", &dst);
                dev->stats.tx_carrier_errors++;
@@ -703,7 +750,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
        uh = udp_hdr(skb);
 
        uh->dest = htons(vxlan_port);
-       uh->source = hash ? :random32();
+       uh->source = htons(src_port);
 
        uh->len = htons(skb->len);
        uh->check = 0;
@@ -716,10 +763,12 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
        iph->frag_off   = df;
        iph->protocol   = IPPROTO_UDP;
        iph->tos        = vxlan_ecn_encap(tos, old_iph, skb);
-       iph->daddr      = fl4.daddr;
+       iph->daddr      = dst;
        iph->saddr      = fl4.saddr;
        iph->ttl        = ttl ? : ip4_dst_hoplimit(&rt->dst);
 
+       vxlan_set_owner(dev, skb);
+
        /* See __IPTUNNEL_XMIT */
        skb->ip_summed = CHECKSUM_NONE;
        ip_select_ident(iph, &rt->dst, NULL);
@@ -929,9 +978,11 @@ static void vxlan_setup(struct net_device *dev)
 {
        struct vxlan_dev *vxlan = netdev_priv(dev);
        unsigned h;
+       int low, high;
 
        eth_hw_addr_random(dev);
        ether_setup(dev);
+       dev->hard_header_len = ETH_HLEN + VXLAN_HEADROOM;
 
        dev->netdev_ops = &vxlan_netdev_ops;
        dev->destructor = vxlan_free;
@@ -948,6 +999,10 @@ static void vxlan_setup(struct net_device *dev)
        vxlan->age_timer.function = vxlan_cleanup;
        vxlan->age_timer.data = (unsigned long) vxlan;
 
+       inet_get_local_port_range(&low, &high);
+       vxlan->port_min = low;
+       vxlan->port_max = high;
+
        vxlan->dev = dev;
 
        for (h = 0; h < FDB_HASH_SIZE; ++h)
@@ -964,6 +1019,7 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
        [IFLA_VXLAN_LEARNING]   = { .type = NLA_U8 },
        [IFLA_VXLAN_AGEING]     = { .type = NLA_U32 },
        [IFLA_VXLAN_LIMIT]      = { .type = NLA_U32 },
+       [IFLA_VXLAN_PORT_RANGE] = { .len  = sizeof(struct ifla_vxlan_port_range) },
 };
 
 static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -996,6 +1052,18 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
                        return -EADDRNOTAVAIL;
                }
        }
+
+       if (data[IFLA_VXLAN_PORT_RANGE]) {
+               const struct ifla_vxlan_port_range *p
+                       = nla_data(data[IFLA_VXLAN_PORT_RANGE]);
+
+               if (ntohs(p->high) < ntohs(p->low)) {
+                       pr_debug("port range %u .. %u not valid\n",
+                                ntohs(p->low), ntohs(p->high));
+                       return -EINVAL;
+               }
+       }
+
        return 0;
 }
 
@@ -1022,14 +1090,18 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
        if (data[IFLA_VXLAN_LOCAL])
                vxlan->saddr = nla_get_be32(data[IFLA_VXLAN_LOCAL]);
 
-       if (data[IFLA_VXLAN_LINK]) {
-               vxlan->link = nla_get_u32(data[IFLA_VXLAN_LINK]);
+       if (data[IFLA_VXLAN_LINK] &&
+           (vxlan->link = nla_get_u32(data[IFLA_VXLAN_LINK]))) {
+               struct net_device *lowerdev
+                        = __dev_get_by_index(net, vxlan->link);
 
-               if (!tb[IFLA_MTU]) {
-                       struct net_device *lowerdev;
-                       lowerdev = __dev_get_by_index(net, vxlan->link);
-                       dev->mtu = lowerdev->mtu - VXLAN_HEADROOM;
+               if (!lowerdev) {
+                       pr_info("ifindex %d does not exist\n", vxlan->link);
+                       return -ENODEV;
                }
+
+               if (!tb[IFLA_MTU])
+                       dev->mtu = lowerdev->mtu - VXLAN_HEADROOM;
        }
 
        if (data[IFLA_VXLAN_TOS])
@@ -1046,6 +1118,13 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
        if (data[IFLA_VXLAN_LIMIT])
                vxlan->addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]);
 
+       if (data[IFLA_VXLAN_PORT_RANGE]) {
+               const struct ifla_vxlan_port_range *p
+                       = nla_data(data[IFLA_VXLAN_PORT_RANGE]);
+               vxlan->port_min = ntohs(p->low);
+               vxlan->port_max = ntohs(p->high);
+       }
+
        err = register_netdevice(dev);
        if (!err)
                hlist_add_head_rcu(&vxlan->hlist, vni_head(net, vxlan->vni));
@@ -1074,23 +1153,28 @@ static size_t vxlan_get_size(const struct net_device *dev)
                nla_total_size(sizeof(__u8)) +  /* IFLA_VXLAN_LEARNING */
                nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_AGEING */
                nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LIMIT */
+               nla_total_size(sizeof(struct ifla_vxlan_port_range)) +
                0;
 }
 
 static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
        const struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct ifla_vxlan_port_range ports = {
+               .low =  htons(vxlan->port_min),
+               .high = htons(vxlan->port_max),
+       };
 
        if (nla_put_u32(skb, IFLA_VXLAN_ID, vxlan->vni))
                goto nla_put_failure;
 
-       if (vxlan->gaddr && nla_put_u32(skb, IFLA_VXLAN_GROUP, vxlan->gaddr))
+       if (vxlan->gaddr && nla_put_be32(skb, IFLA_VXLAN_GROUP, vxlan->gaddr))
                goto nla_put_failure;
 
        if (vxlan->link && nla_put_u32(skb, IFLA_VXLAN_LINK, vxlan->link))
                goto nla_put_failure;
 
-       if (vxlan->saddr && nla_put_u32(skb, IFLA_VXLAN_LOCAL, vxlan->saddr))
+       if (vxlan->saddr && nla_put_be32(skb, IFLA_VXLAN_LOCAL, vxlan->saddr))
                goto nla_put_failure;
 
        if (nla_put_u8(skb, IFLA_VXLAN_TTL, vxlan->ttl) ||
@@ -1100,6 +1184,9 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
            nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->addrmax))
                goto nla_put_failure;
 
+       if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports))
+               goto nla_put_failure;
+
        return 0;
 
 nla_put_failure:
index 1a623183cbe54d63f8392f924953b127ded83c1f..b6271325f8035c33ebaabf5e172f9ef9725780ba 100644 (file)
@@ -597,7 +597,7 @@ fst_q_work_item(u64 * queue, int card_index)
         * bottom half for the card.  Note the limitation of 64 cards.
         * That ought to be enough
         */
-       mask = 1 << card_index;
+       mask = (u64)1 << card_index;
        *queue |= mask;
        spin_unlock_irqrestore(&fst_work_q_lock, flags);
 }
index 9fd6d9a9942ec298b81be9a8e62697df1d13c037..9f31cfa56cc092cfb9dca9647b3ef7aad62175c4 100644 (file)
@@ -1804,7 +1804,7 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
        int ret;
        struct ath5k_hw *ah = hw->priv;
-       struct ath5k_vif *avf = (void *)vif->drv_priv;
+       struct ath5k_vif *avf;
        struct sk_buff *skb;
 
        if (WARN_ON(!vif)) {
@@ -1819,6 +1819,7 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
                goto out;
        }
 
+       avf = (void *)vif->drv_priv;
        ath5k_txbuf_free_skb(ah, avf->bbuf);
        avf->bbuf->skb = skb;
        ret = ath5k_beacon_setup(ah, avf->bbuf);
index 76f07d8c272d1dc951dfe23e4a4a8a3cc58aa14b..1b48414dca95d919a3c66dc6c760ce0b7338abdc 100644 (file)
@@ -120,7 +120,7 @@ static void ath9k_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
 
        if (ath_tx_start(hw, skb, &txctl) != 0) {
                ath_dbg(common, XMIT, "CABQ TX failed\n");
-               dev_kfree_skb_any(skb);
+               ieee80211_free_txskb(hw, skb);
        }
 }
 
index f9a6ec5cf4704818a6da783338ada8e3e737c759..8e1559aba495a0bd7447ac2c79703d49caf70abd 100644 (file)
@@ -1450,9 +1450,14 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
        REG_WRITE(ah, AR_RTC_FORCE_WAKE,
                  AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
 
+       if (!ah->reset_power_on)
+               type = ATH9K_RESET_POWER_ON;
+
        switch (type) {
        case ATH9K_RESET_POWER_ON:
                ret = ath9k_hw_set_reset_power_on(ah);
+               if (!ret)
+                       ah->reset_power_on = true;
                break;
        case ATH9K_RESET_WARM:
        case ATH9K_RESET_COLD:
index 566a4ce4f156e8200c29fa4e71da7376a7e1df5d..dbc1b7a4cbfdc0eeca59efa19f4d52e7e09044ec 100644 (file)
@@ -741,6 +741,7 @@ struct ath_hw {
        u32 rfkill_polarity;
        u32 ah_flags;
 
+       bool reset_power_on;
        bool htc_reset_init;
 
        enum nl80211_iftype opmode;
index 31ab82e3ba85fdee932f1c8b2037c262037b1f24..dd45edfa6baec25304af0a07ccea22f1c0910f29 100644 (file)
@@ -639,8 +639,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
                ath_err(common,
                        "Unable to reset hardware; reset status %d (freq %u MHz)\n",
                        r, curchan->center_freq);
-               spin_unlock_bh(&sc->sc_pcu_lock);
-               goto mutex_unlock;
+               ah->reset_power_on = false;
        }
 
        /* Setup our intr mask. */
@@ -665,11 +664,8 @@ static int ath9k_start(struct ieee80211_hw *hw)
        clear_bit(SC_OP_INVALID, &sc->sc_flags);
        sc->sc_ah->is_monitoring = false;
 
-       if (!ath_complete_reset(sc, false)) {
-               r = -EIO;
-               spin_unlock_bh(&sc->sc_pcu_lock);
-               goto mutex_unlock;
-       }
+       if (!ath_complete_reset(sc, false))
+               ah->reset_power_on = false;
 
        if (ah->led_pin >= 0) {
                ath9k_hw_cfg_output(ah, ah->led_pin,
@@ -688,12 +684,11 @@ static int ath9k_start(struct ieee80211_hw *hw)
        if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
                common->bus_ops->extn_synch_en(common);
 
-mutex_unlock:
        mutex_unlock(&sc->mutex);
 
        ath9k_ps_restore(sc);
 
-       return r;
+       return 0;
 }
 
 static void ath9k_tx(struct ieee80211_hw *hw,
@@ -770,7 +765,7 @@ static void ath9k_tx(struct ieee80211_hw *hw,
 
        return;
 exit:
-       dev_kfree_skb_any(skb);
+       ieee80211_free_txskb(hw, skb);
 }
 
 static void ath9k_stop(struct ieee80211_hw *hw)
index 0e630a99b68b8fa729af6007de32e97d16c7f6ff..f088f4bf9a26a0802ca4526dce91b48213fdd09f 100644 (file)
@@ -324,6 +324,10 @@ static int ath_pci_suspend(struct device *device)
 static int ath_pci_resume(struct device *device)
 {
        struct pci_dev *pdev = to_pci_dev(device);
+       struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
        u32 val;
 
        /*
@@ -335,6 +339,9 @@ static int ath_pci_resume(struct device *device)
        if ((val & 0x0000ff00) != 0)
                pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
 
+       ath_pci_aspm_init(common);
+       ah->reset_power_on = false;
+
        return 0;
 }
 
index 36618e3a5e609831184b973e30b3a9aa739522f3..378bd70256b2c7b8ad6358b2488919198dc42950 100644 (file)
@@ -66,8 +66,7 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
 static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
                                           struct ath_txq *txq,
                                           struct ath_atx_tid *tid,
-                                          struct sk_buff *skb,
-                                          bool dequeue);
+                                          struct sk_buff *skb);
 
 enum {
        MCS_HT20,
@@ -176,7 +175,15 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
                fi = get_frame_info(skb);
                bf = fi->bf;
 
-               if (bf && fi->retries) {
+               if (!bf) {
+                       bf = ath_tx_setup_buffer(sc, txq, tid, skb);
+                       if (!bf) {
+                               ieee80211_free_txskb(sc->hw, skb);
+                               continue;
+                       }
+               }
+
+               if (fi->retries) {
                        list_add_tail(&bf->list, &bf_head);
                        ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
                        ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
@@ -785,10 +792,13 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
                fi = get_frame_info(skb);
                bf = fi->bf;
                if (!fi->bf)
-                       bf = ath_tx_setup_buffer(sc, txq, tid, skb, true);
+                       bf = ath_tx_setup_buffer(sc, txq, tid, skb);
 
-               if (!bf)
+               if (!bf) {
+                       __skb_unlink(skb, &tid->buf_q);
+                       ieee80211_free_txskb(sc->hw, skb);
                        continue;
+               }
 
                bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
                seqno = bf->bf_state.seqno;
@@ -1731,9 +1741,11 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
                return;
        }
 
-       bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
-       if (!bf)
+       bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+       if (!bf) {
+               ieee80211_free_txskb(sc->hw, skb);
                return;
+       }
 
        bf->bf_state.bf_type = BUF_AMPDU;
        INIT_LIST_HEAD(&bf_head);
@@ -1757,11 +1769,6 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
        struct ath_buf *bf;
 
        bf = fi->bf;
-       if (!bf)
-               bf = ath_tx_setup_buffer(sc, txq, tid, skb, false);
-
-       if (!bf)
-               return;
 
        INIT_LIST_HEAD(&bf_head);
        list_add_tail(&bf->list, &bf_head);
@@ -1839,8 +1846,7 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
 static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
                                           struct ath_txq *txq,
                                           struct ath_atx_tid *tid,
-                                          struct sk_buff *skb,
-                                          bool dequeue)
+                                          struct sk_buff *skb)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_frame_info *fi = get_frame_info(skb);
@@ -1852,7 +1858,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
        bf = ath_tx_get_buffer(sc);
        if (!bf) {
                ath_dbg(common, XMIT, "TX buffers are full\n");
-               goto error;
+               return NULL;
        }
 
        ATH_TXBUF_RESET(bf);
@@ -1881,18 +1887,12 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
                ath_err(ath9k_hw_common(sc->sc_ah),
                        "dma_mapping_error() on TX\n");
                ath_tx_return_buffer(sc, bf);
-               goto error;
+               return NULL;
        }
 
        fi->bf = bf;
 
        return bf;
-
-error:
-       if (dequeue)
-               __skb_unlink(skb, &tid->buf_q);
-       dev_kfree_skb_any(skb);
-       return NULL;
 }
 
 /* FIXME: tx power */
@@ -1921,9 +1921,14 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
                 */
                ath_tx_send_ampdu(sc, tid, skb, txctl);
        } else {
-               bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
-               if (!bf)
+               bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+               if (!bf) {
+                       if (txctl->paprd)
+                               dev_kfree_skb_any(skb);
+                       else
+                               ieee80211_free_txskb(sc->hw, skb);
                        return;
+               }
 
                bf->bf_state.bfs_paprd = txctl->paprd;
 
index 2aa4a59c72c87d4045de3f405d697e0067cf71da..2df17f1e49efca2ddb24f38a0145c4ce73225111 100644 (file)
@@ -303,6 +303,7 @@ struct ar9170 {
        unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
        unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];
        bool needs_full_reset;
+       bool force_usb_reset;
        atomic_t pending_restarts;
 
        /* interface mode settings */
index 67997b39aba79f0d14c47ffdbe4e85248bece20b..25a1e2f4f73862fb9bc26f6310d87bb3d51b6cf5 100644 (file)
@@ -465,27 +465,26 @@ static void carl9170_restart_work(struct work_struct *work)
 {
        struct ar9170 *ar = container_of(work, struct ar9170,
                                         restart_work);
-       int err;
+       int err = -EIO;
 
        ar->usedkeys = 0;
        ar->filter_state = 0;
        carl9170_cancel_worker(ar);
 
        mutex_lock(&ar->mutex);
-       err = carl9170_usb_restart(ar);
-       if (net_ratelimit()) {
-               if (err) {
-                       dev_err(&ar->udev->dev, "Failed to restart device "
-                               " (%d).\n", err);
-                } else {
-                       dev_info(&ar->udev->dev, "device restarted "
-                                "successfully.\n");
+       if (!ar->force_usb_reset) {
+               err = carl9170_usb_restart(ar);
+               if (net_ratelimit()) {
+                       if (err)
+                               dev_err(&ar->udev->dev, "Failed to restart device (%d).\n", err);
+                       else
+                               dev_info(&ar->udev->dev, "device restarted successfully.\n");
                }
        }
-
        carl9170_zap_queues(ar);
        mutex_unlock(&ar->mutex);
-       if (!err) {
+
+       if (!err && !ar->force_usb_reset) {
                ar->restart_counter++;
                atomic_set(&ar->pending_restarts, 0);
 
@@ -526,10 +525,10 @@ void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r)
        if (!ar->registered)
                return;
 
-       if (IS_ACCEPTING_CMD(ar) && !ar->needs_full_reset)
-               ieee80211_queue_work(ar->hw, &ar->restart_work);
-       else
-               carl9170_usb_reset(ar);
+       if (!IS_ACCEPTING_CMD(ar) || ar->needs_full_reset)
+               ar->force_usb_reset = true;
+
+       ieee80211_queue_work(ar->hw, &ar->restart_work);
 
        /*
         * At this point, the device instance might have vanished/disabled.
index 2691620393eae14f771f89641124ce9ff5b354c4..0679458a1bac44469ddf0d00935e7b165f66f9ed 100644 (file)
@@ -1596,8 +1596,9 @@ done:
                }
        }
 
-       if (mwifiex_bss_start(priv, bss, &req_ssid))
-               return -EFAULT;
+       ret = mwifiex_bss_start(priv, bss, &req_ssid);
+       if (ret)
+               return ret;
 
        if (mode == NL80211_IFTYPE_ADHOC) {
                /* Inform the BSS information to kernel, otherwise
@@ -1652,9 +1653,19 @@ done:
                        "info: association to bssid %pM failed\n",
                        priv->cfg_bssid);
                memset(priv->cfg_bssid, 0, ETH_ALEN);
+
+               if (ret > 0)
+                       cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
+                                               NULL, 0, NULL, 0, ret,
+                                               GFP_KERNEL);
+               else
+                       cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
+                                               NULL, 0, NULL, 0,
+                                               WLAN_STATUS_UNSPECIFIED_FAILURE,
+                                               GFP_KERNEL);
        }
 
-       return ret;
+       return 0;
 }
 
 /*
@@ -1802,7 +1813,7 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
 {
        struct net_device *dev = request->wdev->netdev;
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       int i, offset;
+       int i, offset, ret;
        struct ieee80211_channel *chan;
        struct ieee_types_header *ie;
 
@@ -1855,8 +1866,12 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
 
                priv->user_scan_cfg->chan_list[i].scan_time = 0;
        }
-       if (mwifiex_scan_networks(priv, priv->user_scan_cfg))
-               return -EFAULT;
+
+       ret = mwifiex_scan_networks(priv, priv->user_scan_cfg);
+       if (ret) {
+               dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
+               return ret;
+       }
 
        if (request->ie && request->ie_len) {
                for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
index 82e63cee1e9770bf100a11e8e76b68531741df8d..7b0858af8f5d804d05ae6c8ebd4bc20990a6ffed 100644 (file)
@@ -1180,16 +1180,18 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
        struct mwifiex_adapter *adapter = priv->adapter;
        struct host_cmd_ds_802_11_ad_hoc_result *adhoc_result;
        struct mwifiex_bssdescriptor *bss_desc;
+       u16 reason_code;
 
        adhoc_result = &resp->params.adhoc_result;
 
        bss_desc = priv->attempted_bss_desc;
 
        /* Join result code 0 --> SUCCESS */
-       if (le16_to_cpu(resp->result)) {
+       reason_code = le16_to_cpu(resp->result);
+       if (reason_code) {
                dev_err(priv->adapter->dev, "ADHOC_RESP: failed\n");
                if (priv->media_connected)
-                       mwifiex_reset_connect_state(priv);
+                       mwifiex_reset_connect_state(priv, reason_code);
 
                memset(&priv->curr_bss_params.bss_descriptor,
                       0x00, sizeof(struct mwifiex_bssdescriptor));
index bfb3fa69805c8d34d5d25586ec014c7d71728c9a..c2d0ab146af545431b8fe5f3d04916756ef3b782 100644 (file)
@@ -847,7 +847,7 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
                                 struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
                                 struct host_cmd_ds_command *resp);
-void mwifiex_reset_connect_state(struct mwifiex_private *priv);
+void mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason);
 u8 mwifiex_band_to_radio_type(u8 band);
 int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac);
 int mwifiex_adhoc_start(struct mwifiex_private *priv,
index e36a75988f877600978c083595c4844d951860c5..00b658d3b6ecfae72792b055a717aab9c41a0401 100644 (file)
@@ -1296,7 +1296,7 @@ mwifiex_radio_type_to_band(u8 radio_type)
 int mwifiex_scan_networks(struct mwifiex_private *priv,
                          const struct mwifiex_user_scan_cfg *user_scan_in)
 {
-       int ret = 0;
+       int ret;
        struct mwifiex_adapter *adapter = priv->adapter;
        struct cmd_ctrl_node *cmd_node;
        union mwifiex_scan_cmd_config_tlv *scan_cfg_out;
@@ -1309,25 +1309,26 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
        unsigned long flags;
 
        if (adapter->scan_processing) {
-               dev_dbg(adapter->dev, "cmd: Scan already in process...\n");
-               return ret;
+               dev_err(adapter->dev, "cmd: Scan already in process...\n");
+               return -EBUSY;
        }
 
-       spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-       adapter->scan_processing = true;
-       spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
-
        if (priv->scan_block) {
-               dev_dbg(adapter->dev,
+               dev_err(adapter->dev,
                        "cmd: Scan is blocked during association...\n");
-               return ret;
+               return -EBUSY;
        }
 
+       spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
+       adapter->scan_processing = true;
+       spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+
        scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
                                                                GFP_KERNEL);
        if (!scan_cfg_out) {
                dev_err(adapter->dev, "failed to alloc scan_cfg_out\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto done;
        }
 
        buf_size = sizeof(struct mwifiex_chan_scan_param_set) *
@@ -1336,7 +1337,8 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
        if (!scan_chan_list) {
                dev_err(adapter->dev, "failed to alloc scan_chan_list\n");
                kfree(scan_cfg_out);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto done;
        }
 
        mwifiex_config_scan(priv, user_scan_in, &scan_cfg_out->config,
@@ -1364,14 +1366,16 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
                        spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
                                               flags);
                }
-       } else {
-               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-               adapter->scan_processing = true;
-               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
        }
 
        kfree(scan_cfg_out);
        kfree(scan_chan_list);
+done:
+       if (ret) {
+               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
+               adapter->scan_processing = false;
+               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+       }
        return ret;
 }
 
@@ -1430,8 +1434,8 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
                        ret = mwifiex_is_network_compatible(priv, bss_desc,
                                                            priv->bss_mode);
                        if (ret)
-                               dev_err(priv->adapter->dev, "cannot find ssid "
-                                       "%s\n", bss_desc->ssid.ssid);
+                               dev_err(priv->adapter->dev,
+                                       "Incompatible network settings\n");
                        break;
                default:
                        ret = 0;
index e380171c4c5dd08918669863d4a756894e46a2e9..09e6a267f5666fd0bf868bd537635726239e4680 100644 (file)
@@ -545,7 +545,7 @@ static int mwifiex_ret_802_11_deauthenticate(struct mwifiex_private *priv,
        if (!memcmp(resp->params.deauth.mac_addr,
                    &priv->curr_bss_params.bss_descriptor.mac_address,
                    sizeof(resp->params.deauth.mac_addr)))
-               mwifiex_reset_connect_state(priv);
+               mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING);
 
        return 0;
 }
@@ -558,7 +558,7 @@ static int mwifiex_ret_802_11_deauthenticate(struct mwifiex_private *priv,
 static int mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private *priv,
                                          struct host_cmd_ds_command *resp)
 {
-       mwifiex_reset_connect_state(priv);
+       mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING);
        return 0;
 }
 
index aafde30e714aa97e40ecbbedc86a39fb08b26866..8132119e1a211a41c887a0bda77f433af41a8bcd 100644 (file)
@@ -41,7 +41,7 @@
  *      - Sends a disconnect event to upper layers/applications.
  */
 void
-mwifiex_reset_connect_state(struct mwifiex_private *priv)
+mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
 {
        struct mwifiex_adapter *adapter = priv->adapter;
 
@@ -117,10 +117,10 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv)
        priv->media_connected = false;
        dev_dbg(adapter->dev,
                "info: successfully disconnected from %pM: reason code %d\n",
-               priv->cfg_bssid, WLAN_REASON_DEAUTH_LEAVING);
+               priv->cfg_bssid, reason_code);
        if (priv->bss_mode == NL80211_IFTYPE_STATION) {
-               cfg80211_disconnected(priv->netdev, WLAN_REASON_DEAUTH_LEAVING,
-                                     NULL, 0, GFP_KERNEL);
+               cfg80211_disconnected(priv->netdev, reason_code, NULL, 0,
+                                     GFP_KERNEL);
        }
        memset(priv->cfg_bssid, 0, ETH_ALEN);
 
@@ -186,7 +186,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
        struct mwifiex_adapter *adapter = priv->adapter;
        int ret = 0;
        u32 eventcause = adapter->event_cause;
-       u16 ctrl;
+       u16 ctrl, reason_code;
 
        switch (eventcause) {
        case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
@@ -204,22 +204,31 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
        case EVENT_DEAUTHENTICATED:
                dev_dbg(adapter->dev, "event: Deauthenticated\n");
                adapter->dbg.num_event_deauth++;
-               if (priv->media_connected)
-                       mwifiex_reset_connect_state(priv);
+               if (priv->media_connected) {
+                       reason_code =
+                               le16_to_cpu(*(__le16 *)adapter->event_body);
+                       mwifiex_reset_connect_state(priv, reason_code);
+               }
                break;
 
        case EVENT_DISASSOCIATED:
                dev_dbg(adapter->dev, "event: Disassociated\n");
                adapter->dbg.num_event_disassoc++;
-               if (priv->media_connected)
-                       mwifiex_reset_connect_state(priv);
+               if (priv->media_connected) {
+                       reason_code =
+                               le16_to_cpu(*(__le16 *)adapter->event_body);
+                       mwifiex_reset_connect_state(priv, reason_code);
+               }
                break;
 
        case EVENT_LINK_LOST:
                dev_dbg(adapter->dev, "event: Link lost\n");
                adapter->dbg.num_event_link_lost++;
-               if (priv->media_connected)
-                       mwifiex_reset_connect_state(priv);
+               if (priv->media_connected) {
+                       reason_code =
+                               le16_to_cpu(*(__le16 *)adapter->event_body);
+                       mwifiex_reset_connect_state(priv, reason_code);
+               }
                break;
 
        case EVENT_PS_SLEEP:
index 540c94f8505a9b734b9b09ef6ab814ca04b17bd0..01dc8891070c3729c37b08cce18506ab583c4761 100644 (file)
@@ -2252,9 +2252,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
         */
        if (rt2x00_rt(rt2x00dev, RT3352)) {
                rt2800_bbp_write(rt2x00dev, 27, 0x0);
-               rt2800_bbp_write(rt2x00dev, 62, 0x26 + rt2x00dev->lna_gain);
+               rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
                rt2800_bbp_write(rt2x00dev, 27, 0x20);
-               rt2800_bbp_write(rt2x00dev, 62, 0x26 + rt2x00dev->lna_gain);
+               rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
        } else {
                rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
                rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
index 4ebfcf3d8a3b26d07c5cd2e742ab59aff3c5ba63..f2d6b78d901d92d3965fe3bd849751f04fb7ccf3 100644 (file)
@@ -335,21 +335,35 @@ unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb)
 
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                unsigned long size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
+               unsigned long offset = skb_shinfo(skb)->frags[i].page_offset;
                unsigned long bytes;
+
+               offset &= ~PAGE_MASK;
+
                while (size > 0) {
+                       BUG_ON(offset >= PAGE_SIZE);
                        BUG_ON(copy_off > MAX_BUFFER_OFFSET);
 
-                       if (start_new_rx_buffer(copy_off, size, 0)) {
+                       bytes = PAGE_SIZE - offset;
+
+                       if (bytes > size)
+                               bytes = size;
+
+                       if (start_new_rx_buffer(copy_off, bytes, 0)) {
                                count++;
                                copy_off = 0;
                        }
 
-                       bytes = size;
                        if (copy_off + bytes > MAX_BUFFER_OFFSET)
                                bytes = MAX_BUFFER_OFFSET - copy_off;
 
                        copy_off += bytes;
+
+                       offset += bytes;
                        size -= bytes;
+
+                       if (offset == PAGE_SIZE)
+                               offset = 0;
                }
        }
        return count;
@@ -403,14 +417,24 @@ static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb,
        unsigned long bytes;
 
        /* Data must not cross a page boundary. */
-       BUG_ON(size + offset > PAGE_SIZE);
+       BUG_ON(size + offset > PAGE_SIZE<<compound_order(page));
 
        meta = npo->meta + npo->meta_prod - 1;
 
+       /* Skip unused frames from start of page */
+       page += offset >> PAGE_SHIFT;
+       offset &= ~PAGE_MASK;
+
        while (size > 0) {
+               BUG_ON(offset >= PAGE_SIZE);
                BUG_ON(npo->copy_off > MAX_BUFFER_OFFSET);
 
-               if (start_new_rx_buffer(npo->copy_off, size, *head)) {
+               bytes = PAGE_SIZE - offset;
+
+               if (bytes > size)
+                       bytes = size;
+
+               if (start_new_rx_buffer(npo->copy_off, bytes, *head)) {
                        /*
                         * Netfront requires there to be some data in the head
                         * buffer.
@@ -420,7 +444,6 @@ static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb,
                        meta = get_next_rx_buffer(vif, npo);
                }
 
-               bytes = size;
                if (npo->copy_off + bytes > MAX_BUFFER_OFFSET)
                        bytes = MAX_BUFFER_OFFSET - npo->copy_off;
 
@@ -453,6 +476,13 @@ static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb,
                offset += bytes;
                size -= bytes;
 
+               /* Next frame */
+               if (offset == PAGE_SIZE && size) {
+                       BUG_ON(!PageCompound(page));
+                       page++;
+                       offset = 0;
+               }
+
                /* Leave a gap for the GSO descriptor. */
                if (*head && skb_shinfo(skb)->gso_size && !vif->gso_prefix)
                        vif->rx.req_cons++;
index ec6209dd7c397b9238cc1b495e5b849d966a3fdf..debaa75b0552d6daeefc24e4d5ee4dd929baca76 100644 (file)
@@ -725,10 +725,10 @@ static const struct nmk_pingroup nmk_db8500_groups[] = {
        DB8500_PIN_GROUP(spi0_c_1, NMK_GPIO_ALT_C),
        DB8500_PIN_GROUP(usbsim_c_2, NMK_GPIO_ALT_C),
        DB8500_PIN_GROUP(i2c3_c_2, NMK_GPIO_ALT_C),
-       /* Other alt C1 column, these are still configured as alt C */
-       DB8500_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C),
-       DB8500_PIN_GROUP(spi2_oc1_1, NMK_GPIO_ALT_C),
-       DB8500_PIN_GROUP(spi2_oc1_2, NMK_GPIO_ALT_C),
+       /* Other alt C1 column */
+       DB8500_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C1),
+       DB8500_PIN_GROUP(spi2_oc1_1, NMK_GPIO_ALT_C1),
+       DB8500_PIN_GROUP(spi2_oc1_2, NMK_GPIO_ALT_C1),
 };
 
 /* We use this macro to define the groups applicable to a function */
@@ -860,6 +860,284 @@ static const struct nmk_function nmk_db8500_functions[] = {
        FUNCTION(spi2),
 };
 
+static const struct prcm_gpiocr_altcx_pin_desc db8500_altcx_pins[] = {
+       PRCM_GPIOCR_ALTCX(23,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_CLK_a */
+                               true, PRCM_IDX_GPIOCR1, 7,      /* SBAG_CLK_a */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(24,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE or U2_RXD ??? */
+                               true, PRCM_IDX_GPIOCR1, 7,      /* SBAG_VAL_a */
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STM_MOD_CMD0 */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(25,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[0] */
+                               true, PRCM_IDX_GPIOCR1, 7,      /* SBAG_D_a[0] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(26,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[1] */
+                               true, PRCM_IDX_GPIOCR1, 7,      /* SBAG_D_a[1] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(27,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[2] */
+                               true, PRCM_IDX_GPIOCR1, 7,      /* SBAG_D_a[2] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(28,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[3] */
+                               true, PRCM_IDX_GPIOCR1, 7,      /* SBAG_D_a[3] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(29,   false, 0, 0,
+                               false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STM_MOD_CMD0 */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(30,   false, 0, 0,
+                               false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STM_MOD_CMD0 */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(31,   false, 0, 0,
+                               false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STM_MOD_CMD0 */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(32,   false, 0, 0,
+                               false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STM_MOD_CMD0 */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(68,   true, PRCM_IDX_GPIOCR1, 18,     /* REMAP_SELECT_ON */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(69,   true, PRCM_IDX_GPIOCR1, 18,     /* REMAP_SELECT_ON */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(70,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D23 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               true, PRCM_IDX_GPIOCR1, 11,     /* STM_MOD_CMD1 */
+                               true, PRCM_IDX_GPIOCR1, 8       /* SBAG_CLK */
+       ),
+       PRCM_GPIOCR_ALTCX(71,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D22 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               true, PRCM_IDX_GPIOCR1, 11,     /* STM_MOD_CMD1 */
+                               true, PRCM_IDX_GPIOCR1, 8       /* SBAG_D3 */
+       ),
+       PRCM_GPIOCR_ALTCX(72,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D21 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               true, PRCM_IDX_GPIOCR1, 11,     /* STM_MOD_CMD1 */
+                               true, PRCM_IDX_GPIOCR1, 8       /* SBAG_D2 */
+       ),
+       PRCM_GPIOCR_ALTCX(73,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D20 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               true, PRCM_IDX_GPIOCR1, 11,     /* STM_MOD_CMD1 */
+                               true, PRCM_IDX_GPIOCR1, 8       /* SBAG_D1 */
+       ),
+       PRCM_GPIOCR_ALTCX(74,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D19 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               true, PRCM_IDX_GPIOCR1, 11,     /* STM_MOD_CMD1 */
+                               true, PRCM_IDX_GPIOCR1, 8       /* SBAG_D0 */
+       ),
+       PRCM_GPIOCR_ALTCX(75,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D18 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               true, PRCM_IDX_GPIOCR1, 0,      /* DBG_UARTMOD_CMD0 */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(76,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D17 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               true, PRCM_IDX_GPIOCR1, 0,      /* DBG_UARTMOD_CMD0 */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(77,   true, PRCM_IDX_GPIOCR1, 5,      /* PTM_A9_D16 */
+                               true, PRCM_IDX_GPIOCR2, 2,      /* DBG_ETM_R4_CMD0 */
+                               false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 8       /* SBAG_VAL */
+       ),
+       PRCM_GPIOCR_ALTCX(86,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_O3 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(87,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_O2 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(88,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_I3 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(89,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_I2 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(90,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_O1 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(91,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_O0 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(92,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_I1 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(93,   true, PRCM_IDX_GPIOCR1, 12,     /* KP_I0 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(96,   true, PRCM_IDX_GPIOCR2, 3,      /* RF_INT */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(97,   true, PRCM_IDX_GPIOCR2, 1,      /* RF_CTRL */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(151,  false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_CTL */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS17 */
+       ),
+       PRCM_GPIOCR_ALTCX(152,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_CLK */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_CLK */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS16 */
+       ),
+       PRCM_GPIOCR_ALTCX(153,  true, PRCM_IDX_GPIOCR1, 1,      /* UARTMOD_CMD1 */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D15 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS15 */
+       ),
+       PRCM_GPIOCR_ALTCX(154,  true, PRCM_IDX_GPIOCR1, 1,      /* UARTMOD_CMD1 */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D14 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS14 */
+       ),
+       PRCM_GPIOCR_ALTCX(155,  true, PRCM_IDX_GPIOCR1, 13,     /* STM_MOD_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D13 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS13 */
+       ),
+       PRCM_GPIOCR_ALTCX(156,  true, PRCM_IDX_GPIOCR1, 13,     /* STM_MOD_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D12 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS12 */
+       ),
+       PRCM_GPIOCR_ALTCX(157,  true, PRCM_IDX_GPIOCR1, 13,     /* STM_MOD_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D11 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS11 */
+       ),
+       PRCM_GPIOCR_ALTCX(158,  true, PRCM_IDX_GPIOCR1, 13,     /* STM_MOD_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D10 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS10 */
+       ),
+       PRCM_GPIOCR_ALTCX(159,  true, PRCM_IDX_GPIOCR1, 13,     /* STM_MOD_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D9 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS9 */
+       ),
+       PRCM_GPIOCR_ALTCX(160,  false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 14,     /* PTM_A9_D8 */
+                               true, PRCM_IDX_GPIOCR1, 19,     /* DBG_ETM_R4_CMD2 */
+                               true, PRCM_IDX_GPIOCR1, 25      /* HW_OBS8 */
+       ),
+       PRCM_GPIOCR_ALTCX(161,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO7 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D7 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS7 */
+       ),
+       PRCM_GPIOCR_ALTCX(162,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO6 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D6 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS6 */
+       ),
+       PRCM_GPIOCR_ALTCX(163,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO5 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D5 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS5 */
+       ),
+       PRCM_GPIOCR_ALTCX(164,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO4 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D4 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS4 */
+       ),
+       PRCM_GPIOCR_ALTCX(165,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO3 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D3 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS3 */
+       ),
+       PRCM_GPIOCR_ALTCX(166,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO2 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D2 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS2 */
+       ),
+       PRCM_GPIOCR_ALTCX(167,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO1 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D1 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS1 */
+       ),
+       PRCM_GPIOCR_ALTCX(168,  true, PRCM_IDX_GPIOCR1, 4,      /* Hx_GPIO0 */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* PTM_A9_D0 */
+                               true, PRCM_IDX_GPIOCR1, 15,     /* DBG_ETM_R4_CMD1*/
+                               true, PRCM_IDX_GPIOCR1, 24      /* HW_OBS0 */
+       ),
+       PRCM_GPIOCR_ALTCX(170,  true, PRCM_IDX_GPIOCR2, 2,      /* RF_INT */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(171,  true, PRCM_IDX_GPIOCR2, 0,      /* RF_CTRL */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(215,  true, PRCM_IDX_GPIOCR1, 23,     /* SPI2_TXD */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(216,  true, PRCM_IDX_GPIOCR1, 23,     /* SPI2_FRM */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(217,  true, PRCM_IDX_GPIOCR1, 23,     /* SPI2_CLK */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(218,  true, PRCM_IDX_GPIOCR1, 23,     /* SPI2_RXD */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+};
+
+static const u16 db8500_prcm_gpiocr_regs[] = {
+       [PRCM_IDX_GPIOCR1] = 0x138,
+       [PRCM_IDX_GPIOCR2] = 0x574,
+};
+
 static const struct nmk_pinctrl_soc_data nmk_db8500_soc = {
        .gpio_ranges = nmk_db8500_ranges,
        .gpio_num_ranges = ARRAY_SIZE(nmk_db8500_ranges),
@@ -869,6 +1147,9 @@ static const struct nmk_pinctrl_soc_data nmk_db8500_soc = {
        .nfunctions = ARRAY_SIZE(nmk_db8500_functions),
        .groups = nmk_db8500_groups,
        .ngroups = ARRAY_SIZE(nmk_db8500_groups),
+       .altcx_pins = db8500_altcx_pins,
+       .npins_altcx = ARRAY_SIZE(db8500_altcx_pins),
+       .prcm_gpiocr_registers = db8500_prcm_gpiocr_regs,
 };
 
 void __devinit
index 3daf665c84c3fbed73fdc2187a5c54cbe4d8fd18..52fc30181f7ea908848a48a6d095373a1d1619d6 100644 (file)
@@ -778,50 +778,50 @@ static const struct nmk_pingroup nmk_db8540_groups[] = {
        DB8540_PIN_GROUP(spi0_c_1, NMK_GPIO_ALT_C),
        DB8540_PIN_GROUP(i2c3_c_1, NMK_GPIO_ALT_C),
 
-       /* Other alt C1 column, these are still configured as alt C */
-       DB8540_PIN_GROUP(spi3_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(stmape_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(u2_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(remap0_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(remap1_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modobsrefclk_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modobspwrctrl_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modobsclkout_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(moduart1_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modprcmudbg_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modobsresout_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modaccgpo_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modxmip_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(i2c6_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(u2txrx_oc1_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(u2ctsrts_oc1_1, NMK_GPIO_ALT_C),
+       /* Other alt C1 column */
+       DB8540_PIN_GROUP(spi3_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(stmape_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(u2_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(remap0_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(remap1_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(modobsrefclk_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(modobspwrctrl_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(modobsclkout_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(moduart1_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(modprcmudbg_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(modobsresout_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(modaccgpo_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(modxmip_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(i2c6_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(u2txrx_oc1_1, NMK_GPIO_ALT_C1),
+       DB8540_PIN_GROUP(u2ctsrts_oc1_1, NMK_GPIO_ALT_C1),
 
-       /* Other alt C2 column, these are still configured as alt C */
-       DB8540_PIN_GROUP(sbag_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(hxclk_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modaccuart_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(stmmod_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(moduartstmmux_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(hxgpio_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(sbag_oc2_2, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modobsservice_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(moduart0_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(stmape_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(u2_oc2_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modxmip_oc2_1, NMK_GPIO_ALT_C),
+       /* Other alt C2 column */
+       DB8540_PIN_GROUP(sbag_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(hxclk_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(modaccuart_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(stmmod_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(moduartstmmux_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(hxgpio_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(sbag_oc2_2, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(modobsservice_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(moduart0_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(stmape_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(u2_oc2_1, NMK_GPIO_ALT_C2),
+       DB8540_PIN_GROUP(modxmip_oc2_1, NMK_GPIO_ALT_C2),
 
-       /* Other alt C3 column, these are still configured as alt C */
-       DB8540_PIN_GROUP(modaccgpo_oc3_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(tpui_oc3_1, NMK_GPIO_ALT_C),
+       /* Other alt C3 column */
+       DB8540_PIN_GROUP(modaccgpo_oc3_1, NMK_GPIO_ALT_C3),
+       DB8540_PIN_GROUP(tpui_oc3_1, NMK_GPIO_ALT_C3),
 
-       /* Other alt C4 column, these are still configured as alt C */
-       DB8540_PIN_GROUP(hwobs_oc4_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(moduart1txrx_oc4_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(moduart1rtscts_oc4_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modaccuarttxrx_oc4_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(modaccuartrtscts_oc4_1, NMK_GPIO_ALT_C),
-       DB8540_PIN_GROUP(stmmod_oc4_1, NMK_GPIO_ALT_C),
+       /* Other alt C4 column */
+       DB8540_PIN_GROUP(hwobs_oc4_1, NMK_GPIO_ALT_C4),
+       DB8540_PIN_GROUP(moduart1txrx_oc4_1, NMK_GPIO_ALT_C4),
+       DB8540_PIN_GROUP(moduart1rtscts_oc4_1, NMK_GPIO_ALT_C4),
+       DB8540_PIN_GROUP(modaccuarttxrx_oc4_1, NMK_GPIO_ALT_C4),
+       DB8540_PIN_GROUP(modaccuartrtscts_oc4_1, NMK_GPIO_ALT_C4),
+       DB8540_PIN_GROUP(stmmod_oc4_1, NMK_GPIO_ALT_C4),
 
 };
 
@@ -981,6 +981,265 @@ static const struct nmk_function nmk_db8540_functions[] = {
        FUNCTION(usb)
 };
 
+static const struct prcm_gpiocr_altcx_pin_desc db8540_altcx_pins[] = {
+       PRCM_GPIOCR_ALTCX(8,    true, PRCM_IDX_GPIOCR1, 20,     /* SPI3_CLK */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(9,    true, PRCM_IDX_GPIOCR1, 20,     /* SPI3_RXD */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(10,   true, PRCM_IDX_GPIOCR1, 20,     /* SPI3_FRM */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(11,   true, PRCM_IDX_GPIOCR1, 20,     /* SPI3_TXD */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(23,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_CLK_a */
+                               true, PRCM_IDX_GPIOCR2, 10,     /* SBAG_CLK_a */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(24,   true, PRCM_IDX_GPIOCR3, 30,     /* U2_RXD_g */
+                               true, PRCM_IDX_GPIOCR2, 10,     /* SBAG_VAL_a */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(25,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[0] */
+                               true, PRCM_IDX_GPIOCR2, 10,     /* SBAG_D_a[0] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(26,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[1] */
+                               true, PRCM_IDX_GPIOCR2, 10,     /* SBAG_D_a[1] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(27,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[2] */
+                               true, PRCM_IDX_GPIOCR2, 10,     /* SBAG_D_a[2] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(28,   true, PRCM_IDX_GPIOCR1, 9,      /* STMAPE_DAT_a[3] */
+                               true, PRCM_IDX_GPIOCR2, 10,     /* SBAG_D_a[3] */
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(64,   true, PRCM_IDX_GPIOCR1, 15,     /* MODOBS_REFCLK_REQ */
+                               false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_CTL */
+                               true, PRCM_IDX_GPIOCR2, 23      /* HW_OBS_APE_PRCMU[17] */
+       ),
+       PRCM_GPIOCR_ALTCX(65,   true, PRCM_IDX_GPIOCR1, 19,     /* MODOBS_PWRCTRL0 */
+                               true, PRCM_IDX_GPIOCR1, 24,     /* Hx_CLK */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_CLK */
+                               true, PRCM_IDX_GPIOCR2, 24      /* HW_OBS_APE_PRCMU[16] */
+       ),
+       PRCM_GPIOCR_ALTCX(66,   true, PRCM_IDX_GPIOCR1, 15,     /* MODOBS_CLKOUT1 */
+                               false, 0, 0,
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[15] */
+                               true, PRCM_IDX_GPIOCR2, 25      /* HW_OBS_APE_PRCMU[15] */
+       ),
+       PRCM_GPIOCR_ALTCX(67,   true, PRCM_IDX_GPIOCR1, 1,      /* MODUART1_TXD_a */
+                               true, PRCM_IDX_GPIOCR1, 6,      /* MODACCUART_TXD_a */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[14] */
+                               true, PRCM_IDX_GPIOCR2, 26      /* HW_OBS_APE_PRCMU[14] */
+       ),
+       PRCM_GPIOCR_ALTCX(70,   true, PRCM_IDX_GPIOCR3, 6,      /* MOD_PRCMU_DEBUG[17] */
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STMMOD_CLK_b */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[13] */
+                               true, PRCM_IDX_GPIOCR2, 27      /* HW_OBS_APE_PRCMU[13] */
+       ),
+       PRCM_GPIOCR_ALTCX(71,   true, PRCM_IDX_GPIOCR3, 6,      /* MOD_PRCMU_DEBUG[16] */
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STMMOD_DAT_b[3] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[12] */
+                               true, PRCM_IDX_GPIOCR2, 27      /* HW_OBS_APE_PRCMU[12] */
+       ),
+       PRCM_GPIOCR_ALTCX(72,   true, PRCM_IDX_GPIOCR3, 6,      /* MOD_PRCMU_DEBUG[15] */
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STMMOD_DAT_b[2] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[11] */
+                               true, PRCM_IDX_GPIOCR2, 27      /* HW_OBS_APE_PRCMU[11] */
+       ),
+       PRCM_GPIOCR_ALTCX(73,   true, PRCM_IDX_GPIOCR3, 6,      /* MOD_PRCMU_DEBUG[14] */
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STMMOD_DAT_b[1] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[10] */
+                               true, PRCM_IDX_GPIOCR2, 27      /* HW_OBS_APE_PRCMU[10] */
+       ),
+       PRCM_GPIOCR_ALTCX(74,   true, PRCM_IDX_GPIOCR3, 6,      /* MOD_PRCMU_DEBUG[13] */
+                               true, PRCM_IDX_GPIOCR1, 10,     /* STMMOD_DAT_b[0] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[9] */
+                               true, PRCM_IDX_GPIOCR2, 27      /* HW_OBS_APE_PRCMU[9] */
+       ),
+       PRCM_GPIOCR_ALTCX(75,   true, PRCM_IDX_GPIOCR1, 12,     /* MODOBS_RESOUT0_N */
+                               true, PRCM_IDX_GPIOCR2, 1,      /* MODUART_STMMUX_RXD_b */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[8] */
+                               true, PRCM_IDX_GPIOCR2, 28      /* HW_OBS_APE_PRCMU[8] */
+       ),
+       PRCM_GPIOCR_ALTCX(76,   true, PRCM_IDX_GPIOCR3, 7,      /* MOD_PRCMU_DEBUG[12] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[7] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[7] */
+                               true, PRCM_IDX_GPIOCR2, 29      /* HW_OBS_APE_PRCMU[7] */
+       ),
+       PRCM_GPIOCR_ALTCX(77,   true, PRCM_IDX_GPIOCR3, 7,      /* MOD_PRCMU_DEBUG[11] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[6] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[6] */
+                               true, PRCM_IDX_GPIOCR2, 29      /* HW_OBS_APE_PRCMU[6] */
+       ),
+       PRCM_GPIOCR_ALTCX(78,   true, PRCM_IDX_GPIOCR3, 7,      /* MOD_PRCMU_DEBUG[10] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[5] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[5] */
+                               true, PRCM_IDX_GPIOCR2, 29      /* HW_OBS_APE_PRCMU[5] */
+       ),
+       PRCM_GPIOCR_ALTCX(79,   true, PRCM_IDX_GPIOCR3, 7,      /* MOD_PRCMU_DEBUG[9] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[4] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[4] */
+                               true, PRCM_IDX_GPIOCR2, 29      /* HW_OBS_APE_PRCMU[4] */
+       ),
+       PRCM_GPIOCR_ALTCX(80,   true, PRCM_IDX_GPIOCR1, 26,     /* MODACC_GPO[0] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[3] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[3] */
+                               true, PRCM_IDX_GPIOCR2, 30      /* HW_OBS_APE_PRCMU[3] */
+       ),
+       PRCM_GPIOCR_ALTCX(81,   true, PRCM_IDX_GPIOCR2, 17,     /* MODACC_GPO[1] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[2] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[2] */
+                               true, PRCM_IDX_GPIOCR2, 30      /* HW_OBS_APE_PRCMU[2] */
+       ),
+       PRCM_GPIOCR_ALTCX(82,   true, PRCM_IDX_GPIOCR3, 8,      /* MOD_PRCMU_DEBUG[8] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[1] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[1] */
+                               true, PRCM_IDX_GPIOCR2, 31      /* HW_OBS_APE_PRCMU[1] */
+       ),
+       PRCM_GPIOCR_ALTCX(83,   true, PRCM_IDX_GPIOCR3, 8,      /* MOD_PRCMU_DEBUG[7] */
+                               true, PRCM_IDX_GPIOCR1, 25,     /* Hx_GPIO[0] */
+                               true, PRCM_IDX_GPIOCR1, 2,      /* TPIU_D[0] */
+                               true, PRCM_IDX_GPIOCR2, 31      /* HW_OBS_APE_PRCMU[0] */
+       ),
+       PRCM_GPIOCR_ALTCX(84,   true, PRCM_IDX_GPIOCR3, 9,      /* MOD_PRCMU_DEBUG[6] */
+                               true, PRCM_IDX_GPIOCR1, 8,      /* SBAG_CLK_b */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[23] */
+                               true, PRCM_IDX_GPIOCR1, 16      /* MODUART1_RXD_b */
+       ),
+       PRCM_GPIOCR_ALTCX(85,   true, PRCM_IDX_GPIOCR3, 9,      /* MOD_PRCMU_DEBUG[5] */
+                               true, PRCM_IDX_GPIOCR1, 8,      /* SBAG_D_b[3] */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[22] */
+                               true, PRCM_IDX_GPIOCR1, 16      /* MODUART1_TXD_b */
+       ),
+       PRCM_GPIOCR_ALTCX(86,   true, PRCM_IDX_GPIOCR3, 9,      /* MOD_PRCMU_DEBUG[0] */
+                               true, PRCM_IDX_GPIOCR2, 18,     /* STMAPE_DAT_b[0] */
+                               true, PRCM_IDX_GPIOCR1, 14,     /* TPIU_D[25] */
+                               true, PRCM_IDX_GPIOCR1, 11      /* STMMOD_DAT_c[0] */
+       ),
+       PRCM_GPIOCR_ALTCX(87,   true, PRCM_IDX_GPIOCR3, 0,      /* MODACC_GPO_a[5] */
+                               true, PRCM_IDX_GPIOCR2, 3,      /* U2_RXD_c */
+                               true, PRCM_IDX_GPIOCR1, 4,      /* TPIU_D[24] */
+                               true, PRCM_IDX_GPIOCR1, 21      /* MODUART_STMMUX_RXD_c */
+       ),
+       PRCM_GPIOCR_ALTCX(151,  true, PRCM_IDX_GPIOCR1, 18,     /* REMAP0 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(152,  true, PRCM_IDX_GPIOCR1, 18,     /* REMAP1 */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(153,  true, PRCM_IDX_GPIOCR3, 2,      /* KP_O_b[6] */
+                               true, PRCM_IDX_GPIOCR1, 8,      /* SBAG_D_b[2] */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[21] */
+                               true, PRCM_IDX_GPIOCR1, 0       /* MODUART1_RTS */
+       ),
+       PRCM_GPIOCR_ALTCX(154,  true, PRCM_IDX_GPIOCR3, 2,      /* KP_I_b[6] */
+                               true, PRCM_IDX_GPIOCR1, 8,      /* SBAG_D_b[1] */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[20] */
+                               true, PRCM_IDX_GPIOCR1, 0       /* MODUART1_CTS */
+       ),
+       PRCM_GPIOCR_ALTCX(155,  true, PRCM_IDX_GPIOCR3, 3,      /* KP_O_b[5] */
+                               true, PRCM_IDX_GPIOCR1, 8,      /* SBAG_D_b[0] */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[19] */
+                               true, PRCM_IDX_GPIOCR1, 5       /* MODACCUART_RXD_c */
+       ),
+       PRCM_GPIOCR_ALTCX(156,  true, PRCM_IDX_GPIOCR3, 3,      /* KP_O_b[4] */
+                               true, PRCM_IDX_GPIOCR1, 8,      /* SBAG_VAL_b */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[18] */
+                               true, PRCM_IDX_GPIOCR1, 5       /* MODACCUART_TXD_b */
+       ),
+       PRCM_GPIOCR_ALTCX(157,  true, PRCM_IDX_GPIOCR3, 4,      /* KP_I_b[5] */
+                               true, PRCM_IDX_GPIOCR1, 23,     /* MODOBS_SERVICE_N */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[17] */
+                               true, PRCM_IDX_GPIOCR1, 14      /* MODACCUART_RTS */
+       ),
+       PRCM_GPIOCR_ALTCX(158,  true, PRCM_IDX_GPIOCR3, 4,      /* KP_I_b[4] */
+                               true, PRCM_IDX_GPIOCR2, 0,      /* U2_TXD_c */
+                               true, PRCM_IDX_GPIOCR1, 3,      /* TPIU_D[16] */
+                               true, PRCM_IDX_GPIOCR1, 14      /* MODACCUART_CTS */
+       ),
+       PRCM_GPIOCR_ALTCX(159,  true, PRCM_IDX_GPIOCR3, 5,      /* KP_O_b[3] */
+                               true, PRCM_IDX_GPIOCR3, 10,     /* MODUART0_RXD */
+                               true, PRCM_IDX_GPIOCR1, 4,      /* TPIU_D[31] */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(160,  true, PRCM_IDX_GPIOCR3, 5,      /* KP_I_b[3] */
+                               true, PRCM_IDX_GPIOCR3, 10,     /* MODUART0_TXD */
+                               true, PRCM_IDX_GPIOCR1, 4,      /* TPIU_D[30] */
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(161,  true, PRCM_IDX_GPIOCR3, 9,      /* MOD_PRCMU_DEBUG[4] */
+                               true, PRCM_IDX_GPIOCR2, 18,     /* STMAPE_CLK_b */
+                               true, PRCM_IDX_GPIOCR1, 4,      /* TPIU_D[29] */
+                               true, PRCM_IDX_GPIOCR1, 11      /* STMMOD_CLK_c */
+       ),
+       PRCM_GPIOCR_ALTCX(162,  true, PRCM_IDX_GPIOCR3, 9,      /* MOD_PRCMU_DEBUG[3] */
+                               true, PRCM_IDX_GPIOCR2, 18,     /* STMAPE_DAT_b[3] */
+                               true, PRCM_IDX_GPIOCR1, 4,      /* TPIU_D[28] */
+                               true, PRCM_IDX_GPIOCR1, 11      /* STMMOD_DAT_c[3] */
+       ),
+       PRCM_GPIOCR_ALTCX(163,  true, PRCM_IDX_GPIOCR3, 9,      /* MOD_PRCMU_DEBUG[2] */
+                               true, PRCM_IDX_GPIOCR2, 18,     /* STMAPE_DAT_b[2] */
+                               true, PRCM_IDX_GPIOCR1, 4,      /* TPIU_D[27] */
+                               true, PRCM_IDX_GPIOCR1, 11      /* STMMOD_DAT_c[2] */
+       ),
+       PRCM_GPIOCR_ALTCX(164,  true, PRCM_IDX_GPIOCR3, 9,      /* MOD_PRCMU_DEBUG[1] */
+                               true, PRCM_IDX_GPIOCR2, 18,     /* STMAPE_DAT_b[1] */
+                               true, PRCM_IDX_GPIOCR1, 4,      /* TPIU_D[26] */
+                               true, PRCM_IDX_GPIOCR1, 11      /* STMMOD_DAT_c[1] */
+       ),
+       PRCM_GPIOCR_ALTCX(204,  true, PRCM_IDX_GPIOCR2, 2,      /* U2_RXD_f */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(205,  true, PRCM_IDX_GPIOCR2, 2,      /* U2_TXD_f */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(206,  true, PRCM_IDX_GPIOCR2, 2,      /* U2_CTSn_b */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+       PRCM_GPIOCR_ALTCX(207,  true, PRCM_IDX_GPIOCR2, 2,      /* U2_RTSn_b */
+                               false, 0, 0,
+                               false, 0, 0,
+                               false, 0, 0
+       ),
+};
+
+static const u16 db8540_prcm_gpiocr_regs[] = {
+       [PRCM_IDX_GPIOCR1] = 0x138,
+       [PRCM_IDX_GPIOCR2] = 0x574,
+       [PRCM_IDX_GPIOCR3] = 0x2bc,
+};
+
 static const struct nmk_pinctrl_soc_data nmk_db8540_soc = {
        .gpio_ranges = nmk_db8540_ranges,
        .gpio_num_ranges = ARRAY_SIZE(nmk_db8540_ranges),
@@ -990,6 +1249,9 @@ static const struct nmk_pinctrl_soc_data nmk_db8540_soc = {
        .nfunctions = ARRAY_SIZE(nmk_db8540_functions),
        .groups = nmk_db8540_groups,
        .ngroups = ARRAY_SIZE(nmk_db8540_groups),
+       .altcx_pins = db8540_altcx_pins,
+       .npins_altcx = ARRAY_SIZE(db8540_altcx_pins),
+       .prcm_gpiocr_registers = db8540_prcm_gpiocr_regs,
 };
 
 void __devinit
index 6030a513f3c488506de4d80cd3cfae6c25ce69b2..fec9c30133d43b2731a9fe8d765ba05106d5eda1 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/pinctrl/pinconf.h>
 /* Since we request GPIOs from ourself */
 #include <linux/pinctrl/consumer.h>
+#include <linux/mfd/dbx500-prcmu.h>
 
 #include <asm/mach/irq.h>
 
@@ -237,6 +238,89 @@ nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset)
        dev_dbg(nmk_chip->chip.dev, "%d: clearing interrupt mask\n", gpio);
 }
 
+static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
+       unsigned offset, unsigned alt_num)
+{
+       int i;
+       u16 reg;
+       u8 bit;
+       u8 alt_index;
+       const struct prcm_gpiocr_altcx_pin_desc *pin_desc;
+       const u16 *gpiocr_regs;
+
+       if (alt_num > PRCM_IDX_GPIOCR_ALTC_MAX) {
+               dev_err(npct->dev, "PRCM GPIOCR: alternate-C%i is invalid\n",
+                       alt_num);
+               return;
+       }
+
+       for (i = 0 ; i < npct->soc->npins_altcx ; i++) {
+               if (npct->soc->altcx_pins[i].pin == offset)
+                       break;
+       }
+       if (i == npct->soc->npins_altcx) {
+               dev_dbg(npct->dev, "PRCM GPIOCR: pin %i is not found\n",
+                       offset);
+               return;
+       }
+
+       pin_desc = npct->soc->altcx_pins + i;
+       gpiocr_regs = npct->soc->prcm_gpiocr_registers;
+
+       /*
+        * If alt_num is NULL, just clear current ALTCx selection
+        * to make sure we come back to a pure ALTC selection
+        */
+       if (!alt_num) {
+               for (i = 0 ; i < PRCM_IDX_GPIOCR_ALTC_MAX ; i++) {
+                       if (pin_desc->altcx[i].used == true) {
+                               reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
+                               bit = pin_desc->altcx[i].control_bit;
+                               if (prcmu_read(reg) & BIT(bit)) {
+                                       prcmu_write_masked(reg, BIT(bit), 0);
+                                       dev_dbg(npct->dev,
+                                               "PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n",
+                                               offset, i+1);
+                               }
+                       }
+               }
+               return;
+       }
+
+       alt_index = alt_num - 1;
+       if (pin_desc->altcx[alt_index].used == false) {
+               dev_warn(npct->dev,
+                       "PRCM GPIOCR: pin %i: alternate-C%i does not exist\n",
+                       offset, alt_num);
+               return;
+       }
+
+       /*
+        * Check if any other ALTCx functions are activated on this pin
+        * and disable it first.
+        */
+       for (i = 0 ; i < PRCM_IDX_GPIOCR_ALTC_MAX ; i++) {
+               if (i == alt_index)
+                       continue;
+               if (pin_desc->altcx[i].used == true) {
+                       reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
+                       bit = pin_desc->altcx[i].control_bit;
+                       if (prcmu_read(reg) & BIT(bit)) {
+                               prcmu_write_masked(reg, BIT(bit), 0);
+                               dev_dbg(npct->dev,
+                                       "PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n",
+                                       offset, i+1);
+                       }
+               }
+       }
+
+       reg = gpiocr_regs[pin_desc->altcx[alt_index].reg_index];
+       bit = pin_desc->altcx[alt_index].control_bit;
+       dev_dbg(npct->dev, "PRCM GPIOCR: pin %i: alternate-C%i has been selected\n",
+               offset, alt_index+1);
+       prcmu_write_masked(reg, BIT(bit), BIT(bit));
+}
+
 static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
                             pin_cfg_t cfg, bool sleep, unsigned int *slpmregs)
 {
@@ -1287,9 +1371,19 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
 
        platform_set_drvdata(dev, nmk_chip);
 
-       nmk_chip->domain = irq_domain_add_legacy(np, NMK_GPIO_PER_CHIP,
-                                               NOMADIK_GPIO_TO_IRQ(pdata->first_gpio),
-                                               0, &nmk_gpio_irq_simple_ops, nmk_chip);
+       if (np) {
+               /* The DT case will just grab a set of IRQ numbers */
+               nmk_chip->domain = irq_domain_add_linear(np, NMK_GPIO_PER_CHIP,
+                               &nmk_gpio_irq_simple_ops, nmk_chip);
+       } else {
+               /* Non-DT legacy mode, use hardwired IRQ numbers */
+               int irq_start;
+
+               irq_start = NOMADIK_GPIO_TO_IRQ(pdata->first_gpio);
+               nmk_chip->domain = irq_domain_add_simple(NULL,
+                               NMK_GPIO_PER_CHIP, irq_start,
+                               &nmk_gpio_irq_simple_ops, nmk_chip);
+       }
        if (!nmk_chip->domain) {
                dev_err(&dev->dev, "failed to create irqdomain\n");
                ret = -ENOSYS;
@@ -1441,7 +1535,7 @@ static int nmk_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
         * IOFORCE will switch *all* ports to their sleepmode setting to as
         * to avoid glitches. (Not just one port!)
         */
-       glitch = (g->altsetting == NMK_GPIO_ALT_C);
+       glitch = ((g->altsetting & NMK_GPIO_ALT_C) == NMK_GPIO_ALT_C);
 
        if (glitch) {
                spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
@@ -1491,8 +1585,21 @@ static int nmk_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
                 */
                nmk_gpio_disable_lazy_irq(nmk_chip, bit);
 
-               __nmk_gpio_set_mode_safe(nmk_chip, bit, g->altsetting, glitch);
+               __nmk_gpio_set_mode_safe(nmk_chip, bit,
+                       (g->altsetting & NMK_GPIO_ALT_C), glitch);
                clk_disable(nmk_chip->clk);
+
+               /*
+                * Call PRCM GPIOCR config function in case ALTC
+                * has been selected:
+                * - If selection is a ALTCx, some bits in PRCM GPIOCR registers
+                *   must be set.
+                * - If selection is pure ALTC and previous selection was ALTCx,
+                *   then some bits in PRCM GPIOCR registers must be cleared.
+                */
+               if ((g->altsetting & NMK_GPIO_ALT_C) == NMK_GPIO_ALT_C)
+                       nmk_prcm_altcx_set_mode(npct, g->pins[i],
+                               g->altsetting >> NMK_GPIO_ALT_CX_SHIFT);
        }
 
        /* When all pins are successfully reconfigured we get here */
index 5c99f1c62dfd1a1524f3d833b37d36c83c96a3c1..eef316e979a02a1156c8ede6ca10c3b039e5d7fc 100644 (file)
@@ -8,6 +8,78 @@
 #define PINCTRL_NMK_DB8500     1
 #define PINCTRL_NMK_DB8540     2
 
+#define PRCM_GPIOCR_ALTCX(pin_num,\
+       altc1_used, altc1_ri, altc1_cb,\
+       altc2_used, altc2_ri, altc2_cb,\
+       altc3_used, altc3_ri, altc3_cb,\
+       altc4_used, altc4_ri, altc4_cb)\
+{\
+       .pin = pin_num,\
+       .altcx[PRCM_IDX_GPIOCR_ALTC1] = {\
+               .used = altc1_used,\
+               .reg_index = altc1_ri,\
+               .control_bit = altc1_cb\
+       },\
+       .altcx[PRCM_IDX_GPIOCR_ALTC2] = {\
+               .used = altc2_used,\
+               .reg_index = altc2_ri,\
+               .control_bit = altc2_cb\
+       },\
+       .altcx[PRCM_IDX_GPIOCR_ALTC3] = {\
+               .used = altc3_used,\
+               .reg_index = altc3_ri,\
+               .control_bit = altc3_cb\
+       },\
+       .altcx[PRCM_IDX_GPIOCR_ALTC4] = {\
+               .used = altc4_used,\
+               .reg_index = altc4_ri,\
+               .control_bit = altc4_cb\
+       },\
+}
+
+/**
+ * enum prcm_gpiocr_reg_index
+ * Used to reference an PRCM GPIOCR register address.
+ */
+enum prcm_gpiocr_reg_index {
+       PRCM_IDX_GPIOCR1,
+       PRCM_IDX_GPIOCR2,
+       PRCM_IDX_GPIOCR3
+};
+/**
+ * enum prcm_gpiocr_altcx_index
+ * Used to reference an Other alternate-C function.
+ */
+enum prcm_gpiocr_altcx_index {
+       PRCM_IDX_GPIOCR_ALTC1,
+       PRCM_IDX_GPIOCR_ALTC2,
+       PRCM_IDX_GPIOCR_ALTC3,
+       PRCM_IDX_GPIOCR_ALTC4,
+       PRCM_IDX_GPIOCR_ALTC_MAX,
+};
+
+/**
+ * struct prcm_gpio_altcx - Other alternate-C function
+ * @used: other alternate-C function availability
+ * @reg_index: PRCM GPIOCR register index used to control the function
+ * @control_bit: PRCM GPIOCR bit used to control the function
+ */
+struct prcm_gpiocr_altcx {
+       bool used:1;
+       u8 reg_index:2;
+       u8 control_bit:5;
+} __packed;
+
+/**
+ * struct prcm_gpio_altcx_pin_desc - Other alternate-C pin
+ * @pin: The pin number
+ * @altcx: array of other alternate-C[1-4] functions
+ */
+struct prcm_gpiocr_altcx_pin_desc {
+       unsigned short pin;
+       struct prcm_gpiocr_altcx altcx[PRCM_IDX_GPIOCR_ALTC_MAX];
+};
+
 /**
  * struct nmk_function - Nomadik pinctrl mux function
  * @name: The name of the function, exported to pinctrl core.
@@ -50,6 +122,9 @@ struct nmk_pingroup {
  * @nfunction: The number of entries in @functions.
  * @groups:    An array describing all pin groups the pin SoC supports.
  * @ngroups:   The number of entries in @groups.
+ * @altcx_pins:        The pins that support Other alternate-C function on this SoC
+ * @npins_altcx: The number of Other alternate-C pins
+ * @prcm_gpiocr_registers: The array of PRCM GPIOCR registers on this SoC
  */
 struct nmk_pinctrl_soc_data {
        struct pinctrl_gpio_range *gpio_ranges;
@@ -60,6 +135,9 @@ struct nmk_pinctrl_soc_data {
        unsigned nfunctions;
        const struct nmk_pingroup *groups;
        unsigned ngroups;
+       const struct prcm_gpiocr_altcx_pin_desc *altcx_pins;
+       unsigned npins_altcx;
+       const u16 *prcm_gpiocr_registers;
 };
 
 #ifdef CONFIG_PINCTRL_STN8815
index d4957b4edb62850d8414c449eed8c31a62969355..24768a27e1d8b2593bb97fd382a3fdf1b2a40252 100644 (file)
@@ -930,7 +930,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
        if (!sr_info->base) {
                dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
                ret = -ENOMEM;
-               goto err_release_region;
+               goto err_free_name;
        }
 
        if (irq)
@@ -969,7 +969,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
                        __func__);
                ret = PTR_ERR(sr_info->dbg_dir);
-               goto err_free_name;
+               goto err_debugfs;
        }
 
        (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR,
@@ -1013,11 +1013,11 @@ static int __init omap_sr_probe(struct platform_device *pdev)
 
 err_debugfs:
        debugfs_remove_recursive(sr_info->dbg_dir);
-err_free_name:
-       kfree(sr_info->name);
 err_iounmap:
        list_del(&sr_info->node);
        iounmap(sr_info->base);
+err_free_name:
+       kfree(sr_info->name);
 err_release_region:
        release_mem_region(mem->start, resource_size(mem));
 err_free_devinfo:
index d7c6b83097c1d3e856c8a0da50bdb8c4b6726fcd..ed81720e7b2bf4e7cd24f19f84c382e0ba7b669b 100644 (file)
@@ -1,6 +1,5 @@
 menuconfig PWM
        bool "Pulse-Width Modulation (PWM) Support"
-       depends on !MACH_JZ4740 && !PUV3_PWM
        help
          Generic Pulse-Width Modulation (PWM) support.
 
@@ -29,6 +28,15 @@ menuconfig PWM
 
 if PWM
 
+config PWM_AB8500
+       tristate "AB8500 PWM support"
+       depends on AB8500_CORE && ARCH_U8500
+       help
+         Generic PWM framework driver for Analog Baseband AB8500.
+
+         To compile this driver as a module, choose M here: the module
+         will be called pwm-ab8500.
+
 config PWM_BFIN
        tristate "Blackfin PWM support"
        depends on BFIN_GPTIMERS
@@ -47,6 +55,16 @@ config PWM_IMX
          To compile this driver as a module, choose M here: the module
          will be called pwm-imx.
 
+config PWM_JZ4740
+       tristate "Ingenic JZ4740 PWM support"
+       depends on MACH_JZ4740
+       help
+         Generic PWM framework driver for Ingenic JZ4740 based
+         machines.
+
+         To compile this driver as a module, choose M here: the module
+         will be called pwm-jz4740.
+
 config PWM_LPC32XX
        tristate "LPC32XX PWM support"
        depends on ARCH_LPC32XX
@@ -67,6 +85,15 @@ config PWM_MXS
          To compile this driver as a module, choose M here: the module
          will be called pwm-mxs.
 
+config PWM_PUV3
+       tristate "PKUnity NetBook-0916 PWM support"
+       depends on ARCH_PUV3
+       help
+         Generic PWM framework driver for PKUnity NetBook-0916.
+
+         To compile this driver as a module, choose M here: the module
+         will be called pwm-puv3.
+
 config PWM_PXA
        tristate "PXA PWM support"
        depends on ARCH_PXA
index 78f123dca30d27336cf086b8b5494f1de3df7162..acfe4821c58b0daeac507d18a9910e7939fbcd22 100644 (file)
@@ -1,8 +1,11 @@
 obj-$(CONFIG_PWM)              += core.o
+obj-$(CONFIG_PWM_AB8500)       += pwm-ab8500.o
 obj-$(CONFIG_PWM_BFIN)         += pwm-bfin.o
 obj-$(CONFIG_PWM_IMX)          += pwm-imx.o
+obj-$(CONFIG_PWM_JZ4740)       += pwm-jz4740.o
 obj-$(CONFIG_PWM_LPC32XX)      += pwm-lpc32xx.o
 obj-$(CONFIG_PWM_MXS)          += pwm-mxs.o
+obj-$(CONFIG_PWM_PUV3)         += pwm-puv3.o
 obj-$(CONFIG_PWM_PXA)          += pwm-pxa.o
 obj-$(CONFIG_PWM_SAMSUNG)      += pwm-samsung.o
 obj-$(CONFIG_PWM_TEGRA)                += pwm-tegra.o
index c6e05078d3adaff05708cc11ce76ea97763a375b..f5acdaa527077bc1e6e4bd8f67a52b21c5310dfb 100644 (file)
@@ -371,13 +371,35 @@ EXPORT_SYMBOL_GPL(pwm_free);
  */
 int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
 {
-       if (!pwm || period_ns == 0 || duty_ns > period_ns)
+       if (!pwm || duty_ns < 0 || period_ns <= 0 || duty_ns > period_ns)
                return -EINVAL;
 
        return pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns);
 }
 EXPORT_SYMBOL_GPL(pwm_config);
 
+/**
+ * pwm_set_polarity() - configure the polarity of a PWM signal
+ * @pwm: PWM device
+ * @polarity: new polarity of the PWM signal
+ *
+ * Note that the polarity cannot be configured while the PWM device is enabled
+ */
+int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity)
+{
+       if (!pwm || !pwm->chip->ops)
+               return -EINVAL;
+
+       if (!pwm->chip->ops->set_polarity)
+               return -ENOSYS;
+
+       if (test_bit(PWMF_ENABLED, &pwm->flags))
+               return -EBUSY;
+
+       return pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity);
+}
+EXPORT_SYMBOL_GPL(pwm_set_polarity);
+
 /**
  * pwm_enable() - start a PWM output toggling
  * @pwm: PWM device
@@ -624,6 +646,64 @@ out:
 }
 EXPORT_SYMBOL_GPL(pwm_put);
 
+static void devm_pwm_release(struct device *dev, void *res)
+{
+       pwm_put(*(struct pwm_device **)res);
+}
+
+/**
+ * devm_pwm_get() - resource managed pwm_get()
+ * @dev: device for PWM consumer
+ * @con_id: consumer name
+ *
+ * This function performs like pwm_get() but the acquired PWM device will
+ * automatically be released on driver detach.
+ */
+struct pwm_device *devm_pwm_get(struct device *dev, const char *con_id)
+{
+       struct pwm_device **ptr, *pwm;
+
+       ptr = devres_alloc(devm_pwm_release, sizeof(**ptr), GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       pwm = pwm_get(dev, con_id);
+       if (!IS_ERR(pwm)) {
+               *ptr = pwm;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return pwm;
+}
+EXPORT_SYMBOL_GPL(devm_pwm_get);
+
+static int devm_pwm_match(struct device *dev, void *res, void *data)
+{
+       struct pwm_device **p = res;
+
+       if (WARN_ON(!p || !*p))
+               return 0;
+
+       return *p == data;
+}
+
+/**
+ * devm_pwm_put() - resource managed pwm_put()
+ * @dev: device for PWM consumer
+ * @pwm: PWM device
+ *
+ * Release a PWM previously allocated using devm_pwm_get(). Calling this
+ * function is usually not needed because devm-allocated resources are
+ * automatically released on driver detach.
+ */
+void devm_pwm_put(struct device *dev, struct pwm_device *pwm)
+{
+       WARN_ON(devres_release(dev, devm_pwm_release, devm_pwm_match, pwm));
+}
+EXPORT_SYMBOL_GPL(devm_pwm_put);
+
 #ifdef CONFIG_DEBUG_FS
 static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s)
 {
similarity index 52%
rename from drivers/misc/ab8500-pwm.c
rename to drivers/pwm/pwm-ab8500.c
index d7a9aa14e5d5aafd8c0efc907b127147a202d197..cfb72ca873d17ece9cbdc61ee359457a2b945e54 100644 (file)
 #define ENABLE_PWM                     1
 #define DISABLE_PWM                    0
 
-struct pwm_device {
-       struct device *dev;
-       struct list_head node;
-       const char *label;
-       unsigned int pwm_id;
+struct ab8500_pwm_chip {
+       struct pwm_chip chip;
 };
 
-static LIST_HEAD(pwm_list);
-
-int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+static int ab8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+                            int duty_ns, int period_ns)
 {
        int ret = 0;
        unsigned int higher_val, lower_val;
@@ -50,95 +46,94 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
         */
        higher_val = ((duty_ns & 0x0300) >> 8);
 
-       reg = AB8500_PWM_OUT_CTRL1_REG + ((pwm->pwm_id - 1) * 2);
+       reg = AB8500_PWM_OUT_CTRL1_REG + ((chip->base - 1) * 2);
 
-       ret = abx500_set_register_interruptible(pwm->dev, AB8500_MISC,
+       ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC,
                        reg, (u8)lower_val);
        if (ret < 0)
                return ret;
-       ret = abx500_set_register_interruptible(pwm->dev, AB8500_MISC,
+       ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC,
                        (reg + 1), (u8)higher_val);
 
        return ret;
 }
-EXPORT_SYMBOL(pwm_config);
 
-int pwm_enable(struct pwm_device *pwm)
+static int ab8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
        int ret;
 
-       ret = abx500_mask_and_set_register_interruptible(pwm->dev,
+       ret = abx500_mask_and_set_register_interruptible(chip->dev,
                                AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
-                               1 << (pwm->pwm_id-1), ENABLE_PWM);
+                               1 << (chip->base - 1), ENABLE_PWM);
        if (ret < 0)
-               dev_err(pwm->dev, "%s: Failed to disable PWM, Error %d\n",
+               dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
                                                        pwm->label, ret);
        return ret;
 }
-EXPORT_SYMBOL(pwm_enable);
 
-void pwm_disable(struct pwm_device *pwm)
+static void ab8500_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
        int ret;
 
-       ret = abx500_mask_and_set_register_interruptible(pwm->dev,
+       ret = abx500_mask_and_set_register_interruptible(chip->dev,
                                AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
-                               1 << (pwm->pwm_id-1), DISABLE_PWM);
+                               1 << (chip->base - 1), DISABLE_PWM);
        if (ret < 0)
-               dev_err(pwm->dev, "%s: Failed to disable PWM, Error %d\n",
+               dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
                                                        pwm->label, ret);
        return;
 }
-EXPORT_SYMBOL(pwm_disable);
-
-struct pwm_device *pwm_request(int pwm_id, const char *label)
-{
-       struct pwm_device *pwm;
-
-       list_for_each_entry(pwm, &pwm_list, node) {
-               if (pwm->pwm_id == pwm_id) {
-                       pwm->label = label;
-                       pwm->pwm_id = pwm_id;
-                       return pwm;
-               }
-       }
-
-       return ERR_PTR(-ENOENT);
-}
-EXPORT_SYMBOL(pwm_request);
 
-void pwm_free(struct pwm_device *pwm)
-{
-       pwm_disable(pwm);
-}
-EXPORT_SYMBOL(pwm_free);
+static const struct pwm_ops ab8500_pwm_ops = {
+       .config = ab8500_pwm_config,
+       .enable = ab8500_pwm_enable,
+       .disable = ab8500_pwm_disable,
+};
 
 static int __devinit ab8500_pwm_probe(struct platform_device *pdev)
 {
-       struct pwm_device *pwm;
+       struct ab8500_pwm_chip *ab8500;
+       int err;
+
        /*
         * Nothing to be done in probe, this is required to get the
         * device which is required for ab8500 read and write
         */
-       pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
-       if (pwm == NULL) {
+       ab8500 = kzalloc(sizeof(*ab8500), GFP_KERNEL);
+       if (ab8500 == NULL) {
                dev_err(&pdev->dev, "failed to allocate memory\n");
                return -ENOMEM;
        }
-       pwm->dev = &pdev->dev;
-       pwm->pwm_id = pdev->id;
-       list_add_tail(&pwm->node, &pwm_list);
-       platform_set_drvdata(pdev, pwm);
-       dev_dbg(pwm->dev, "pwm probe successful\n");
+
+       ab8500->chip.dev = &pdev->dev;
+       ab8500->chip.ops = &ab8500_pwm_ops;
+       ab8500->chip.base = pdev->id;
+       ab8500->chip.npwm = 1;
+
+       err = pwmchip_add(&ab8500->chip);
+       if (err < 0) {
+               kfree(ab8500);
+               return err;
+       }
+
+       dev_dbg(&pdev->dev, "pwm probe successful\n");
+       platform_set_drvdata(pdev, ab8500);
+
        return 0;
 }
 
 static int __devexit ab8500_pwm_remove(struct platform_device *pdev)
 {
-       struct pwm_device *pwm = platform_get_drvdata(pdev);
-       list_del(&pwm->node);
+       struct ab8500_pwm_chip *ab8500 = platform_get_drvdata(pdev);
+       int err;
+
+       err = pwmchip_remove(&ab8500->chip);
+       if (err < 0)
+               return err;
+
        dev_dbg(&pdev->dev, "pwm driver removed\n");
-       kfree(pwm);
+       kfree(ab8500);
+
        return 0;
 }
 
@@ -150,19 +145,8 @@ static struct platform_driver ab8500_pwm_driver = {
        .probe = ab8500_pwm_probe,
        .remove = __devexit_p(ab8500_pwm_remove),
 };
+module_platform_driver(ab8500_pwm_driver);
 
-static int __init ab8500_pwm_init(void)
-{
-       return platform_driver_register(&ab8500_pwm_driver);
-}
-
-static void __exit ab8500_pwm_exit(void)
-{
-       platform_driver_unregister(&ab8500_pwm_driver);
-}
-
-subsys_initcall(ab8500_pwm_init);
-module_exit(ab8500_pwm_exit);
 MODULE_AUTHOR("Arun MURTHY <arun.murthy@stericsson.com>");
 MODULE_DESCRIPTION("AB8500 Pulse Width Modulation Driver");
 MODULE_ALIAS("platform:ab8500-pwm");
index d53c4e7941ef4364f9cf06975e19132e86bf817a..5da8e185e838c111676fb40a9d159619a846cdc7 100644 (file)
@@ -69,9 +69,6 @@ static int bfin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
        unsigned long period, duty;
        unsigned long long val;
 
-       if (duty_ns < 0 || duty_ns > period_ns)
-               return -EINVAL;
-
        val = (unsigned long long)get_sclk() * period_ns;
        do_div(val, NSEC_PER_SEC);
        period = val;
index 2a0b35333972836e0793fbe7a9f2e2c2de50e2af..8a5d3ae2946aef2f9e39010d3536150090fd0682 100644 (file)
@@ -16,8 +16,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/pwm.h>
-#include <mach/hardware.h>
-
+#include <linux/of_device.h>
 
 /* i.MX1 and i.MX21 share the same PWM function block: */
 
@@ -25,6 +24,7 @@
 #define MX1_PWMS    0x04   /* PWM Sample Register */
 #define MX1_PWMP    0x08   /* PWM Period Register */
 
+#define MX1_PWMC_EN            (1 << 4)
 
 /* i.MX27, i.MX31, i.MX35 share the same PWM function block: */
 
 #define MX3_PWMCR_EN              (1 << 0)
 
 struct imx_chip {
-       struct clk      *clk;
+       struct clk      *clk_per;
+       struct clk      *clk_ipg;
 
-       int             clk_enabled;
+       int             enabled;
        void __iomem    *mmio_base;
 
        struct pwm_chip chip;
+
+       int (*config)(struct pwm_chip *chip,
+               struct pwm_device *pwm, int duty_ns, int period_ns);
+       void (*set_enable)(struct pwm_chip *chip, bool enable);
 };
 
 #define to_imx_chip(chip)      container_of(chip, struct imx_chip, chip)
 
-static int imx_pwm_config(struct pwm_chip *chip,
+static int imx_pwm_config_v1(struct pwm_chip *chip,
                struct pwm_device *pwm, int duty_ns, int period_ns)
 {
        struct imx_chip *imx = to_imx_chip(chip);
 
-       if (!(cpu_is_mx1() || cpu_is_mx21())) {
-               unsigned long long c;
-               unsigned long period_cycles, duty_cycles, prescale;
-               u32 cr;
-
-               c = clk_get_rate(imx->clk);
-               c = c * period_ns;
-               do_div(c, 1000000000);
-               period_cycles = c;
-
-               prescale = period_cycles / 0x10000 + 1;
-
-               period_cycles /= prescale;
-               c = (unsigned long long)period_cycles * duty_ns;
-               do_div(c, period_ns);
-               duty_cycles = c;
-
-               /*
-                * according to imx pwm RM, the real period value should be
-                * PERIOD value in PWMPR plus 2.
-                */
-               if (period_cycles > 2)
-                       period_cycles -= 2;
-               else
-                       period_cycles = 0;
-
-               writel(duty_cycles, imx->mmio_base + MX3_PWMSAR);
-               writel(period_cycles, imx->mmio_base + MX3_PWMPR);
-
-               cr = MX3_PWMCR_PRESCALER(prescale) |
-                       MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN |
-                       MX3_PWMCR_DBGEN | MX3_PWMCR_EN;
-
-               if (cpu_is_mx25())
-                       cr |= MX3_PWMCR_CLKSRC_IPG;
-               else
-                       cr |= MX3_PWMCR_CLKSRC_IPG_HIGH;
-
-               writel(cr, imx->mmio_base + MX3_PWMCR);
-       } else if (cpu_is_mx1() || cpu_is_mx21()) {
-               /* The PWM subsystem allows for exact frequencies. However,
-                * I cannot connect a scope on my device to the PWM line and
-                * thus cannot provide the program the PWM controller
-                * exactly. Instead, I'm relying on the fact that the
-                * Bootloader (u-boot or WinCE+haret) has programmed the PWM
-                * function group already. So I'll just modify the PWM sample
-                * register to follow the ratio of duty_ns vs. period_ns
-                * accordingly.
-                *
-                * This is good enough for programming the brightness of
-                * the LCD backlight.
-                *
-                * The real implementation would divide PERCLK[0] first by
-                * both the prescaler (/1 .. /128) and then by CLKSEL
-                * (/2 .. /16).
-                */
-               u32 max = readl(imx->mmio_base + MX1_PWMP);
-               u32 p = max * duty_ns / period_ns;
-               writel(max - p, imx->mmio_base + MX1_PWMS);
-       } else {
-               BUG();
-       }
+       /*
+        * The PWM subsystem allows for exact frequencies. However,
+        * I cannot connect a scope on my device to the PWM line and
+        * thus cannot provide the program the PWM controller
+        * exactly. Instead, I'm relying on the fact that the
+        * Bootloader (u-boot or WinCE+haret) has programmed the PWM
+        * function group already. So I'll just modify the PWM sample
+        * register to follow the ratio of duty_ns vs. period_ns
+        * accordingly.
+        *
+        * This is good enough for programming the brightness of
+        * the LCD backlight.
+        *
+        * The real implementation would divide PERCLK[0] first by
+        * both the prescaler (/1 .. /128) and then by CLKSEL
+        * (/2 .. /16).
+        */
+       u32 max = readl(imx->mmio_base + MX1_PWMP);
+       u32 p = max * duty_ns / period_ns;
+       writel(max - p, imx->mmio_base + MX1_PWMS);
 
        return 0;
 }
 
+static void imx_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
+{
+       struct imx_chip *imx = to_imx_chip(chip);
+       u32 val;
+
+       val = readl(imx->mmio_base + MX1_PWMC);
+
+       if (enable)
+               val |= MX1_PWMC_EN;
+       else
+               val &= ~MX1_PWMC_EN;
+
+       writel(val, imx->mmio_base + MX1_PWMC);
+}
+
+static int imx_pwm_config_v2(struct pwm_chip *chip,
+               struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+       struct imx_chip *imx = to_imx_chip(chip);
+       unsigned long long c;
+       unsigned long period_cycles, duty_cycles, prescale;
+       u32 cr;
+
+       c = clk_get_rate(imx->clk_per);
+       c = c * period_ns;
+       do_div(c, 1000000000);
+       period_cycles = c;
+
+       prescale = period_cycles / 0x10000 + 1;
+
+       period_cycles /= prescale;
+       c = (unsigned long long)period_cycles * duty_ns;
+       do_div(c, period_ns);
+       duty_cycles = c;
+
+       /*
+        * according to imx pwm RM, the real period value should be
+        * PERIOD value in PWMPR plus 2.
+        */
+       if (period_cycles > 2)
+               period_cycles -= 2;
+       else
+               period_cycles = 0;
+
+       writel(duty_cycles, imx->mmio_base + MX3_PWMSAR);
+       writel(period_cycles, imx->mmio_base + MX3_PWMPR);
+
+       cr = MX3_PWMCR_PRESCALER(prescale) |
+               MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN |
+               MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC_IPG_HIGH;
+
+       if (imx->enabled)
+               cr |= MX3_PWMCR_EN;
+
+       writel(cr, imx->mmio_base + MX3_PWMCR);
+
+       return 0;
+}
+
+static void imx_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
+{
+       struct imx_chip *imx = to_imx_chip(chip);
+       u32 val;
+
+       val = readl(imx->mmio_base + MX3_PWMCR);
+
+       if (enable)
+               val |= MX3_PWMCR_EN;
+       else
+               val &= ~MX3_PWMCR_EN;
+
+       writel(val, imx->mmio_base + MX3_PWMCR);
+}
+
+static int imx_pwm_config(struct pwm_chip *chip,
+               struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+       struct imx_chip *imx = to_imx_chip(chip);
+       int ret;
+
+       ret = clk_prepare_enable(imx->clk_ipg);
+       if (ret)
+               return ret;
+
+       ret = imx->config(chip, pwm, duty_ns, period_ns);
+
+       clk_disable_unprepare(imx->clk_ipg);
+
+       return ret;
+}
+
 static int imx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
        struct imx_chip *imx = to_imx_chip(chip);
-       int rc = 0;
+       int ret;
 
-       if (!imx->clk_enabled) {
-               rc = clk_prepare_enable(imx->clk);
-               if (!rc)
-                       imx->clk_enabled = 1;
-       }
-       return rc;
+       ret = clk_prepare_enable(imx->clk_per);
+       if (ret)
+               return ret;
+
+       imx->set_enable(chip, true);
+
+       imx->enabled = 1;
+
+       return 0;
 }
 
 static void imx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
        struct imx_chip *imx = to_imx_chip(chip);
 
-       writel(0, imx->mmio_base + MX3_PWMCR);
+       imx->set_enable(chip, false);
 
-       if (imx->clk_enabled) {
-               clk_disable_unprepare(imx->clk);
-               imx->clk_enabled = 0;
-       }
+       clk_disable_unprepare(imx->clk_per);
+       imx->enabled = 0;
 }
 
 static struct pwm_ops imx_pwm_ops = {
@@ -153,30 +208,66 @@ static struct pwm_ops imx_pwm_ops = {
        .owner = THIS_MODULE,
 };
 
+struct imx_pwm_data {
+       int (*config)(struct pwm_chip *chip,
+               struct pwm_device *pwm, int duty_ns, int period_ns);
+       void (*set_enable)(struct pwm_chip *chip, bool enable);
+};
+
+static struct imx_pwm_data imx_pwm_data_v1 = {
+       .config = imx_pwm_config_v1,
+       .set_enable = imx_pwm_set_enable_v1,
+};
+
+static struct imx_pwm_data imx_pwm_data_v2 = {
+       .config = imx_pwm_config_v2,
+       .set_enable = imx_pwm_set_enable_v2,
+};
+
+static const struct of_device_id imx_pwm_dt_ids[] = {
+       { .compatible = "fsl,imx1-pwm", .data = &imx_pwm_data_v1, },
+       { .compatible = "fsl,imx27-pwm", .data = &imx_pwm_data_v2, },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_pwm_dt_ids);
+
 static int __devinit imx_pwm_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *of_id =
+                       of_match_device(imx_pwm_dt_ids, &pdev->dev);
+       struct imx_pwm_data *data;
        struct imx_chip *imx;
        struct resource *r;
        int ret = 0;
 
+       if (!of_id)
+               return -ENODEV;
+
        imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL);
        if (imx == NULL) {
                dev_err(&pdev->dev, "failed to allocate memory\n");
                return -ENOMEM;
        }
 
-       imx->clk = devm_clk_get(&pdev->dev, "pwm");
+       imx->clk_per = devm_clk_get(&pdev->dev, "per");
+       if (IS_ERR(imx->clk_per)) {
+               dev_err(&pdev->dev, "getting per clock failed with %ld\n",
+                               PTR_ERR(imx->clk_per));
+               return PTR_ERR(imx->clk_per);
+       }
 
-       if (IS_ERR(imx->clk))
-               return PTR_ERR(imx->clk);
+       imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+       if (IS_ERR(imx->clk_ipg)) {
+               dev_err(&pdev->dev, "getting ipg clock failed with %ld\n",
+                               PTR_ERR(imx->clk_ipg));
+               return PTR_ERR(imx->clk_ipg);
+       }
 
        imx->chip.ops = &imx_pwm_ops;
        imx->chip.dev = &pdev->dev;
        imx->chip.base = -1;
        imx->chip.npwm = 1;
 
-       imx->clk_enabled = 0;
-
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (r == NULL) {
                dev_err(&pdev->dev, "no memory resource defined\n");
@@ -187,6 +278,10 @@ static int __devinit imx_pwm_probe(struct platform_device *pdev)
        if (imx->mmio_base == NULL)
                return -EADDRNOTAVAIL;
 
+       data = of_id->data;
+       imx->config = data->config;
+       imx->set_enable = data->set_enable;
+
        ret = pwmchip_add(&imx->chip);
        if (ret < 0)
                return ret;
@@ -208,23 +303,14 @@ static int __devexit imx_pwm_remove(struct platform_device *pdev)
 
 static struct platform_driver imx_pwm_driver = {
        .driver         = {
-               .name   = "mxc_pwm",
+               .name   = "imx-pwm",
+               .of_match_table = of_match_ptr(imx_pwm_dt_ids),
        },
        .probe          = imx_pwm_probe,
        .remove         = __devexit_p(imx_pwm_remove),
 };
 
-static int __init imx_pwm_init(void)
-{
-       return platform_driver_register(&imx_pwm_driver);
-}
-arch_initcall(imx_pwm_init);
-
-static void __exit imx_pwm_exit(void)
-{
-       platform_driver_unregister(&imx_pwm_driver);
-}
-module_exit(imx_pwm_exit);
+module_platform_driver(imx_pwm_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
new file mode 100644 (file)
index 0000000..10250fc
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 platform PWM support
+ *
+ *  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.
+ *
+ *  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/clk.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+
+#include <asm/mach-jz4740/gpio.h>
+#include <asm/mach-jz4740/timer.h>
+
+#define NUM_PWM 8
+
+static const unsigned int jz4740_pwm_gpio_list[NUM_PWM] = {
+       JZ_GPIO_PWM0,
+       JZ_GPIO_PWM1,
+       JZ_GPIO_PWM2,
+       JZ_GPIO_PWM3,
+       JZ_GPIO_PWM4,
+       JZ_GPIO_PWM5,
+       JZ_GPIO_PWM6,
+       JZ_GPIO_PWM7,
+};
+
+struct jz4740_pwm_chip {
+       struct pwm_chip chip;
+       struct clk *clk;
+};
+
+static inline struct jz4740_pwm_chip *to_jz4740(struct pwm_chip *chip)
+{
+       return container_of(chip, struct jz4740_pwm_chip, chip);
+}
+
+static int jz4740_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       unsigned int gpio = jz4740_pwm_gpio_list[pwm->hwpwm];
+       int ret;
+
+       /*
+        * Timers 0 and 1 are used for system tasks, so they are unavailable
+        * for use as PWMs.
+        */
+       if (pwm->hwpwm < 2)
+               return -EBUSY;
+
+       ret = gpio_request(gpio, pwm->label);
+       if (ret) {
+               dev_err(chip->dev, "Failed to request GPIO#%u for PWM: %d\n",
+                       gpio, ret);
+               return ret;
+       }
+
+       jz_gpio_set_function(gpio, JZ_GPIO_FUNC_PWM);
+
+       jz4740_timer_start(pwm->hwpwm);
+
+       return 0;
+}
+
+static void jz4740_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       unsigned int gpio = jz4740_pwm_gpio_list[pwm->hwpwm];
+
+       jz4740_timer_set_ctrl(pwm->hwpwm, 0);
+
+       jz_gpio_set_function(gpio, JZ_GPIO_FUNC_NONE);
+       gpio_free(gpio);
+
+       jz4740_timer_stop(pwm->hwpwm);
+}
+
+static int jz4740_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       uint32_t ctrl = jz4740_timer_get_ctrl(pwm->pwm);
+
+       ctrl |= JZ_TIMER_CTRL_PWM_ENABLE;
+       jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
+       jz4740_timer_enable(pwm->hwpwm);
+
+       return 0;
+}
+
+static void jz4740_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       uint32_t ctrl = jz4740_timer_get_ctrl(pwm->hwpwm);
+
+       ctrl &= ~JZ_TIMER_CTRL_PWM_ENABLE;
+       jz4740_timer_disable(pwm->hwpwm);
+       jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
+}
+
+static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+                            int duty_ns, int period_ns)
+{
+       struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip);
+       unsigned long long tmp;
+       unsigned long period, duty;
+       unsigned int prescaler = 0;
+       uint16_t ctrl;
+       bool is_enabled;
+
+       tmp = (unsigned long long)clk_get_rate(jz4740->clk) * period_ns;
+       do_div(tmp, 1000000000);
+       period = tmp;
+
+       while (period > 0xffff && prescaler < 6) {
+               period >>= 2;
+               ++prescaler;
+       }
+
+       if (prescaler == 6)
+               return -EINVAL;
+
+       tmp = (unsigned long long)period * duty_ns;
+       do_div(tmp, period_ns);
+       duty = period - tmp;
+
+       if (duty >= period)
+               duty = period - 1;
+
+       is_enabled = jz4740_timer_is_enabled(pwm->hwpwm);
+       if (is_enabled)
+               jz4740_pwm_disable(chip, pwm);
+
+       jz4740_timer_set_count(pwm->hwpwm, 0);
+       jz4740_timer_set_duty(pwm->hwpwm, duty);
+       jz4740_timer_set_period(pwm->hwpwm, period);
+
+       ctrl = JZ_TIMER_CTRL_PRESCALER(prescaler) | JZ_TIMER_CTRL_SRC_EXT |
+               JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN;
+
+       jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
+
+       if (is_enabled)
+               jz4740_pwm_enable(chip, pwm);
+
+       return 0;
+}
+
+static const struct pwm_ops jz4740_pwm_ops = {
+       .request = jz4740_pwm_request,
+       .free = jz4740_pwm_free,
+       .config = jz4740_pwm_config,
+       .enable = jz4740_pwm_enable,
+       .disable = jz4740_pwm_disable,
+       .owner = THIS_MODULE,
+};
+
+static int __devinit jz4740_pwm_probe(struct platform_device *pdev)
+{
+       struct jz4740_pwm_chip *jz4740;
+       int ret;
+
+       jz4740 = devm_kzalloc(&pdev->dev, sizeof(*jz4740), GFP_KERNEL);
+       if (!jz4740)
+               return -ENOMEM;
+
+       jz4740->clk = clk_get(NULL, "ext");
+       if (IS_ERR(jz4740->clk))
+               return PTR_ERR(jz4740->clk);
+
+       jz4740->chip.dev = &pdev->dev;
+       jz4740->chip.ops = &jz4740_pwm_ops;
+       jz4740->chip.npwm = NUM_PWM;
+       jz4740->chip.base = -1;
+
+       ret = pwmchip_add(&jz4740->chip);
+       if (ret < 0) {
+               clk_put(jz4740->clk);
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, jz4740);
+
+       return 0;
+}
+
+static int __devexit jz4740_pwm_remove(struct platform_device *pdev)
+{
+       struct jz4740_pwm_chip *jz4740 = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = pwmchip_remove(&jz4740->chip);
+       if (ret < 0)
+               return ret;
+
+       clk_put(jz4740->clk);
+
+       return 0;
+}
+
+static struct platform_driver jz4740_pwm_driver = {
+       .driver = {
+               .name = "jz4740-pwm",
+               .owner = THIS_MODULE,
+       },
+       .probe = jz4740_pwm_probe,
+       .remove = __devexit_p(jz4740_pwm_remove),
+};
+module_platform_driver(jz4740_pwm_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Ingenic JZ4740 PWM driver");
+MODULE_ALIAS("platform:jz4740-pwm");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-puv3.c b/drivers/pwm/pwm-puv3.c
new file mode 100644 (file)
index 0000000..2a93f37
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * linux/arch/unicore32/kernel/pwm.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *     Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *     Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/pwm.h>
+
+#include <asm/div64.h>
+#include <mach/hardware.h>
+
+struct puv3_pwm_chip {
+       struct pwm_chip chip;
+       void __iomem *base;
+       struct clk *clk;
+       bool enabled;
+};
+
+static inline struct puv3_pwm_chip *to_puv3(struct pwm_chip *chip)
+{
+       return container_of(chip, struct puv3_pwm_chip, chip);
+}
+
+/*
+ * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE
+ * duty_ns   = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
+ */
+static int puv3_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+                          int duty_ns, int period_ns)
+{
+       unsigned long period_cycles, prescale, pv, dc;
+       struct puv3_pwm_chip *puv3 = to_puv3(chip);
+       unsigned long long c;
+
+       c = clk_get_rate(puv3->clk);
+       c = c * period_ns;
+       do_div(c, 1000000000);
+       period_cycles = c;
+
+       if (period_cycles < 1)
+               period_cycles = 1;
+
+       prescale = (period_cycles - 1) / 1024;
+       pv = period_cycles / (prescale + 1) - 1;
+
+       if (prescale > 63)
+               return -EINVAL;
+
+       if (duty_ns == period_ns)
+               dc = OST_PWMDCCR_FDCYCLE;
+       else
+               dc = (pv + 1) * duty_ns / period_ns;
+
+       /*
+        * NOTE: the clock to PWM has to be enabled first
+        * before writing to the registers
+        */
+       clk_prepare_enable(puv3->clk);
+
+       writel(prescale, puv3->base + OST_PWM_PWCR);
+       writel(pv - dc, puv3->base + OST_PWM_DCCR);
+       writel(pv, puv3->base + OST_PWM_PCR);
+
+       clk_disable_unprepare(puv3->clk);
+
+       return 0;
+}
+
+static int puv3_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       struct puv3_pwm_chip *puv3 = to_puv3(chip);
+
+       return clk_prepare_enable(puv3->clk);
+}
+
+static void puv3_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       struct puv3_pwm_chip *puv3 = to_puv3(chip);
+
+       clk_disable_unprepare(puv3->clk);
+}
+
+static const struct pwm_ops puv3_pwm_ops = {
+       .config = puv3_pwm_config,
+       .enable = puv3_pwm_enable,
+       .disable = puv3_pwm_disable,
+       .owner = THIS_MODULE,
+};
+
+static int __devinit pwm_probe(struct platform_device *pdev)
+{
+       struct puv3_pwm_chip *puv3;
+       struct resource *r;
+       int ret;
+
+       puv3 = devm_kzalloc(&pdev->dev, sizeof(*puv3), GFP_KERNEL);
+       if (puv3 == NULL) {
+               dev_err(&pdev->dev, "failed to allocate memory\n");
+               return -ENOMEM;
+       }
+
+       puv3->clk = devm_clk_get(&pdev->dev, "OST_CLK");
+       if (IS_ERR(puv3->clk))
+               return PTR_ERR(puv3->clk);
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (r == NULL) {
+               dev_err(&pdev->dev, "no memory resource defined\n");
+               return -ENODEV;
+       }
+
+       puv3->base = devm_request_and_ioremap(&pdev->dev, r);
+       if (puv3->base == NULL)
+               return -EADDRNOTAVAIL;
+
+       puv3->chip.dev = &pdev->dev;
+       puv3->chip.ops = &puv3_pwm_ops;
+       puv3->chip.base = -1;
+       puv3->chip.npwm = 1;
+
+       ret = pwmchip_add(&puv3->chip);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, puv3);
+       return 0;
+}
+
+static int __devexit pwm_remove(struct platform_device *pdev)
+{
+       struct puv3_pwm_chip *puv3 = platform_get_drvdata(pdev);
+
+       return pwmchip_remove(&puv3->chip);
+}
+
+static struct platform_driver puv3_pwm_driver = {
+       .driver = {
+               .name = "PKUnity-v3-PWM",
+       },
+       .probe = pwm_probe,
+       .remove = __devexit_p(pwm_remove),
+};
+module_platform_driver(puv3_pwm_driver);
+
+MODULE_LICENSE("GPL v2");
index bd5867a1c70064db164836630b7f126c2eeb4afb..260c3a88564d2a59e51d9c780d2d45517a54dbbd 100644 (file)
@@ -70,9 +70,6 @@ static int pxa_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
        unsigned long offset;
        int rc;
 
-       if (period_ns == 0 || duty_ns > period_ns)
-               return -EINVAL;
-
        offset = pwm->hwpwm ? 0x10 : 0;
 
        c = clk_get_rate(pc->clk);
index e5187c0ade9fdde4a4cfd4e8ba55c8b2d337173a..023a3bee76e7d04e9a76922d46c95addcf418086 100644 (file)
@@ -126,9 +126,6 @@ static int s3c_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
        if (period_ns > NS_IN_HZ || duty_ns > NS_IN_HZ)
                return -ERANGE;
 
-       if (duty_ns > period_ns)
-               return -EINVAL;
-
        if (period_ns == s3c->period_ns &&
            duty_ns == s3c->duty_ns)
                return 0;
index 4b6688909fee076c5573e086b972b7b3cf5ebffc..d6d4cf05565ef0975ca149e03ece75964f74baf6 100644 (file)
@@ -32,6 +32,7 @@
 #define CAP3                   0x10
 #define CAP4                   0x14
 #define ECCTL2                 0x2A
+#define ECCTL2_APWM_POL_LOW    BIT(10)
 #define ECCTL2_APWM_MODE       BIT(9)
 #define ECCTL2_SYNC_SEL_DISA   (BIT(7) | BIT(6))
 #define ECCTL2_TSCTR_FREERUN   BIT(4)
@@ -59,7 +60,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
        unsigned long period_cycles, duty_cycles;
        unsigned int reg_val;
 
-       if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC)
+       if (period_ns > NSEC_PER_SEC)
                return -ERANGE;
 
        c = pc->clk_rate;
@@ -111,6 +112,26 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
        return 0;
 }
 
+static int ecap_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
+               enum pwm_polarity polarity)
+{
+       struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);
+       unsigned short reg_val;
+
+       pm_runtime_get_sync(pc->chip.dev);
+       reg_val = readw(pc->mmio_base + ECCTL2);
+       if (polarity == PWM_POLARITY_INVERSED)
+               /* Duty cycle defines LOW period of PWM */
+               reg_val |= ECCTL2_APWM_POL_LOW;
+       else
+               /* Duty cycle defines HIGH period of PWM */
+               reg_val &= ~ECCTL2_APWM_POL_LOW;
+
+       writew(reg_val, pc->mmio_base + ECCTL2);
+       pm_runtime_put_sync(pc->chip.dev);
+       return 0;
+}
+
 static int ecap_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
        struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);
@@ -157,6 +178,7 @@ static void ecap_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 static const struct pwm_ops ecap_pwm_ops = {
        .free           = ecap_pwm_free,
        .config         = ecap_pwm_config,
+       .set_polarity   = ecap_pwm_set_polarity,
        .enable         = ecap_pwm_enable,
        .disable        = ecap_pwm_disable,
        .owner          = THIS_MODULE,
index b1996bcd5b788fd8923ef646b828d71dbc769265..d3c1dff0a0dc7a5a3eceb7e7c15fa1af10012afa 100644 (file)
 #define AQCTL_ZRO_FRCHIGH      BIT(1)
 #define AQCTL_ZRO_FRCTOGGLE    (BIT(1) | BIT(0))
 
+#define AQCTL_CHANA_POLNORMAL  (AQCTL_CAU_FRCLOW | AQCTL_PRD_FRCHIGH | \
+                               AQCTL_ZRO_FRCHIGH)
+#define AQCTL_CHANA_POLINVERSED        (AQCTL_CAU_FRCHIGH | AQCTL_PRD_FRCLOW | \
+                               AQCTL_ZRO_FRCLOW)
+#define AQCTL_CHANB_POLNORMAL  (AQCTL_CBU_FRCLOW | AQCTL_PRD_FRCHIGH | \
+                               AQCTL_ZRO_FRCHIGH)
+#define AQCTL_CHANB_POLINVERSED        (AQCTL_CBU_FRCHIGH | AQCTL_PRD_FRCLOW | \
+                               AQCTL_ZRO_FRCLOW)
+
 #define AQSFRC_RLDCSF_MASK     (BIT(7) | BIT(6))
 #define AQSFRC_RLDCSF_ZRO      0
 #define AQSFRC_RLDCSF_PRD      BIT(6)
@@ -105,6 +114,7 @@ struct ehrpwm_pwm_chip {
        unsigned int    clk_rate;
        void __iomem    *mmio_base;
        unsigned long period_cycles[NUM_PWM_CHANNEL];
+       enum pwm_polarity polarity[NUM_PWM_CHANNEL];
 };
 
 static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
@@ -165,39 +175,37 @@ static int set_prescale_div(unsigned long rqst_prescaler,
        return 1;
 }
 
-static void configure_chans(struct ehrpwm_pwm_chip *pc, int chan,
-               unsigned long duty_cycles)
+static void configure_polarity(struct ehrpwm_pwm_chip *pc, int chan)
 {
-       int cmp_reg, aqctl_reg;
+       int aqctl_reg;
        unsigned short aqctl_val, aqctl_mask;
 
        /*
-        * Channels can be configured from action qualifier module.
-        * Channel 0 configured with compare A register and for
-        * up-counter mode.
-        * Channel 1 configured with compare B register and for
-        * up-counter mode.
+        * Configure PWM output to HIGH/LOW level on counter
+        * reaches compare register value and LOW/HIGH level
+        * on counter value reaches period register value and
+        * zero value on counter
         */
        if (chan == 1) {
                aqctl_reg = AQCTLB;
-               cmp_reg = CMPB;
-               /* Configure PWM Low from compare B value */
-               aqctl_val = AQCTL_CBU_FRCLOW;
                aqctl_mask = AQCTL_CBU_MASK;
+
+               if (pc->polarity[chan] == PWM_POLARITY_INVERSED)
+                       aqctl_val = AQCTL_CHANB_POLINVERSED;
+               else
+                       aqctl_val = AQCTL_CHANB_POLNORMAL;
        } else {
-               cmp_reg = CMPA;
                aqctl_reg = AQCTLA;
-               /* Configure PWM Low from compare A value*/
-               aqctl_val = AQCTL_CAU_FRCLOW;
                aqctl_mask = AQCTL_CAU_MASK;
+
+               if (pc->polarity[chan] == PWM_POLARITY_INVERSED)
+                       aqctl_val = AQCTL_CHANA_POLINVERSED;
+               else
+                       aqctl_val = AQCTL_CHANA_POLNORMAL;
        }
 
-       /* Configure PWM High from period value and zero value */
-       aqctl_val |= AQCTL_PRD_FRCHIGH | AQCTL_ZRO_FRCHIGH;
        aqctl_mask |= AQCTL_PRD_MASK | AQCTL_ZRO_MASK;
-       ehrpwm_modify(pc->mmio_base,  aqctl_reg, aqctl_mask, aqctl_val);
-
-       ehrpwm_write(pc->mmio_base,  cmp_reg, duty_cycles);
+       ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val);
 }
 
 /*
@@ -211,9 +219,9 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
        unsigned long long c;
        unsigned long period_cycles, duty_cycles;
        unsigned short ps_divval, tb_divval;
-       int i;
+       int i, cmp_reg;
 
-       if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC)
+       if (period_ns > NSEC_PER_SEC)
                return -ERANGE;
 
        c = pc->clk_rate;
@@ -278,12 +286,29 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
        ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CTRMODE_MASK,
                        TBCTL_CTRMODE_UP);
 
-       /* Configure the channel for duty cycle */
-       configure_chans(pc, pwm->hwpwm, duty_cycles);
+       if (pwm->hwpwm == 1)
+               /* Channel 1 configured with compare B register */
+               cmp_reg = CMPB;
+       else
+               /* Channel 0 configured with compare A register */
+               cmp_reg = CMPA;
+
+       ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles);
+
        pm_runtime_put_sync(chip->dev);
        return 0;
 }
 
+static int ehrpwm_pwm_set_polarity(struct pwm_chip *chip,
+               struct pwm_device *pwm, enum pwm_polarity polarity)
+{
+       struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
+
+       /* Configuration of polarity in hardware delayed, do at enable */
+       pc->polarity[pwm->hwpwm] = polarity;
+       return 0;
+}
+
 static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
@@ -307,6 +332,9 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 
        ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
 
+       /* Channels polarity can be configured from action qualifier module */
+       configure_polarity(pc, pwm->hwpwm);
+
        /* Enable time counter for free_run */
        ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN);
        return 0;
@@ -358,6 +386,7 @@ static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 static const struct pwm_ops ehrpwm_pwm_ops = {
        .free           = ehrpwm_pwm_free,
        .config         = ehrpwm_pwm_config,
+       .set_polarity   = ehrpwm_pwm_set_polarity,
        .enable         = ehrpwm_pwm_enable,
        .disable        = ehrpwm_pwm_disable,
        .owner          = THIS_MODULE,
index 48e9041dd1e29b016b7997c2f8c74726ce90223d..07da58bb495c0c26775f1e1583c0c355697a2c87 100644 (file)
@@ -55,9 +55,9 @@ static int rio_mport_phys_table[] = {
 };
 
 
-/*
+/**
  * rio_destid_alloc - Allocate next available destID for given network
- * net: RIO network
+ * @net: RIO network
  *
  * Returns next available device destination ID for the specified RIO network.
  * Marks allocated ID as one in use.
@@ -69,14 +69,9 @@ static u16 rio_destid_alloc(struct rio_net *net)
        struct rio_id_table *idtab = &net->destid_table;
 
        spin_lock(&idtab->lock);
-       destid = find_next_zero_bit(idtab->table, idtab->max, idtab->next);
-       if (destid >= idtab->max)
-               destid = find_first_zero_bit(idtab->table, idtab->max);
+       destid = find_first_zero_bit(idtab->table, idtab->max);
 
        if (destid < idtab->max) {
-               idtab->next = destid + 1;
-               if (idtab->next >= idtab->max)
-                       idtab->next = 0;
                set_bit(destid, idtab->table);
                destid += idtab->start;
        } else
@@ -86,10 +81,10 @@ static u16 rio_destid_alloc(struct rio_net *net)
        return (u16)destid;
 }
 
-/*
+/**
  * rio_destid_reserve - Reserve the specivied destID
- * net: RIO network
- * destid: destID to reserve
+ * @net: RIO network
+ * @destid: destID to reserve
  *
  * Tries to reserve the specified destID.
  * Returns 0 if successfull.
@@ -106,10 +101,10 @@ static int rio_destid_reserve(struct rio_net *net, u16 destid)
        return oldbit;
 }
 
-/*
+/**
  * rio_destid_free - free a previously allocated destID
- * net: RIO network
- * destid: destID to free
+ * @net: RIO network
+ * @destid: destID to free
  *
  * Makes the specified destID available for use.
  */
@@ -123,9 +118,9 @@ static void rio_destid_free(struct rio_net *net, u16 destid)
        spin_unlock(&idtab->lock);
 }
 
-/*
+/**
  * rio_destid_first - return first destID in use
- * net: RIO network
+ * @net: RIO network
  */
 static u16 rio_destid_first(struct rio_net *net)
 {
@@ -142,10 +137,10 @@ static u16 rio_destid_first(struct rio_net *net)
        return (u16)destid;
 }
 
-/*
+/**
  * rio_destid_next - return next destID in use
- * net: RIO network
- * from: destination ID from which search shall continue
+ * @net: RIO network
+ * @from: destination ID from which search shall continue
  */
 static u16 rio_destid_next(struct rio_net *net, u16 from)
 {
@@ -1163,8 +1158,8 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port,
 
        net = kzalloc(sizeof(struct rio_net), GFP_KERNEL);
        if (net && do_enum) {
-               net->destid_table.table = kzalloc(
-                       BITS_TO_LONGS(RIO_MAX_ROUTE_ENTRIES(port->sys_size)) *
+               net->destid_table.table = kcalloc(
+                       BITS_TO_LONGS(RIO_MAX_ROUTE_ENTRIES(port->sys_size)),
                        sizeof(long),
                        GFP_KERNEL);
 
@@ -1174,7 +1169,6 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port,
                        net = NULL;
                } else {
                        net->destid_table.start = start;
-                       net->destid_table.next = 0;
                        net->destid_table.max =
                                        RIO_MAX_ROUTE_ENTRIES(port->sys_size);
                        spin_lock_init(&net->destid_table.lock);
@@ -1391,7 +1385,7 @@ int __devinit rio_disc_mport(struct rio_mport *mport)
                while (time_before(jiffies, to_end)) {
                        if (rio_enum_complete(mport))
                                goto enum_done;
-                       schedule_timeout_uninterruptible(msecs_to_jiffies(10));
+                       msleep(10);
                }
 
                pr_debug("RIO: discovery timeout on mport %d %s\n",
index d4bd69013c501010fc5ba76ce58c949d46708a9e..c17ae22567e0494c381bf023c13e48dfc729aa8b 100644 (file)
@@ -1275,49 +1275,68 @@ static void __devinit disc_work_handler(struct work_struct *_work)
        pr_debug("RIO: discovery work for mport %d %s\n",
                 work->mport->id, work->mport->name);
        rio_disc_mport(work->mport);
-
-       kfree(work);
 }
 
 int __devinit rio_init_mports(void)
 {
        struct rio_mport *port;
        struct rio_disc_work *work;
-       int no_disc = 0;
+       int n = 0;
+
+       if (!next_portid)
+               return -ENODEV;
 
+       /*
+        * First, run enumerations and check if we need to perform discovery
+        * on any of the registered mports.
+        */
        list_for_each_entry(port, &rio_mports, node) {
                if (port->host_deviceid >= 0)
                        rio_enum_mport(port);
-               else if (!no_disc) {
-                       if (!rio_wq) {
-                               rio_wq = alloc_workqueue("riodisc", 0, 0);
-                               if (!rio_wq) {
-                                       pr_err("RIO: unable allocate rio_wq\n");
-                                       no_disc = 1;
-                                       continue;
-                               }
-                       }
-
-                       work = kzalloc(sizeof *work, GFP_KERNEL);
-                       if (!work) {
-                               pr_err("RIO: no memory for work struct\n");
-                               no_disc = 1;
-                               continue;
-                       }
-
-                       work->mport = port;
-                       INIT_WORK(&work->work, disc_work_handler);
-                       queue_work(rio_wq, &work->work);
-               }
+               else
+                       n++;
+       }
+
+       if (!n)
+               goto no_disc;
+
+       /*
+        * If we have mports that require discovery schedule a discovery work
+        * for each of them. If the code below fails to allocate needed
+        * resources, exit without error to keep results of enumeration
+        * process (if any).
+        * TODO: Implement restart of dicovery process for all or
+        * individual discovering mports.
+        */
+       rio_wq = alloc_workqueue("riodisc", 0, 0);
+       if (!rio_wq) {
+               pr_err("RIO: unable allocate rio_wq\n");
+               goto no_disc;
        }
 
-       if (rio_wq) {
-               pr_debug("RIO: flush discovery workqueue\n");
-               flush_workqueue(rio_wq);
-               pr_debug("RIO: flush discovery workqueue finished\n");
+       work = kcalloc(n, sizeof *work, GFP_KERNEL);
+       if (!work) {
+               pr_err("RIO: no memory for work struct\n");
                destroy_workqueue(rio_wq);
+               goto no_disc;
        }
 
+       n = 0;
+       list_for_each_entry(port, &rio_mports, node) {
+               if (port->host_deviceid < 0) {
+                       work[n].mport = port;
+                       INIT_WORK(&work[n].work, disc_work_handler);
+                       queue_work(rio_wq, &work[n].work);
+                       n++;
+               }
+       }
+
+       flush_workqueue(rio_wq);
+       pr_debug("RIO: destroy discovery workqueue\n");
+       destroy_workqueue(rio_wq);
+       kfree(work);
+
+no_disc:
        rio_init();
 
        return 0;
index e069f176a82d0f05c6d6ec94a619ebd164e501c9..19c03ab2bdcb3f2d585c7b38948b5de3bff113c1 100644 (file)
@@ -59,6 +59,7 @@ comment "RTC interfaces"
 config RTC_INTF_SYSFS
        boolean "/sys/class/rtc/rtcN (sysfs)"
        depends on SYSFS
+       default RTC_CLASS
        help
          Say yes here if you want to use your RTCs using sysfs interfaces,
          /sys/class/rtc/rtc0 through /sys/.../rtcN.
@@ -68,6 +69,7 @@ config RTC_INTF_SYSFS
 config RTC_INTF_PROC
        boolean "/proc/driver/rtc (procfs for rtcN)"
        depends on PROC_FS
+       default RTC_CLASS
        help
          Say yes here if you want to use your system clock RTC through
          the proc interface, /proc/driver/rtc.
@@ -79,6 +81,7 @@ config RTC_INTF_PROC
 
 config RTC_INTF_DEV
        boolean "/dev/rtcN (character devices)"
+       default RTC_CLASS
        help
          Say yes here if you want to use your RTCs using the /dev
          interfaces, which "udev" sets up as /dev/rtc0 through
index a5a55da2a1ac14752c426f4a0a00e4fb4f11521c..b6ad0de07930c531f9a81f8314a1b6b974e9d6db 100644 (file)
@@ -69,23 +69,9 @@ static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *a
                                  size_t count);
 static ssize_t dcssblk_remove_store(struct device * dev, struct device_attribute *attr, const char * buf,
                                  size_t count);
-static ssize_t dcssblk_save_store(struct device * dev, struct device_attribute *attr, const char * buf,
-                                 size_t count);
-static ssize_t dcssblk_save_show(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t dcssblk_shared_store(struct device * dev, struct device_attribute *attr, const char * buf,
-                                 size_t count);
-static ssize_t dcssblk_shared_show(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t dcssblk_seglist_show(struct device *dev,
-                               struct device_attribute *attr,
-                               char *buf);
 
 static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store);
 static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store);
-static DEVICE_ATTR(save, S_IWUSR | S_IRUSR, dcssblk_save_show,
-                  dcssblk_save_store);
-static DEVICE_ATTR(shared, S_IWUSR | S_IRUSR, dcssblk_shared_show,
-                  dcssblk_shared_store);
-static DEVICE_ATTR(seglist, S_IRUSR, dcssblk_seglist_show, NULL);
 
 static struct device *dcssblk_root_dev;
 
@@ -416,6 +402,8 @@ out:
        up_write(&dcssblk_devices_sem);
        return rc;
 }
+static DEVICE_ATTR(shared, S_IWUSR | S_IRUSR, dcssblk_shared_show,
+                  dcssblk_shared_store);
 
 /*
  * device attribute for save operation on current copy
@@ -476,6 +464,8 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char
        up_write(&dcssblk_devices_sem);
        return count;
 }
+static DEVICE_ATTR(save, S_IWUSR | S_IRUSR, dcssblk_save_show,
+                  dcssblk_save_store);
 
 /*
  * device attribute for showing all segments in a device
@@ -502,6 +492,21 @@ dcssblk_seglist_show(struct device *dev, struct device_attribute *attr,
        up_read(&dcssblk_devices_sem);
        return i;
 }
+static DEVICE_ATTR(seglist, S_IRUSR, dcssblk_seglist_show, NULL);
+
+static struct attribute *dcssblk_dev_attrs[] = {
+       &dev_attr_shared.attr,
+       &dev_attr_save.attr,
+       &dev_attr_seglist.attr,
+       NULL,
+};
+static struct attribute_group dcssblk_dev_attr_group = {
+       .attrs = dcssblk_dev_attrs,
+};
+static const struct attribute_group *dcssblk_dev_attr_groups[] = {
+       &dcssblk_dev_attr_group,
+       NULL,
+};
 
 /*
  * device attribute for adding devices
@@ -590,6 +595,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
 
        dev_set_name(&dev_info->dev, dev_info->segment_name);
        dev_info->dev.release = dcssblk_release_segment;
+       dev_info->dev.groups = dcssblk_dev_attr_groups;
        INIT_LIST_HEAD(&dev_info->lh);
        dev_info->gd = alloc_disk(DCSSBLK_MINORS_PER_DISK);
        if (dev_info->gd == NULL) {
@@ -637,21 +643,10 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
         * register the device
         */
        rc = device_register(&dev_info->dev);
-       if (rc) {
-               module_put(THIS_MODULE);
-               goto dev_list_del;
-       }
-       get_device(&dev_info->dev);
-       rc = device_create_file(&dev_info->dev, &dev_attr_shared);
-       if (rc)
-               goto unregister_dev;
-       rc = device_create_file(&dev_info->dev, &dev_attr_save);
-       if (rc)
-               goto unregister_dev;
-       rc = device_create_file(&dev_info->dev, &dev_attr_seglist);
        if (rc)
-               goto unregister_dev;
+               goto put_dev;
 
+       get_device(&dev_info->dev);
        add_disk(dev_info->gd);
 
        switch (dev_info->segment_type) {
@@ -668,12 +663,11 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
        rc = count;
        goto out;
 
-unregister_dev:
+put_dev:
        list_del(&dev_info->lh);
        blk_cleanup_queue(dev_info->dcssblk_queue);
        dev_info->gd->queue = NULL;
        put_disk(dev_info->gd);
-       device_unregister(&dev_info->dev);
        list_for_each_entry(seg_info, &dev_info->seg_list, lh) {
                segment_unload(seg_info->segment_name);
        }
index c7275e303a0d95074eefab828142c97406417c2b..899ffa19f5ecd1105e2844362d2a9eb2403b880d 100644 (file)
@@ -39,7 +39,6 @@
 #include "zcrypt_msgtype6.h"
 #include "zcrypt_pcixcc.h"
 #include "zcrypt_cca_key.h"
-#include "zcrypt_msgtype6.h"
 
 #define PCIXCC_MIN_MOD_SIZE     16     /*  128 bits    */
 #define PCIXCC_MIN_MOD_SIZE_OLD         64     /*  512 bits    */
index b7c326f7a6d0f3dc337d8b7b9c45bccb671cd186..342d7d9c0997a55c9b69f651d7827e0df027c5c8 100644 (file)
@@ -165,6 +165,16 @@ bfa_com_phy_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
        bfa_phy_memclaim(phy, phy_dma->kva_curp, phy_dma->dma_curp, mincfg);
 }
 
+static void
+bfa_com_fru_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
+{
+       struct bfa_fru_s        *fru = BFA_FRU(bfa);
+       struct bfa_mem_dma_s    *fru_dma = BFA_MEM_FRU_DMA(bfa);
+
+       bfa_fru_attach(fru, &bfa->ioc, bfa, bfa->trcmod, mincfg);
+       bfa_fru_memclaim(fru, fru_dma->kva_curp, fru_dma->dma_curp, mincfg);
+}
+
 /*
  * BFA IOC FC related definitions
  */
@@ -274,6 +284,15 @@ bfa_iocfc_sm_initing(struct bfa_iocfc_s *iocfc, enum iocfc_event event)
        case IOCFC_E_IOC_ENABLED:
                bfa_fsm_set_state(iocfc, bfa_iocfc_sm_dconf_read);
                break;
+
+       case IOCFC_E_DISABLE:
+               bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling);
+               break;
+
+       case IOCFC_E_STOP:
+               bfa_fsm_set_state(iocfc, bfa_iocfc_sm_stopping);
+               break;
+
        case IOCFC_E_IOC_FAILED:
                bfa_fsm_set_state(iocfc, bfa_iocfc_sm_init_failed);
                break;
@@ -298,6 +317,15 @@ bfa_iocfc_sm_dconf_read(struct bfa_iocfc_s *iocfc, enum iocfc_event event)
        case IOCFC_E_DCONF_DONE:
                bfa_fsm_set_state(iocfc, bfa_iocfc_sm_init_cfg_wait);
                break;
+
+       case IOCFC_E_DISABLE:
+               bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling);
+               break;
+
+       case IOCFC_E_STOP:
+               bfa_fsm_set_state(iocfc, bfa_iocfc_sm_stopping);
+               break;
+
        case IOCFC_E_IOC_FAILED:
                bfa_fsm_set_state(iocfc, bfa_iocfc_sm_init_failed);
                break;
@@ -322,6 +350,15 @@ bfa_iocfc_sm_init_cfg_wait(struct bfa_iocfc_s *iocfc, enum iocfc_event event)
        case IOCFC_E_CFG_DONE:
                bfa_fsm_set_state(iocfc, bfa_iocfc_sm_init_cfg_done);
                break;
+
+       case IOCFC_E_DISABLE:
+               bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling);
+               break;
+
+       case IOCFC_E_STOP:
+               bfa_fsm_set_state(iocfc, bfa_iocfc_sm_stopping);
+               break;
+
        case IOCFC_E_IOC_FAILED:
                bfa_fsm_set_state(iocfc, bfa_iocfc_sm_init_failed);
                break;
@@ -433,6 +470,12 @@ bfa_iocfc_sm_stopping(struct bfa_iocfc_s *iocfc, enum iocfc_event event)
                bfa_cb_queue(iocfc->bfa, &iocfc->bfa->iocfc.stop_hcb_qe,
                             bfa_iocfc_stop_cb, iocfc->bfa);
                break;
+
+       case IOCFC_E_IOC_ENABLED:
+       case IOCFC_E_DCONF_DONE:
+       case IOCFC_E_CFG_DONE:
+               break;
+
        default:
                bfa_sm_fault(iocfc->bfa, event);
                break;
@@ -454,6 +497,15 @@ bfa_iocfc_sm_enabling(struct bfa_iocfc_s *iocfc, enum iocfc_event event)
        case IOCFC_E_IOC_ENABLED:
                bfa_fsm_set_state(iocfc, bfa_iocfc_sm_cfg_wait);
                break;
+
+       case IOCFC_E_DISABLE:
+               bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling);
+               break;
+
+       case IOCFC_E_STOP:
+               bfa_fsm_set_state(iocfc, bfa_iocfc_sm_dconf_write);
+               break;
+
        case IOCFC_E_IOC_FAILED:
                bfa_fsm_set_state(iocfc, bfa_iocfc_sm_failed);
 
@@ -493,6 +545,13 @@ bfa_iocfc_sm_cfg_wait(struct bfa_iocfc_s *iocfc, enum iocfc_event event)
                             bfa_iocfc_enable_cb, iocfc->bfa);
                iocfc->bfa->iocfc.cb_reqd = BFA_FALSE;
                break;
+       case IOCFC_E_DISABLE:
+               bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling);
+               break;
+
+       case IOCFC_E_STOP:
+               bfa_fsm_set_state(iocfc, bfa_iocfc_sm_dconf_write);
+               break;
        case IOCFC_E_IOC_FAILED:
                bfa_fsm_set_state(iocfc, bfa_iocfc_sm_failed);
                if (iocfc->bfa->iocfc.cb_reqd == BFA_FALSE)
@@ -524,6 +583,10 @@ bfa_iocfc_sm_disabling(struct bfa_iocfc_s *iocfc, enum iocfc_event event)
        case IOCFC_E_IOC_DISABLED:
                bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabled);
                break;
+       case IOCFC_E_IOC_ENABLED:
+       case IOCFC_E_DCONF_DONE:
+       case IOCFC_E_CFG_DONE:
+               break;
        default:
                bfa_sm_fault(iocfc->bfa, event);
                break;
@@ -785,19 +848,20 @@ void
 bfa_isr_enable(struct bfa_s *bfa)
 {
        u32 umsk;
-       int pci_func = bfa_ioc_pcifn(&bfa->ioc);
+       int port_id = bfa_ioc_portid(&bfa->ioc);
 
-       bfa_trc(bfa, pci_func);
+       bfa_trc(bfa, bfa_ioc_pcifn(&bfa->ioc));
+       bfa_trc(bfa, port_id);
 
        bfa_msix_ctrl_install(bfa);
 
        if (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)) {
                umsk = __HFN_INT_ERR_MASK_CT2;
-               umsk |= pci_func == 0 ?
+               umsk |= port_id == 0 ?
                        __HFN_INT_FN0_MASK_CT2 : __HFN_INT_FN1_MASK_CT2;
        } else {
                umsk = __HFN_INT_ERR_MASK;
-               umsk |= pci_func == 0 ? __HFN_INT_FN0_MASK : __HFN_INT_FN1_MASK;
+               umsk |= port_id == 0 ? __HFN_INT_FN0_MASK : __HFN_INT_FN1_MASK;
        }
 
        writel(umsk, bfa->iocfc.bfa_regs.intr_status);
@@ -930,7 +994,8 @@ bfa_iocfc_send_cfg(void *bfa_arg)
                cfg_info->single_msix_vec = 1;
        cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;
        cfg_info->num_cqs = cfg->fwcfg.num_cqs;
-       cfg_info->num_ioim_reqs = cpu_to_be16(cfg->fwcfg.num_ioim_reqs);
+       cfg_info->num_ioim_reqs = cpu_to_be16(bfa_fcpim_get_throttle_cfg(bfa,
+                                              cfg->fwcfg.num_ioim_reqs));
        cfg_info->num_fwtio_reqs = cpu_to_be16(cfg->fwcfg.num_fwtio_reqs);
 
        bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);
@@ -1192,10 +1257,14 @@ bfa_iocfc_qreg(struct bfa_s *bfa, struct bfi_iocfc_qreg_s *qreg)
 static void
 bfa_iocfc_res_recfg(struct bfa_s *bfa, struct bfa_iocfc_fwcfg_s *fwcfg)
 {
+       struct bfa_iocfc_s      *iocfc   = &bfa->iocfc;
+       struct bfi_iocfc_cfg_s  *cfg_info = iocfc->cfginfo;
+
        bfa_fcxp_res_recfg(bfa, fwcfg->num_fcxp_reqs);
        bfa_uf_res_recfg(bfa, fwcfg->num_uf_bufs);
        bfa_rport_res_recfg(bfa, fwcfg->num_rports);
-       bfa_fcp_res_recfg(bfa, fwcfg->num_ioim_reqs);
+       bfa_fcp_res_recfg(bfa, cpu_to_be16(cfg_info->num_ioim_reqs),
+                         fwcfg->num_ioim_reqs);
        bfa_tskim_res_recfg(bfa, fwcfg->num_tskim_reqs);
 }
 
@@ -1693,6 +1762,7 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
        struct bfa_mem_dma_s *flash_dma = BFA_MEM_FLASH_DMA(bfa);
        struct bfa_mem_dma_s *diag_dma = BFA_MEM_DIAG_DMA(bfa);
        struct bfa_mem_dma_s *phy_dma = BFA_MEM_PHY_DMA(bfa);
+       struct bfa_mem_dma_s *fru_dma = BFA_MEM_FRU_DMA(bfa);
 
        WARN_ON((cfg == NULL) || (meminfo == NULL));
 
@@ -1717,6 +1787,8 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
        bfa_mem_dma_setup(meminfo, diag_dma, bfa_diag_meminfo());
        bfa_mem_dma_setup(meminfo, phy_dma,
                          bfa_phy_meminfo(cfg->drvcfg.min_cfg));
+       bfa_mem_dma_setup(meminfo, fru_dma,
+                         bfa_fru_meminfo(cfg->drvcfg.min_cfg));
 }
 
 /*
@@ -1789,6 +1861,7 @@ bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
        bfa_com_flash_attach(bfa, cfg->drvcfg.min_cfg);
        bfa_com_diag_attach(bfa);
        bfa_com_phy_attach(bfa, cfg->drvcfg.min_cfg);
+       bfa_com_fru_attach(bfa, cfg->drvcfg.min_cfg);
 }
 
 /*
index b5a1595cc0a523f6e71e8b1c8c438257c5897f70..0efdf312b42c4af85cce1ef461adc9ffb1aef51d 100644 (file)
@@ -159,10 +159,13 @@ enum bfa_status {
        BFA_STATUS_BEACON_ON    = 72,   /* Port Beacon already on */
        BFA_STATUS_ENOFSAVE     = 78,   /*  No saved firmware trace */
        BFA_STATUS_IOC_DISABLED = 82,   /* IOC is already disabled */
+       BFA_STATUS_ERROR_TRL_ENABLED  = 87,   /* TRL is enabled */
+       BFA_STATUS_ERROR_QOS_ENABLED  = 88,   /* QoS is enabled */
        BFA_STATUS_NO_SFP_DEV = 89,     /* No SFP device check or replace SFP */
        BFA_STATUS_MEMTEST_FAILED = 90, /* Memory test failed contact support */
        BFA_STATUS_LEDTEST_OP = 109, /* LED test is operating */
        BFA_STATUS_INVALID_MAC  = 134, /*  Invalid MAC address */
+       BFA_STATUS_CMD_NOTSUPP_CNA = 146, /* Command not supported for CNA */
        BFA_STATUS_PBC          = 154, /*  Operation not allowed for pre-boot
                                        *  configuration */
        BFA_STATUS_BAD_FWCFG = 156,     /* Bad firmware configuration */
@@ -184,6 +187,17 @@ enum bfa_status {
        BFA_STATUS_FAA_ACQ_ADDR = 200,  /* Acquiring addr */
        BFA_STATUS_ERROR_TRUNK_ENABLED = 203,   /* Trunk enabled on adapter */
        BFA_STATUS_MAX_ENTRY_REACHED = 212,     /* MAX entry reached */
+       BFA_STATUS_TOPOLOGY_LOOP = 230, /* Topology is set to Loop */
+       BFA_STATUS_LOOP_UNSUPP_MEZZ = 231, /* Loop topology is not supported
+                                           * on mezz cards */
+       BFA_STATUS_INVALID_BW = 233,    /* Invalid bandwidth value */
+       BFA_STATUS_QOS_BW_INVALID = 234,   /* Invalid QOS bandwidth
+                                           * configuration */
+       BFA_STATUS_DPORT_ENABLED = 235, /* D-port mode is already enabled */
+       BFA_STATUS_DPORT_DISABLED = 236, /* D-port mode is already disabled */
+       BFA_STATUS_CMD_NOTSUPP_MEZZ = 239, /* Cmd not supported for MEZZ card */
+       BFA_STATUS_FRU_NOT_PRESENT = 240, /* fru module not present */
+       BFA_STATUS_DPORT_ERR = 245,     /* D-port mode is enabled */
        BFA_STATUS_MAX_VAL              /* Unknown error code */
 };
 #define bfa_status_t enum bfa_status
@@ -249,6 +263,10 @@ struct bfa_adapter_attr_s {
 
        u8              is_mezz;
        u8              trunk_capable;
+       u8              mfg_day;        /* manufacturing day */
+       u8              mfg_month;      /* manufacturing month */
+       u16             mfg_year;       /* manufacturing year */
+       u16             rsvd;
 };
 
 /*
@@ -498,6 +516,17 @@ struct bfa_ioc_aen_data_s {
        mac_t   mac;
 };
 
+/*
+ *     D-port states
+ *
+*/
+enum bfa_dport_state {
+       BFA_DPORT_ST_DISABLED   = 0,    /* D-port is Disabled */
+       BFA_DPORT_ST_DISABLING  = 1,    /* D-port is Disabling */
+       BFA_DPORT_ST_ENABLING   = 2,    /* D-port is Enabling */
+       BFA_DPORT_ST_ENABLED    = 3,    /* D-port is Enabled */
+};
+
 /*
  * ---------------------- mfg definitions ------------
  */
@@ -722,7 +751,8 @@ struct bfa_ablk_cfg_pf_s {
        u8      rsvd[1];
        u16     num_qpairs;
        u16     num_vectors;
-       u32     bw;
+       u16     bw_min;
+       u16     bw_max;
 };
 
 struct bfa_ablk_cfg_port_s {
@@ -889,11 +919,40 @@ struct sfp_diag_ext_s {
        u8      ext_status_ctl[2];
 };
 
+/*
+ * Diagnostic: Data Fields -- Address A2h
+ * General Use Fields: User Writable Table - Features's Control Registers
+ * Total 32 bytes
+ */
+struct sfp_usr_eeprom_s {
+       u8      rsvd1[2];       /* 128-129 */
+       u8      ewrap;          /* 130 */
+       u8      rsvd2[2];       /*  */
+       u8      owrap;          /* 133 */
+       u8      rsvd3[2];       /*  */
+       u8      prbs;           /* 136: PRBS 7 generator */
+       u8      rsvd4[2];       /*  */
+       u8      tx_eqz_16;      /* 139: TX Equalizer (16xFC) */
+       u8      tx_eqz_8;       /* 140: TX Equalizer (8xFC) */
+       u8      rsvd5[2];       /*  */
+       u8      rx_emp_16;      /* 143: RX Emphasis (16xFC) */
+       u8      rx_emp_8;       /* 144: RX Emphasis (8xFC) */
+       u8      rsvd6[2];       /*  */
+       u8      tx_eye_adj;     /* 147: TX eye Threshold Adjust */
+       u8      rsvd7[3];       /*  */
+       u8      tx_eye_qctl;    /* 151: TX eye Quality Control */
+       u8      tx_eye_qres;    /* 152: TX eye Quality Result */
+       u8      rsvd8[2];       /*  */
+       u8      poh[3];         /* 155-157: Power On Hours */
+       u8      rsvd9[2];       /*  */
+};
+
 struct sfp_mem_s {
        struct sfp_srlid_base_s srlid_base;
        struct sfp_srlid_ext_s  srlid_ext;
        struct sfp_diag_base_s  diag_base;
        struct sfp_diag_ext_s   diag_ext;
+       struct sfp_usr_eeprom_s usr_eeprom;
 };
 
 /*
index 36756ce0e58f63dcb34736ef5834c7641bdcb323..ec03c8cd8dacd0ecb3961ba1233816880bc46c4a 100644 (file)
@@ -258,6 +258,7 @@ struct bfa_fw_port_lksm_stats_s {
        u32    hwsm_lrr_rx;        /*  No. of times LRR rx-ed by HWSM      */
        u32    hwsm_lr_rx;         /*  No. of times LR rx-ed by HWSM       */
        u32    bbsc_lr;            /* LKSM LR tx for credit recovery       */
+       u32     rsvd;
 };
 
 struct bfa_fw_port_snsm_stats_s {
@@ -270,6 +271,9 @@ struct bfa_fw_port_snsm_stats_s {
        u32    sync_lost;          /*  Sync loss count                     */
        u32    sig_lost;           /*  Signal loss count                   */
        u32    asn8g_attempts;     /* SNSM HWSM at 8Gbps attempts          */
+       u32    adapt_success;      /* SNSM adaptation success   */
+       u32    adapt_fails;        /* SNSM adaptation failures */
+       u32    adapt_ign_fails;    /* SNSM adaptation failures ignored */
 };
 
 struct bfa_fw_port_physm_stats_s {
@@ -324,12 +328,46 @@ struct bfa_fw_fcoe_port_stats_s {
        struct bfa_fw_fip_stats_s               fip_stats;
 };
 
+/**
+ * @brief LPSM statistics
+ */
+struct bfa_fw_lpsm_stats_s {
+       u32     cls_rx;         /* LPSM cls_rx                  */
+       u32     cls_tx;         /* LPSM cls_tx                  */
+       u32     arbf0_rx;       /* LPSM abrf0 rcvd              */
+       u32     arbf0_tx;       /* LPSM abrf0 xmit              */
+       u32     init_rx;        /* LPSM loop init start         */
+       u32     unexp_hwst;     /* LPSM unknown hw state        */
+       u32     unexp_frame;    /* LPSM unknown_frame           */
+       u32     unexp_prim;     /* LPSM unexpected primitive    */
+       u32     prev_alpa_unavail; /* LPSM prev alpa unavailable */
+       u32     alpa_unavail;   /* LPSM alpa not available      */
+       u32     lip_rx;         /* LPSM lip rcvd                */
+       u32     lip_f7f7_rx;    /* LPSM lip f7f7 rcvd           */
+       u32     lip_f8_rx;      /* LPSM lip f8 rcvd             */
+       u32     lip_f8f7_rx;    /* LPSM lip f8f7 rcvd           */
+       u32     lip_other_rx;   /* LPSM lip other rcvd          */
+       u32     lip_tx;         /* LPSM lip xmit                */
+       u32     retry_tov;      /* LPSM retry TOV               */
+       u32     lip_tov;        /* LPSM LIP wait TOV            */
+       u32     idle_tov;       /* LPSM idle wait TOV           */
+       u32     arbf0_tov;      /* LPSM arbfo wait TOV          */
+       u32     stop_loop_tov;  /* LPSM stop loop wait TOV      */
+       u32     lixa_tov;       /* LPSM lisa wait TOV           */
+       u32     lixx_tov;       /* LPSM lilp/lirp wait TOV      */
+       u32     cls_tov;        /* LPSM cls wait TOV            */
+       u32     sler;           /* LPSM SLER recvd              */
+       u32     failed;         /* LPSM failed                  */
+       u32     success;        /* LPSM online                  */
+};
+
 /*
  * IOC firmware FC uport stats
  */
 struct bfa_fw_fc_uport_stats_s {
        struct bfa_fw_port_snsm_stats_s         snsm_stats;
        struct bfa_fw_port_lksm_stats_s         lksm_stats;
+       struct bfa_fw_lpsm_stats_s              lpsm_stats;
 };
 
 /*
@@ -357,11 +395,6 @@ struct bfa_fw_fcxchg_stats_s {
        u32     ua_state_inv;
 };
 
-struct bfa_fw_lpsm_stats_s {
-       u32     cls_rx;
-       u32     cls_tx;
-};
-
 /*
  *  Trunk statistics
  */
@@ -454,7 +487,6 @@ struct bfa_fw_stats_s {
        struct bfa_fw_io_stats_s        io_stats;
        struct bfa_fw_port_stats_s      port_stats;
        struct bfa_fw_fcxchg_stats_s    fcxchg_stats;
-       struct bfa_fw_lpsm_stats_s      lpsm_stats;
        struct bfa_fw_lps_stats_s       lps_stats;
        struct bfa_fw_trunk_stats_s     trunk_stats;
        struct bfa_fw_advsm_stats_s     advsm_stats;
@@ -494,13 +526,23 @@ enum bfa_qos_bw_alloc {
        BFA_QOS_BW_LOW  =  10,  /*  bandwidth allocation for Low */
 };
 #pragma pack(1)
+
+struct bfa_qos_bw_s {
+       u8      qos_bw_set;
+       u8      high;
+       u8      med;
+       u8      low;
+};
+
 /*
  * QoS attribute returned in QoS Query
  */
 struct bfa_qos_attr_s {
-       u8              state;          /*  QoS current state */
-       u8              rsvd[3];
-       u32  total_bb_cr;               /*  Total BB Credits */
+       u8      state;          /*  QoS current state */
+       u8      rsvd1[3];
+       u32     total_bb_cr;    /*  Total BB Credits */
+       struct bfa_qos_bw_s qos_bw;     /* QOS bw cfg */
+       struct bfa_qos_bw_s qos_bw_op;  /* QOS bw operational */
 };
 
 /*
@@ -692,7 +734,8 @@ enum bfa_port_states {
        BFA_PORT_ST_FWMISMATCH          = 12,
        BFA_PORT_ST_PREBOOT_DISABLED    = 13,
        BFA_PORT_ST_TOGGLING_QWAIT      = 14,
-       BFA_PORT_ST_ACQ_ADDR            = 15,
+       BFA_PORT_ST_FAA_MISCONFIG       = 15,
+       BFA_PORT_ST_DPORT               = 16,
        BFA_PORT_ST_MAX_STATE,
 };
 
@@ -714,9 +757,11 @@ enum bfa_port_type {
  */
 enum bfa_port_topology {
        BFA_PORT_TOPOLOGY_NONE = 0,     /*  No valid topology */
-       BFA_PORT_TOPOLOGY_P2P  = 1,     /*  P2P only */
-       BFA_PORT_TOPOLOGY_LOOP = 2,     /*  LOOP topology */
-       BFA_PORT_TOPOLOGY_AUTO = 3,     /*  auto topology selection */
+       BFA_PORT_TOPOLOGY_P2P_OLD_VER = 1, /* P2P def for older ver */
+       BFA_PORT_TOPOLOGY_LOOP = 2,     /* LOOP topology */
+       BFA_PORT_TOPOLOGY_AUTO_OLD_VER = 3, /* auto def for older ver */
+       BFA_PORT_TOPOLOGY_AUTO = 4,     /* auto topology selection */
+       BFA_PORT_TOPOLOGY_P2P = 5,      /* P2P only */
 };
 
 /*
@@ -760,6 +805,7 @@ enum bfa_port_linkstate_rsn {
        BFA_PORT_LINKSTATE_RSN_LOCAL_FAULT      = 9,
        BFA_PORT_LINKSTATE_RSN_REMOTE_FAULT     = 10,
        BFA_PORT_LINKSTATE_RSN_TIMEOUT          = 11,
+       BFA_PORT_LINKSTATE_RSN_FAA_MISCONFIG    = 12,
 
 
 
@@ -833,6 +879,19 @@ struct bfa_lunmask_cfg_s {
        struct bfa_lun_mask_s   lun_list[MAX_LUN_MASK_CFG];
 };
 
+struct bfa_throttle_cfg_s {
+       u16     is_valid;
+       u16     value;
+       u32     rsvd;
+};
+
+struct bfa_defs_fcpim_throttle_s {
+       u16     max_value;
+       u16     cur_value;
+       u16     cfg_value;
+       u16     rsvd;
+};
+
 /*
  *      Physical port configuration
  */
@@ -851,9 +910,10 @@ struct bfa_port_cfg_s {
        u8       bb_scn;        /*  BB_SCN value from FLOGI Exchg */
        u8       bb_scn_state;  /*  Config state of BB_SCN */
        u8       faa_state;     /*  FAA enabled/disabled        */
-       u8       rsvd[1];
+       u8       rsvd1;
        u16      path_tov;      /*  device path timeout */
        u16      q_depth;       /*  SCSI Queue depth            */
+       struct bfa_qos_bw_s qos_bw;     /* QOS bandwidth        */
 };
 #pragma pack()
 
@@ -901,7 +961,7 @@ struct bfa_port_attr_s {
 
        /* FCoE specific  */
        u16                     fcoe_vlan;
-       u8                      rsvd1[2];
+       u8                      rsvd1[6];
 };
 
 /*
@@ -971,6 +1031,13 @@ struct bfa_trunk_vc_attr_s {
        u16 vc_credits[8];
 };
 
+struct bfa_fcport_loop_info_s {
+       u8      myalpa;         /* alpa claimed */
+       u8      alpabm_val;     /* alpa bitmap valid or not (1 or 0) */
+       u8      resvd[6];
+       struct fc_alpabm_s alpabm;      /* alpa bitmap */
+};
+
 /*
  *     Link state information
  */
@@ -981,13 +1048,18 @@ struct bfa_port_link_s {
        u8       speed;         /*  Link speed (1/2/4/8 G) */
        u32      linkstate_opt; /*  Linkstate optional data (debug) */
        u8       trunked;       /*  Trunked or not (1 or 0) */
-       u8       resvd[3];
+       u8       resvd[7];
        struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
        union {
-               struct bfa_qos_vc_attr_s qos_vc_attr;  /*  VC info from ELP */
-               struct bfa_trunk_vc_attr_s trunk_vc_attr;
-               struct bfa_fcport_fcf_s fcf; /*  FCF information (for FCoE) */
-       } vc_fcf;
+               struct bfa_fcport_loop_info_s loop_info;
+               union {
+                       struct bfa_qos_vc_attr_s qos_vc_attr;
+                                       /*  VC info from ELP */
+                       struct bfa_trunk_vc_attr_s trunk_vc_attr;
+                       struct bfa_fcport_fcf_s fcf;
+                                       /*  FCF information (for FCoE) */
+               } vc_fcf;
+       } attr;
 };
 #pragma pack()
 
@@ -1112,6 +1184,9 @@ struct bfa_port_fc_stats_s {
        u64     tx_frames;      /*  Tx frames                   */
        u64     tx_words;       /*  Tx words                    */
        u64     tx_lip;         /*  Tx LIP                      */
+       u64     tx_lip_f7f7;    /*  Tx LIP_F7F7         */
+       u64     tx_lip_f8f7;    /*  Tx LIP_F8F7         */
+       u64     tx_arbf0;       /*  Tx ARB F0                   */
        u64     tx_nos;         /*  Tx NOS                      */
        u64     tx_ols;         /*  Tx OLS                      */
        u64     tx_lr;          /*  Tx LR                       */
@@ -1119,6 +1194,9 @@ struct bfa_port_fc_stats_s {
        u64     rx_frames;      /*  Rx frames                   */
        u64     rx_words;       /*  Rx words                    */
        u64     lip_count;      /*  Rx LIP                      */
+       u64     rx_lip_f7f7;    /*  Rx LIP_F7F7         */
+       u64     rx_lip_f8f7;    /*  Rx LIP_F8F7         */
+       u64     rx_arbf0;       /*  Rx ARB F0                   */
        u64     nos_count;      /*  Rx NOS                      */
        u64     ols_count;      /*  Rx OLS                      */
        u64     lr_count;       /*  Rx LR                       */
@@ -1140,6 +1218,7 @@ struct bfa_port_fc_stats_s {
        u64     bbsc_frames_lost; /* Credit Recovery-Frames Lost  */
        u64     bbsc_credits_lost; /* Credit Recovery-Credits Lost */
        u64     bbsc_link_resets; /* Credit Recovery-Link Resets   */
+       u64     loop_timeouts;  /*  Loop timeouts               */
 };
 
 /*
index e0beb4d7e26443c8881abc3ba66f59b7ac773f87..bea821b9803041086339c3e0b5973ab1df0893d5 100644 (file)
@@ -24,6 +24,7 @@ typedef u64 wwn_t;
 
 #define WWN_NULL       (0)
 #define FC_SYMNAME_MAX 256     /*  max name server symbolic name size */
+#define FC_ALPA_MAX    128
 
 #pragma pack(1)
 
@@ -1015,6 +1016,10 @@ struct fc_symname_s {
        u8         symname[FC_SYMNAME_MAX];
 };
 
+struct fc_alpabm_s {
+       u8      alpa_bm[FC_ALPA_MAX / 8];
+};
+
 /*
  * protocol default timeout values
  */
index 273cee90b3b429166ef8259a81a60aad0a865dc4..dce787f6cca2e421169e8f80b4f9a228b0f1bf4f 100644 (file)
@@ -228,6 +228,10 @@ fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
 
        memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s));
 
+       /* For FC AL bb_cr is 0 and altbbcred is 1 */
+       if (!bb_cr)
+               plogi->csp.altbbcred = 1;
+
        plogi->els_cmd.els_code = els_code;
        if (els_code == FC_ELS_PLOGI)
                fc_els_req_build(fchs, d_id, s_id, ox_id);
index 1633963c66cac646cea41c4a1ba7a386873fa4c7..27b560962357b7da7ca49d5b2be6660d3d45c429 100644 (file)
@@ -158,6 +158,7 @@ enum bfa_tskim_event {
        BFA_TSKIM_SM_IOS_DONE   = 7,    /*  IO and sub TM completions   */
        BFA_TSKIM_SM_CLEANUP    = 8,    /*  TM cleanup on ITN offline   */
        BFA_TSKIM_SM_CLEANUP_DONE = 9,  /*  TM abort completion */
+       BFA_TSKIM_SM_UTAG       = 10,   /*  TM completion unknown tag  */
 };
 
 /*
@@ -3036,7 +3037,7 @@ bfa_ioim_abort(struct bfa_ioim_s *ioim)
 static void
 bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
 {
-       bfa_trc(tskim->bfa, event);
+       bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
 
        switch (event) {
        case BFA_TSKIM_SM_START:
@@ -3074,7 +3075,7 @@ bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
 static void
 bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
 {
-       bfa_trc(tskim->bfa, event);
+       bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
 
        switch (event) {
        case BFA_TSKIM_SM_DONE:
@@ -3110,7 +3111,7 @@ bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
 static void
 bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
 {
-       bfa_trc(tskim->bfa, event);
+       bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
 
        switch (event) {
        case BFA_TSKIM_SM_DONE:
@@ -3119,6 +3120,7 @@ bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
                 */
                break;
 
+       case BFA_TSKIM_SM_UTAG:
        case BFA_TSKIM_SM_CLEANUP_DONE:
                bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
                bfa_tskim_cleanup_ios(tskim);
@@ -3138,7 +3140,7 @@ bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
 static void
 bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
 {
-       bfa_trc(tskim->bfa, event);
+       bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
 
        switch (event) {
        case BFA_TSKIM_SM_IOS_DONE:
@@ -3170,7 +3172,7 @@ bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
 static void
 bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
 {
-       bfa_trc(tskim->bfa, event);
+       bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
 
        switch (event) {
        case BFA_TSKIM_SM_QRESUME:
@@ -3207,7 +3209,7 @@ static void
 bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
                enum bfa_tskim_event event)
 {
-       bfa_trc(tskim->bfa, event);
+       bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
 
        switch (event) {
        case BFA_TSKIM_SM_DONE:
@@ -3238,7 +3240,7 @@ bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
 static void
 bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
 {
-       bfa_trc(tskim->bfa, event);
+       bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
 
        switch (event) {
        case BFA_TSKIM_SM_HCB:
@@ -3560,6 +3562,8 @@ bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
        if (rsp->tsk_status == BFI_TSKIM_STS_ABORTED) {
                bfa_stats(tskim->itnim, tm_cleanup_comps);
                bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP_DONE);
+       } else if (rsp->tsk_status == BFI_TSKIM_STS_UTAG) {
+               bfa_sm_send_event(tskim, BFA_TSKIM_SM_UTAG);
        } else {
                bfa_stats(tskim->itnim, tm_fw_rsps);
                bfa_sm_send_event(tskim, BFA_TSKIM_SM_DONE);
@@ -3699,6 +3703,7 @@ bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
        struct bfa_mem_dma_s *seg_ptr;
        u16     idx, nsegs, num_io_req;
 
+       fcp->max_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
        fcp->num_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
        fcp->num_fwtio_reqs  = cfg->fwcfg.num_fwtio_reqs;
        fcp->num_itns   = cfg->fwcfg.num_rports;
@@ -3721,6 +3726,7 @@ bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
                bfa_iocfc_set_snsbase(bfa, idx, fcp->snsbase[idx].pa);
        }
 
+       fcp->throttle_update_required = 1;
        bfa_fcpim_attach(fcp, bfad, cfg, pcidev);
 
        bfa_iotag_attach(fcp);
@@ -3759,23 +3765,33 @@ bfa_fcp_iocdisable(struct bfa_s *bfa)
 {
        struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
 
-       /* Enqueue unused ioim resources to free_q */
-       list_splice_tail_init(&fcp->iotag_unused_q, &fcp->iotag_ioim_free_q);
-
        bfa_fcpim_iocdisable(fcp);
 }
 
 void
-bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw)
+bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw, u16 max_ioim_fw)
 {
        struct bfa_fcp_mod_s    *mod = BFA_FCP_MOD(bfa);
        struct list_head        *qe;
        int     i;
 
+       /* Update io throttle value only once during driver load time */
+       if (!mod->throttle_update_required)
+               return;
+
        for (i = 0; i < (mod->num_ioim_reqs - num_ioim_fw); i++) {
                bfa_q_deq_tail(&mod->iotag_ioim_free_q, &qe);
                list_add_tail(qe, &mod->iotag_unused_q);
        }
+
+       if (mod->num_ioim_reqs != num_ioim_fw) {
+               bfa_trc(bfa, mod->num_ioim_reqs);
+               bfa_trc(bfa, num_ioim_fw);
+       }
+
+       mod->max_ioim_reqs = max_ioim_fw;
+       mod->num_ioim_reqs = num_ioim_fw;
+       mod->throttle_update_required = 0;
 }
 
 void
@@ -3833,3 +3849,88 @@ bfa_iotag_attach(struct bfa_fcp_mod_s *fcp)
 
        bfa_mem_kva_curp(fcp) = (u8 *) iotag;
 }
+
+
+/**
+ * To send config req, first try to use throttle value from flash
+ * If 0, then use driver parameter
+ * We need to use min(flash_val, drv_val) because
+ * memory allocation was done based on this cfg'd value
+ */
+u16
+bfa_fcpim_get_throttle_cfg(struct bfa_s *bfa, u16 drv_cfg_param)
+{
+       u16 tmp;
+       struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+
+       /*
+        * If throttle value from flash is already in effect after driver is
+        * loaded then until next load, always return current value instead
+        * of actual flash value
+        */
+       if (!fcp->throttle_update_required)
+               return (u16)fcp->num_ioim_reqs;
+
+       tmp = bfa_dconf_read_data_valid(bfa) ? bfa_fcpim_read_throttle(bfa) : 0;
+       if (!tmp || (tmp > drv_cfg_param))
+               tmp = drv_cfg_param;
+
+       return tmp;
+}
+
+bfa_status_t
+bfa_fcpim_write_throttle(struct bfa_s *bfa, u16 value)
+{
+       if (!bfa_dconf_get_min_cfg(bfa)) {
+               BFA_DCONF_MOD(bfa)->dconf->throttle_cfg.value = value;
+               BFA_DCONF_MOD(bfa)->dconf->throttle_cfg.is_valid = 1;
+               return BFA_STATUS_OK;
+       }
+
+       return BFA_STATUS_FAILED;
+}
+
+u16
+bfa_fcpim_read_throttle(struct bfa_s *bfa)
+{
+       struct bfa_throttle_cfg_s *throttle_cfg =
+                       &(BFA_DCONF_MOD(bfa)->dconf->throttle_cfg);
+
+       return ((!bfa_dconf_get_min_cfg(bfa)) ?
+              ((throttle_cfg->is_valid == 1) ? (throttle_cfg->value) : 0) : 0);
+}
+
+bfa_status_t
+bfa_fcpim_throttle_set(struct bfa_s *bfa, u16 value)
+{
+       /* in min cfg no commands should run. */
+       if ((bfa_dconf_get_min_cfg(bfa) == BFA_TRUE) ||
+           (!bfa_dconf_read_data_valid(bfa)))
+               return BFA_STATUS_FAILED;
+
+       bfa_fcpim_write_throttle(bfa, value);
+
+       return bfa_dconf_update(bfa);
+}
+
+bfa_status_t
+bfa_fcpim_throttle_get(struct bfa_s *bfa, void *buf)
+{
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
+       struct bfa_defs_fcpim_throttle_s throttle;
+
+       if ((bfa_dconf_get_min_cfg(bfa) == BFA_TRUE) ||
+           (!bfa_dconf_read_data_valid(bfa)))
+               return BFA_STATUS_FAILED;
+
+       memset(&throttle, 0, sizeof(struct bfa_defs_fcpim_throttle_s));
+
+       throttle.cur_value = (u16)(fcpim->fcp->num_ioim_reqs);
+       throttle.cfg_value = bfa_fcpim_read_throttle(bfa);
+       if (!throttle.cfg_value)
+               throttle.cfg_value = throttle.cur_value;
+       throttle.max_value = (u16)(fcpim->fcp->max_ioim_reqs);
+       memcpy(buf, &throttle, sizeof(struct bfa_defs_fcpim_throttle_s));
+
+       return BFA_STATUS_OK;
+}
index 36f26da80f76c1c496ec20bc1e42ae93e878df11..e693af6e59300aef03127dcd6c2d62e000e1c1c9 100644 (file)
@@ -42,7 +42,7 @@ void bfa_itn_create(struct bfa_s *bfa, struct bfa_rport_s *rport,
                void (*isr)(struct bfa_s *bfa, struct bfi_msg_s *m));
 void bfa_itn_isr(struct bfa_s *bfa, struct bfi_msg_s *m);
 void bfa_iotag_attach(struct bfa_fcp_mod_s *fcp);
-void bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw);
+void bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw, u16 max_ioim_fw);
 
 #define BFA_FCP_MOD(_hal)      (&(_hal)->modules.fcp_mod)
 #define BFA_MEM_FCP_KVA(__bfa) (&(BFA_FCP_MOD(__bfa)->kva_seg))
@@ -51,7 +51,9 @@ void bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw);
 #define BFA_ITN_FROM_TAG(_fcp, _tag)   \
        ((_fcp)->itn_arr + ((_tag) & ((_fcp)->num_itns - 1)))
 #define BFA_SNSINFO_FROM_TAG(_fcp, _tag) \
-       bfa_mem_get_dmabuf_kva(_fcp, _tag, BFI_IOIM_SNSLEN)
+       bfa_mem_get_dmabuf_kva(_fcp, (_tag & BFA_IOIM_IOTAG_MASK),      \
+       BFI_IOIM_SNSLEN)
+
 
 #define BFA_ITNIM_MIN   32
 #define BFA_ITNIM_MAX   1024
@@ -148,6 +150,7 @@ struct bfa_fcp_mod_s {
        struct list_head        iotag_unused_q; /* unused IO resources*/
        struct bfa_iotag_s      *iotag_arr;
        struct bfa_itn_s        *itn_arr;
+       int                     max_ioim_reqs;
        int                     num_ioim_reqs;
        int                     num_fwtio_reqs;
        int                     num_itns;
@@ -155,6 +158,7 @@ struct bfa_fcp_mod_s {
        struct bfa_fcpim_s      fcpim;
        struct bfa_mem_dma_s    dma_seg[BFA_FCP_DMA_SEGS];
        struct bfa_mem_kva_s    kva_seg;
+       int                     throttle_update_required;
 };
 
 /*
@@ -416,5 +420,10 @@ bfa_status_t       bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id,
 bfa_status_t   bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id,
                                wwn_t *pwwn, wwn_t rpwwn, struct scsi_lun lun);
 bfa_status_t   bfa_fcpim_lunmask_clear(struct bfa_s *bfa);
+u16            bfa_fcpim_read_throttle(struct bfa_s *bfa);
+bfa_status_t   bfa_fcpim_write_throttle(struct bfa_s *bfa, u16 value);
+bfa_status_t   bfa_fcpim_throttle_set(struct bfa_s *bfa, u16 value);
+bfa_status_t   bfa_fcpim_throttle_get(struct bfa_s *bfa, void *buf);
+u16     bfa_fcpim_get_throttle_cfg(struct bfa_s *bfa, u16 drv_cfg_param);
 
 #endif /* __BFA_FCPIM_H__ */
index fd3e84d32bd2fed636b61a443f32ebe71f3c54a1..d428808fb37ef7cb0ec1f3cfb41d4bedf974e014 100644 (file)
@@ -303,16 +303,30 @@ static void
 bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
                          enum bfa_fcs_fabric_event event)
 {
+       struct bfa_s    *bfa = fabric->fcs->bfa;
+
        bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
        bfa_trc(fabric->fcs, event);
 
        switch (event) {
        case BFA_FCS_FABRIC_SM_START:
-               if (bfa_fcport_is_linkup(fabric->fcs->bfa)) {
+               if (!bfa_fcport_is_linkup(fabric->fcs->bfa)) {
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+                       break;
+               }
+               if (bfa_fcport_get_topology(bfa) ==
+                               BFA_PORT_TOPOLOGY_LOOP) {
+                       fabric->fab_type = BFA_FCS_FABRIC_LOOP;
+                       fabric->bport.pid = bfa_fcport_get_myalpa(bfa);
+                       fabric->bport.pid = bfa_hton3b(fabric->bport.pid);
+                       bfa_sm_set_state(fabric,
+                                       bfa_fcs_fabric_sm_online);
+                       bfa_fcs_fabric_set_opertype(fabric);
+                       bfa_fcs_lport_online(&fabric->bport);
+               } else {
                        bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
                        bfa_fcs_fabric_login(fabric);
-               } else
-                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+               }
                break;
 
        case BFA_FCS_FABRIC_SM_LINK_UP:
@@ -337,16 +351,28 @@ static void
 bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
                           enum bfa_fcs_fabric_event event)
 {
+       struct bfa_s    *bfa = fabric->fcs->bfa;
+
        bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
        bfa_trc(fabric->fcs, event);
 
        switch (event) {
        case BFA_FCS_FABRIC_SM_LINK_UP:
-               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
-               bfa_fcs_fabric_login(fabric);
+               if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP) {
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
+                       bfa_fcs_fabric_login(fabric);
+                       break;
+               }
+               fabric->fab_type = BFA_FCS_FABRIC_LOOP;
+               fabric->bport.pid = bfa_fcport_get_myalpa(bfa);
+               fabric->bport.pid = bfa_hton3b(fabric->bport.pid);
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
+               bfa_fcs_fabric_set_opertype(fabric);
+               bfa_fcs_lport_online(&fabric->bport);
                break;
 
        case BFA_FCS_FABRIC_SM_RETRY_OP:
+       case BFA_FCS_FABRIC_SM_LOOPBACK:
                break;
 
        case BFA_FCS_FABRIC_SM_DELETE:
@@ -595,14 +621,20 @@ void
 bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
                         enum bfa_fcs_fabric_event event)
 {
+       struct bfa_s    *bfa = fabric->fcs->bfa;
+
        bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
        bfa_trc(fabric->fcs, event);
 
        switch (event) {
        case BFA_FCS_FABRIC_SM_LINK_DOWN:
                bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-               bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
-               bfa_fcs_fabric_notify_offline(fabric);
+               if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) {
+                       bfa_fcs_lport_offline(&fabric->bport);
+               } else {
+                       bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
+                       bfa_fcs_fabric_notify_offline(fabric);
+               }
                break;
 
        case BFA_FCS_FABRIC_SM_DELETE:
@@ -719,20 +751,29 @@ static void
 bfa_fcs_fabric_sm_stopping(struct bfa_fcs_fabric_s *fabric,
                           enum bfa_fcs_fabric_event event)
 {
+       struct bfa_s    *bfa = fabric->fcs->bfa;
+
        bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
        bfa_trc(fabric->fcs, event);
 
        switch (event) {
        case BFA_FCS_FABRIC_SM_STOPCOMP:
-               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
-               bfa_sm_send_event(fabric->lps, BFA_LPS_SM_LOGOUT);
+               if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) {
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
+               } else {
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
+                       bfa_sm_send_event(fabric->lps, BFA_LPS_SM_LOGOUT);
+               }
                break;
 
        case BFA_FCS_FABRIC_SM_LINK_UP:
                break;
 
        case BFA_FCS_FABRIC_SM_LINK_DOWN:
-               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
+               if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
+               else
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
                break;
 
        default:
@@ -975,9 +1016,6 @@ bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
        struct bfa_lport_cfg_s  *pcfg = &fabric->bport.port_cfg;
        u8                      alpa = 0, bb_scn = 0;
 
-       if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
-               alpa = bfa_fcport_get_myalpa(bfa);
-
        if (bfa_fcs_fabric_is_bbscn_enabled(fabric) &&
            (!fabric->fcs->bbscn_flogi_rjt))
                bb_scn = BFA_FCS_PORT_DEF_BB_SCN;
index 6c4377cb287f1eec93791c8d56bd401c28a5f731..a449706c6bc09d803d53dcf2dc4d5fcc3cb8894c 100644 (file)
@@ -118,9 +118,9 @@ struct bfa_fcs_lport_fab_s {
 #define        MAX_ALPA_COUNT  127
 
 struct bfa_fcs_lport_loop_s {
-       u8         num_alpa;    /*  Num of ALPA entries in the map */
-       u8         alpa_pos_map[MAX_ALPA_COUNT];        /*  ALPA Positional
-                                                        *Map */
+       u8      num_alpa;       /*  Num of ALPA entries in the map */
+       u8      alpabm_valid;   /* alpa bitmap valid or not (1 or 0) */
+       u8      alpa_pos_map[MAX_ALPA_COUNT]; /*  ALPA Positional Map */
        struct bfa_fcs_lport_s *port;   /*  parent port */
 };
 
@@ -175,6 +175,7 @@ enum bfa_fcs_fabric_type {
        BFA_FCS_FABRIC_UNKNOWN = 0,
        BFA_FCS_FABRIC_SWITCHED = 1,
        BFA_FCS_FABRIC_N2N = 2,
+       BFA_FCS_FABRIC_LOOP = 3,
 };
 
 
@@ -350,9 +351,10 @@ void               bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg,
                                struct bfa_fcxp_s *fcxp_alloced);
 void            bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *vport);
 void            bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *vport);
-void            bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *vport);
+void            bfa_fcs_lport_fab_scn_online(struct bfa_fcs_lport_s *vport);
 void            bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
                                              struct fchs_s *rx_frame, u32 len);
+void           bfa_fcs_lport_lip_scn_online(bfa_fcs_lport_t *port);
 
 struct bfa_fcs_vport_s {
        struct list_head                qe;             /*  queue elem  */
@@ -453,6 +455,7 @@ struct bfa_fcs_rport_s {
        struct bfa_rport_stats_s stats; /*  rport stats */
        enum bfa_rport_function scsi_function;  /*  Initiator/Target */
        struct bfa_fcs_rpf_s rpf;       /* Rport features module */
+       bfa_boolean_t   scn_online;     /* SCN online flag */
 };
 
 static inline struct bfa_rport_s *
@@ -639,9 +642,9 @@ struct bfa_fcs_fdmi_hba_attr_s {
        u8         model[16];
        u8         model_desc[256];
        u8         hw_version[8];
-       u8         driver_version[8];
+       u8         driver_version[BFA_VERSION_LEN];
        u8         option_rom_ver[BFA_VERSION_LEN];
-       u8         fw_version[8];
+       u8         fw_version[BFA_VERSION_LEN];
        u8         os_name[256];
        __be32        max_ct_pyld;
 };
@@ -733,7 +736,7 @@ enum rport_event {
        RPSM_EVENT_LOGO_IMP     = 5,    /*  implicit logo for SLER      */
        RPSM_EVENT_FCXP_SENT    = 6,    /*  Frame from has been sent    */
        RPSM_EVENT_DELETE       = 7,    /*  RPORT delete request        */
-       RPSM_EVENT_SCN          = 8,    /*  state change notification   */
+       RPSM_EVENT_FAB_SCN      = 8,    /*  state change notification   */
        RPSM_EVENT_ACCEPTED     = 9,    /*  Good response from remote device */
        RPSM_EVENT_FAILED       = 10,   /*  Request to rport failed.    */
        RPSM_EVENT_TIMEOUT      = 11,   /*  Rport SM timeout event      */
@@ -744,7 +747,9 @@ enum rport_event {
        RPSM_EVENT_ADDRESS_DISC = 16,   /*  Need to Discover rport's PID */
        RPSM_EVENT_PRLO_RCVD   = 17,    /*  PRLO from remote device     */
        RPSM_EVENT_PLOGI_RETRY = 18,    /*  Retry PLOGI continuously */
-       RPSM_EVENT_FC4_FCS_ONLINE = 19, /*!< FC-4 FCS online complete */
+       RPSM_EVENT_SCN_OFFLINE = 19,    /* loop scn offline             */
+       RPSM_EVENT_SCN_ONLINE   = 20,   /* loop scn online              */
+       RPSM_EVENT_FC4_FCS_ONLINE = 21, /* FC-4 FCS online complete */
 };
 
 /*
@@ -763,7 +768,7 @@ enum bfa_fcs_itnim_event {
        BFA_FCS_ITNIM_SM_DELETE = 10,   /*  delete event from rport */
        BFA_FCS_ITNIM_SM_PRLO = 11,     /*  delete event from rport */
        BFA_FCS_ITNIM_SM_RSP_NOT_SUPP = 12, /* cmd not supported rsp */
-       BFA_FCS_ITNIM_SM_HAL_ONLINE = 13, /*!< bfa rport online event */
+       BFA_FCS_ITNIM_SM_HAL_ONLINE = 13, /* bfa rport online event */
 };
 
 /*
index 3b75f6fb2de1fbf29b189715e5a3af9d17283343..1224d0462a491a5911fa3eda6d37d36a1ec7caf2 100644 (file)
 
 BFA_TRC_FILE(FCS, PORT);
 
+/*
+ * ALPA to LIXA bitmap mapping
+ *
+ * ALPA 0x00 (Word 0, Bit 30) is invalid for N_Ports. Also Word 0 Bit 31
+ * is for L_bit (login required) and is filled as ALPA 0x00 here.
+ */
+static const u8 loop_alpa_map[] = {
+       0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x0F, 0x10, /* Word 0 Bits 31..24 */
+       0x17, 0x18, 0x1B, 0x1D, 0x1E, 0x1F, 0x23, 0x25, /* Word 0 Bits 23..16 */
+       0x26, 0x27, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, /* Word 0 Bits 15..08 */
+       0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x39, 0x3A, /* Word 0 Bits 07..00 */
+
+       0x3C, 0x43, 0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, /* Word 1 Bits 31..24 */
+       0x4C, 0x4D, 0x4E, 0x51, 0x52, 0x53, 0x54, 0x55, /* Word 1 Bits 23..16 */
+       0x56, 0x59, 0x5A, 0x5C, 0x63, 0x65, 0x66, 0x67, /* Word 1 Bits 15..08 */
+       0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x71, 0x72, /* Word 1 Bits 07..00 */
+
+       0x73, 0x74, 0x75, 0x76, 0x79, 0x7A, 0x7C, 0x80, /* Word 2 Bits 31..24 */
+       0x81, 0x82, 0x84, 0x88, 0x8F, 0x90, 0x97, 0x98, /* Word 2 Bits 23..16 */
+       0x9B, 0x9D, 0x9E, 0x9F, 0xA3, 0xA5, 0xA6, 0xA7, /* Word 2 Bits 15..08 */
+       0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xB1, 0xB2, /* Word 2 Bits 07..00 */
+
+       0xB3, 0xB4, 0xB5, 0xB6, 0xB9, 0xBA, 0xBC, 0xC3, /* Word 3 Bits 31..24 */
+       0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, /* Word 3 Bits 23..16 */
+       0xCE, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD9, /* Word 3 Bits 15..08 */
+       0xDA, 0xDC, 0xE0, 0xE1, 0xE2, 0xE4, 0xE8, 0xEF, /* Word 3 Bits 07..00 */
+};
+
 static void     bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
                                         struct fchs_s *rx_fchs, u8 reason_code,
                                         u8 reason_code_expl);
@@ -51,6 +79,10 @@ static void  bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
 static void    bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
 static void    bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
 
+static void    bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port);
+static void    bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port);
+static void    bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port);
+
 static struct {
        void            (*init) (struct bfa_fcs_lport_s *port);
        void            (*online) (struct bfa_fcs_lport_s *port);
@@ -62,7 +94,9 @@ static struct {
        bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
                        bfa_fcs_lport_fab_offline}, {
        bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
-                       bfa_fcs_lport_n2n_offline},
+                       bfa_fcs_lport_n2n_offline}, {
+       bfa_fcs_lport_loop_init, bfa_fcs_lport_loop_online,
+                       bfa_fcs_lport_loop_offline},
        };
 
 /*
@@ -1127,7 +1161,7 @@ static void
 bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
 {
        bfa_fcs_lport_ns_online(port);
-       bfa_fcs_lport_scn_online(port);
+       bfa_fcs_lport_fab_scn_online(port);
 }
 
 /*
@@ -1221,6 +1255,98 @@ bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
        n2n_port->reply_oxid = 0;
 }
 
+void
+bfa_fcport_get_loop_attr(struct bfa_fcs_lport_s *port)
+{
+       int i = 0, j = 0, bit = 0, alpa_bit = 0;
+       u8 k = 0;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(port->fcs->bfa);
+
+       port->port_topo.ploop.alpabm_valid = fcport->alpabm_valid;
+       port->pid = fcport->myalpa;
+       port->pid = bfa_hton3b(port->pid);
+
+       for (i = 0; i < (FC_ALPA_MAX / 8); i++) {
+               for (j = 0, alpa_bit = 0; j < 8; j++, alpa_bit++) {
+                       bfa_trc(port->fcs->bfa, fcport->alpabm.alpa_bm[i]);
+                       bit = (fcport->alpabm.alpa_bm[i] & (1 << (7 - j)));
+                       if (bit) {
+                               port->port_topo.ploop.alpa_pos_map[k] =
+                                       loop_alpa_map[(i * 8) + alpa_bit];
+                               k++;
+                               bfa_trc(port->fcs->bfa, k);
+                               bfa_trc(port->fcs->bfa,
+                                        port->port_topo.ploop.alpa_pos_map[k]);
+                       }
+               }
+       }
+       port->port_topo.ploop.num_alpa = k;
+}
+
+/*
+ * Called by fcs/port to initialize Loop topology.
+ */
+static void
+bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port)
+{
+}
+
+/*
+ * Called by fcs/port to notify transition to online state.
+ */
+static void
+bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port)
+{
+       u8 num_alpa = 0, alpabm_valid = 0;
+       struct bfa_fcs_rport_s *rport;
+       u8 *alpa_map = NULL;
+       int i = 0;
+       u32 pid;
+
+       bfa_fcport_get_loop_attr(port);
+
+       num_alpa = port->port_topo.ploop.num_alpa;
+       alpabm_valid = port->port_topo.ploop.alpabm_valid;
+       alpa_map = port->port_topo.ploop.alpa_pos_map;
+
+       bfa_trc(port->fcs->bfa, port->pid);
+       bfa_trc(port->fcs->bfa, num_alpa);
+       if (alpabm_valid == 1) {
+               for (i = 0; i < num_alpa; i++) {
+                       bfa_trc(port->fcs->bfa, alpa_map[i]);
+                       if (alpa_map[i] != bfa_hton3b(port->pid)) {
+                               pid = alpa_map[i];
+                               bfa_trc(port->fcs->bfa, pid);
+                               rport = bfa_fcs_lport_get_rport_by_pid(port,
+                                               bfa_hton3b(pid));
+                               if (!rport)
+                                       rport = bfa_fcs_rport_create(port,
+                                               bfa_hton3b(pid));
+                       }
+               }
+       } else {
+               for (i = 0; i < MAX_ALPA_COUNT; i++) {
+                       if (alpa_map[i] != port->pid) {
+                               pid = loop_alpa_map[i];
+                               bfa_trc(port->fcs->bfa, pid);
+                               rport = bfa_fcs_lport_get_rport_by_pid(port,
+                                               bfa_hton3b(pid));
+                               if (!rport)
+                                       rport = bfa_fcs_rport_create(port,
+                                               bfa_hton3b(pid));
+                       }
+               }
+       }
+}
+
+/*
+ * Called by fcs/port to notify transition to offline state.
+ */
+static void
+bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port)
+{
+}
+
 #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
 
 /*
@@ -1888,13 +2014,10 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
                                         sizeof(templen));
        }
 
-       /*
-        * f/w Version = driver version
-        */
        attr = (struct fdmi_attr_s *) curr_ptr;
        attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
-       templen = (u16) strlen(fcs_hba_attr->driver_version);
-       memcpy(attr->value, fcs_hba_attr->driver_version, templen);
+       templen = (u16) strlen(fcs_hba_attr->fw_version);
+       memcpy(attr->value, fcs_hba_attr->fw_version, templen);
        templen = fc_roundup(templen, sizeof(u32));
        curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
        len += templen;
@@ -2296,6 +2419,7 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
 {
        struct bfa_fcs_lport_s *port = fdmi->ms->port;
        struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
+       struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
 
        memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
 
@@ -2331,7 +2455,9 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
                                sizeof(driver_info->host_os_patch));
        }
 
-       hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ);
+       /* Retrieve the max frame size from the port attr */
+       bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
+       hba_attr->max_ct_pyld = fcs_port_attr.max_frm_size;
 }
 
 static void
@@ -2391,7 +2517,7 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
        /*
         * Max PDU Size.
         */
-       port_attr->max_frm_size = cpu_to_be32(FC_MAX_PDUSZ);
+       port_attr->max_frm_size = cpu_to_be32(pport_attr.pport_cfg.maxfrsize);
 
        /*
         * OS device Name
@@ -5199,7 +5325,7 @@ bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
 }
 
 void
-bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
+bfa_fcs_lport_fab_scn_online(struct bfa_fcs_lport_s *port)
 {
        struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
 
@@ -5620,6 +5746,15 @@ bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
        memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
 }
 
+/*
+ * Let new loop map create missing rports
+ */
+void
+bfa_fcs_lport_lip_scn_online(struct bfa_fcs_lport_s *port)
+{
+       bfa_fcs_lport_loop_online(port);
+}
+
 /*
  * FCS virtual port state machine
  */
index cc43b2a58ce33ac9478cc25b9c9fc0509f4eeb96..58ac643ba9f34d40a43c180342b896602eee55b5 100644 (file)
@@ -106,9 +106,13 @@ static void        bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
                                                 enum rport_event event);
 static void    bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
                                         enum rport_event event);
-static void    bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
-                                               enum rport_event event);
-static void    bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
+static void    bfa_fcs_rport_sm_adisc_online_sending(
+                       struct bfa_fcs_rport_s *rport, enum rport_event event);
+static void    bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,
+                                       enum rport_event event);
+static void    bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s
+                                       *rport, enum rport_event event);
+static void    bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,
                                        enum rport_event event);
 static void    bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
                                                enum rport_event event);
@@ -150,8 +154,10 @@ static struct bfa_sm_table_s rport_sm_table[] = {
        {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
        {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
        {BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
-       {BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC},
-       {BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC},
+       {BFA_SM(bfa_fcs_rport_sm_adisc_online_sending), BFA_RPORT_ADISC},
+       {BFA_SM(bfa_fcs_rport_sm_adisc_online), BFA_RPORT_ADISC},
+       {BFA_SM(bfa_fcs_rport_sm_adisc_offline_sending), BFA_RPORT_ADISC},
+       {BFA_SM(bfa_fcs_rport_sm_adisc_offline), BFA_RPORT_ADISC},
        {BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
        {BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
        {BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
@@ -231,10 +237,19 @@ bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_send_plogiacc(rport, NULL);
                break;
 
+       case RPSM_EVENT_SCN_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
        case RPSM_EVENT_ADDRESS_CHANGE:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                /* query the NS */
                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+                                       BFA_PORT_TOPOLOGY_LOOP));
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                rport->ns_retries = 0;
                bfa_fcs_rport_send_nsdisc(rport, NULL);
@@ -280,12 +295,20 @@ bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
 
        case RPSM_EVENT_PLOGI_RCVD:
        case RPSM_EVENT_PLOGI_COMP:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                /*
                 * Ignore, SCN is possibly online notification.
                 */
                break;
 
+       case RPSM_EVENT_SCN_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
        case RPSM_EVENT_ADDRESS_CHANGE:
                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
@@ -346,9 +369,19 @@ bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_send_plogiacc(rport, NULL);
                break;
 
+       case RPSM_EVENT_SCN_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_timer_stop(&rport->timer);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
        case RPSM_EVENT_ADDRESS_CHANGE:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                bfa_timer_stop(&rport->timer);
+               WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+                                       BFA_PORT_TOPOLOGY_LOOP));
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                rport->ns_retries = 0;
                bfa_fcs_rport_send_nsdisc(rport, NULL);
@@ -422,7 +455,18 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
                }
                break;
 
-       case    RPSM_EVENT_PLOGI_RETRY:
+       case RPSM_EVENT_SCN_ONLINE:
+               break;
+
+       case RPSM_EVENT_SCN_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_PLOGI_RETRY:
                rport->plogi_retries = 0;
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
                bfa_timer_start(rport->fcs->bfa, &rport->timer,
@@ -440,8 +484,10 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
                break;
 
        case RPSM_EVENT_ADDRESS_CHANGE:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                bfa_fcxp_discard(rport->fcxp);
+               WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+                                       BFA_PORT_TOPOLOGY_LOOP));
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                rport->ns_retries = 0;
                bfa_fcs_rport_send_nsdisc(rport, NULL);
@@ -512,7 +558,8 @@ bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,
        case RPSM_EVENT_PLOGI_COMP:
        case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
+       case RPSM_EVENT_SCN_OFFLINE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
                bfa_fcs_rport_fcs_offline_action(rport);
                break;
@@ -561,9 +608,10 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_fcs_offline_action(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
+       case RPSM_EVENT_SCN_OFFLINE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
                bfa_fcs_rport_fcs_offline_action(rport);
                break;
@@ -595,14 +643,15 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
        bfa_trc(rport->fcs, event);
 
        switch (event) {
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
                        bfa_sm_set_state(rport,
                                         bfa_fcs_rport_sm_nsquery_sending);
                        rport->ns_retries = 0;
                        bfa_fcs_rport_send_nsdisc(rport, NULL);
                } else {
-                       bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
+                       bfa_sm_set_state(rport,
+                               bfa_fcs_rport_sm_adisc_online_sending);
                        bfa_fcs_rport_send_adisc(rport, NULL);
                }
                break;
@@ -610,6 +659,7 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
        case RPSM_EVENT_PLOGI_RCVD:
        case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
+       case RPSM_EVENT_SCN_OFFLINE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
                bfa_fcs_rport_hal_offline_action(rport);
                break;
@@ -625,6 +675,7 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
                bfa_fcs_rport_hal_offline_action(rport);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
        case RPSM_EVENT_PLOGI_COMP:
                break;
 
@@ -656,7 +707,7 @@ bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_hal_offline_action(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                /*
                 * ignore SCN, wait for response to query itself
                 */
@@ -696,7 +747,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
 
        switch (event) {
        case RPSM_EVENT_ACCEPTED:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online_sending);
                bfa_fcs_rport_send_adisc(rport, NULL);
                break;
 
@@ -718,7 +769,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
                bfa_fcs_rport_hal_offline_action(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                break;
 
        case RPSM_EVENT_LOGO_RCVD:
@@ -747,7 +798,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
  *     authenticating with rport. FC-4s are paused.
  */
 static void
-bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
+bfa_fcs_rport_sm_adisc_online_sending(struct bfa_fcs_rport_s *rport,
         enum rport_event event)
 {
        bfa_trc(rport->fcs, rport->pwwn);
@@ -756,7 +807,7 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
 
        switch (event) {
        case RPSM_EVENT_FCXP_SENT:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online);
                break;
 
        case RPSM_EVENT_DELETE:
@@ -779,7 +830,7 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_hal_offline_action(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                break;
 
        case RPSM_EVENT_PLOGI_RCVD:
@@ -798,7 +849,8 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
  *             FC-4s are paused.
  */
 static void
-bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
+bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,
+                               enum rport_event event)
 {
        bfa_trc(rport->fcs, rport->pwwn);
        bfa_trc(rport->fcs, rport->pid);
@@ -831,7 +883,7 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
                bfa_fcs_rport_hal_offline_action(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                /*
                 * already processing RSCN
                 */
@@ -856,7 +908,96 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
 }
 
 /*
- *             Rport has sent LOGO. Awaiting FC-4 offline completion callback.
+ * ADISC is being sent for authenticating with rport
+ * Already did offline actions.
+ */
+static void
+bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s *rport,
+       enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_FCXP_SENT:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_offline);
+               break;
+
+       case RPSM_EVENT_DELETE:
+       case RPSM_EVENT_SCN_OFFLINE:
+       case RPSM_EVENT_LOGO_IMP:
+       case RPSM_EVENT_LOGO_RCVD:
+       case RPSM_EVENT_PRLO_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa,
+                       &rport->fcxp_wqe);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                       bfa_fcs_rport_timeout, rport,
+                       bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               break;
+
+       default:
+               bfa_sm_fault(rport->fcs, event);
+       }
+}
+
+/*
+ * ADISC to rport
+ * Already did offline actions
+ */
+static void
+bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,
+                       enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_ACCEPTED:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_fcs_rport_hal_online(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               break;
+
+       case RPSM_EVENT_FAILED:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                       bfa_fcs_rport_timeout, rport,
+                       bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_DELETE:
+       case RPSM_EVENT_SCN_OFFLINE:
+       case RPSM_EVENT_LOGO_IMP:
+       case RPSM_EVENT_LOGO_RCVD:
+       case RPSM_EVENT_PRLO_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                       bfa_fcs_rport_timeout, rport,
+                       bfa_fcs_rport_del_timeout);
+               break;
+
+       default:
+               bfa_sm_fault(rport->fcs, event);
+       }
+}
+
+/*
+ * Rport has sent LOGO. Awaiting FC-4 offline completion callback.
  */
 static void
 bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
@@ -881,6 +1022,8 @@ bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
+       case RPSM_EVENT_SCN_OFFLINE:
        case RPSM_EVENT_HCB_ONLINE:
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
@@ -945,6 +1088,8 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_hal_offline(rport);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
+               break;
        case RPSM_EVENT_LOGO_RCVD:
                /*
                 * Rport is going offline. Just ack the logo
@@ -956,8 +1101,9 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_send_prlo_acc(rport);
                break;
 
+       case RPSM_EVENT_SCN_OFFLINE:
        case RPSM_EVENT_HCB_ONLINE:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
                /*
@@ -1015,6 +1161,19 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
                                bfa_fcs_rport_sm_nsdisc_sending);
                        rport->ns_retries = 0;
                        bfa_fcs_rport_send_nsdisc(rport, NULL);
+               } else if (bfa_fcport_get_topology(rport->port->fcs->bfa) ==
+                                       BFA_PORT_TOPOLOGY_LOOP) {
+                       if (rport->scn_online) {
+                               bfa_sm_set_state(rport,
+                                       bfa_fcs_rport_sm_adisc_offline_sending);
+                               bfa_fcs_rport_send_adisc(rport, NULL);
+                       } else {
+                               bfa_sm_set_state(rport,
+                                       bfa_fcs_rport_sm_offline);
+                               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                                       bfa_fcs_rport_timeout, rport,
+                                       bfa_fcs_rport_del_timeout);
+                       }
                } else {
                        bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
                        rport->plogi_retries = 0;
@@ -1027,7 +1186,9 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_free(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_SCN_ONLINE:
+       case RPSM_EVENT_SCN_OFFLINE:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
        case RPSM_EVENT_PLOGI_RCVD:
@@ -1106,6 +1267,8 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
+       case RPSM_EVENT_SCN_OFFLINE:
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
                /*
@@ -1146,6 +1309,8 @@ bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
+       case RPSM_EVENT_SCN_OFFLINE:
        case RPSM_EVENT_ADDRESS_CHANGE:
                break;
 
@@ -1172,7 +1337,9 @@ bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_free(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_SCN_ONLINE:
+       case RPSM_EVENT_SCN_OFFLINE:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_ADDRESS_CHANGE:
                break;
 
@@ -1209,10 +1376,12 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
                bfa_fcs_rport_free(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_ADDRESS_CHANGE:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                bfa_timer_stop(&rport->timer);
+               WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+                                       BFA_PORT_TOPOLOGY_LOOP));
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                rport->ns_retries = 0;
                bfa_fcs_rport_send_nsdisc(rport, NULL);
                break;
@@ -1232,6 +1401,7 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
        case RPSM_EVENT_LOGO_IMP:
+       case RPSM_EVENT_SCN_OFFLINE:
                break;
 
        case RPSM_EVENT_PLOGI_COMP:
@@ -1240,6 +1410,12 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
                bfa_fcs_rport_fcs_online_action(rport);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
+               bfa_timer_stop(&rport->timer);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+               bfa_fcs_rport_send_plogi(rport, NULL);
+               break;
+
        case RPSM_EVENT_PLOGI_SEND:
                bfa_timer_stop(&rport->timer);
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
@@ -1280,7 +1456,7 @@ bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_send_plogiacc(rport, NULL);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
        case RPSM_EVENT_PLOGI_SEND:
@@ -1326,7 +1502,7 @@ bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_send_nsdisc(rport, NULL);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_ADDRESS_CHANGE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                bfa_timer_stop(&rport->timer);
@@ -1439,7 +1615,7 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
        case RPSM_EVENT_PRLO_RCVD:
                bfa_fcs_rport_send_prlo_acc(rport);
                break;
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                /*
                 * ignore, wait for NS query response
                 */
@@ -2546,7 +2722,7 @@ void
 bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
 {
        rport->stats.rscns++;
-       bfa_sm_send_event(rport, RPSM_EVENT_SCN);
+       bfa_sm_send_event(rport, RPSM_EVENT_FAB_SCN);
 }
 
 /*
@@ -2621,6 +2797,48 @@ bfa_cb_rport_qos_scn_flowid(void *cbarg,
        bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
 }
 
+void
+bfa_cb_rport_scn_online(struct bfa_s *bfa)
+{
+       struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;
+       struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);
+       struct bfa_fcs_rport_s *rp;
+       struct list_head *qe;
+
+       list_for_each(qe, &port->rport_q) {
+               rp = (struct bfa_fcs_rport_s *) qe;
+               bfa_sm_send_event(rp, RPSM_EVENT_SCN_ONLINE);
+               rp->scn_online = BFA_TRUE;
+       }
+
+       if (bfa_fcs_lport_is_online(port))
+               bfa_fcs_lport_lip_scn_online(port);
+}
+
+void
+bfa_cb_rport_scn_no_dev(void *rport)
+{
+       struct bfa_fcs_rport_s *rp = rport;
+
+       bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);
+       rp->scn_online = BFA_FALSE;
+}
+
+void
+bfa_cb_rport_scn_offline(struct bfa_s *bfa)
+{
+       struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;
+       struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);
+       struct bfa_fcs_rport_s *rp;
+       struct list_head *qe;
+
+       list_for_each(qe, &port->rport_q) {
+               rp = (struct bfa_fcs_rport_s *) qe;
+               bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);
+               rp->scn_online = BFA_FALSE;
+       }
+}
+
 /*
  *     brief
  *     This routine is a static BFA callback when there is a QoS priority
@@ -2808,6 +3026,9 @@ bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
        struct bfa_rport_qos_attr_s qos_attr;
        struct bfa_fcs_lport_s *port = rport->port;
        bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
+       struct bfa_port_attr_s port_attr;
+
+       bfa_fcport_get_attr(rport->fcs->bfa, &port_attr);
 
        memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
        memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s));
@@ -2838,7 +3059,8 @@ bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
                        rport_speed =
                                bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
 
-               if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port))
+               if ((bfa_fcs_lport_get_rport_max_speed(port) !=
+                   BFA_PORT_SPEED_UNKNOWN) && (rport_speed < port_attr.speed))
                        rport_attr->trl_enforced = BFA_TRUE;
        }
 }
index 75ca8752b9f4b125ce5e47417f912b29c42fff80..0116c1032e2524d373412957d037cf24ae698c03 100644 (file)
@@ -731,8 +731,7 @@ bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
        /*
         * Unlock the hw semaphore. Should be here only once per boot.
         */
-       readl(iocpf->ioc->ioc_regs.ioc_sem_reg);
-       writel(1, iocpf->ioc->ioc_regs.ioc_sem_reg);
+       bfa_ioc_ownership_reset(iocpf->ioc);
 
        /*
         * unlock init semaphore.
@@ -1751,6 +1750,7 @@ bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
        attr->card_type     = be32_to_cpu(attr->card_type);
        attr->maxfrsize     = be16_to_cpu(attr->maxfrsize);
        ioc->fcmode     = (attr->port_mode == BFI_PORT_MODE_FC);
+       attr->mfg_year  = be16_to_cpu(attr->mfg_year);
 
        bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
 }
@@ -2497,6 +2497,9 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
        ad_attr->cna_capable = bfa_ioc_is_cna(ioc);
        ad_attr->trunk_capable = (ad_attr->nports > 1) &&
                                  !bfa_ioc_is_cna(ioc) && !ad_attr->is_mezz;
+       ad_attr->mfg_day = ioc_attr->mfg_day;
+       ad_attr->mfg_month = ioc_attr->mfg_month;
+       ad_attr->mfg_year = ioc_attr->mfg_year;
 }
 
 enum bfa_ioc_type_e
@@ -2923,7 +2926,7 @@ bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc)
                return;
        }
 
-       if (ioc->iocpf.poll_time >= BFA_IOC_TOV)
+       if (ioc->iocpf.poll_time >= (3 * BFA_IOC_TOV))
                bfa_iocpf_timeout(ioc);
        else {
                ioc->iocpf.poll_time += BFA_IOC_POLL_TOV;
@@ -3016,7 +3019,6 @@ bfa_ablk_config_swap(struct bfa_ablk_cfg_s *cfg)
        struct bfa_ablk_cfg_inst_s *cfg_inst;
        int i, j;
        u16     be16;
-       u32     be32;
 
        for (i = 0; i < BFA_ABLK_MAX; i++) {
                cfg_inst = &cfg->inst[i];
@@ -3027,8 +3029,10 @@ bfa_ablk_config_swap(struct bfa_ablk_cfg_s *cfg)
                        cfg_inst->pf_cfg[j].num_qpairs = be16_to_cpu(be16);
                        be16 = cfg_inst->pf_cfg[j].num_vectors;
                        cfg_inst->pf_cfg[j].num_vectors = be16_to_cpu(be16);
-                       be32 = cfg_inst->pf_cfg[j].bw;
-                       cfg_inst->pf_cfg[j].bw = be16_to_cpu(be32);
+                       be16 = cfg_inst->pf_cfg[j].bw_min;
+                       cfg_inst->pf_cfg[j].bw_min = be16_to_cpu(be16);
+                       be16 = cfg_inst->pf_cfg[j].bw_max;
+                       cfg_inst->pf_cfg[j].bw_max = be16_to_cpu(be16);
                }
        }
 }
@@ -3170,7 +3174,8 @@ bfa_ablk_query(struct bfa_ablk_s *ablk, struct bfa_ablk_cfg_s *ablk_cfg,
 
 bfa_status_t
 bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn,
-               u8 port, enum bfi_pcifn_class personality, int bw,
+               u8 port, enum bfi_pcifn_class personality,
+               u16 bw_min, u16 bw_max,
                bfa_ablk_cbfn_t cbfn, void *cbarg)
 {
        struct bfi_ablk_h2i_pf_req_s *m;
@@ -3194,7 +3199,8 @@ bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn,
        bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_CREATE,
                    bfa_ioc_portid(ablk->ioc));
        m->pers = cpu_to_be16((u16)personality);
-       m->bw = cpu_to_be32(bw);
+       m->bw_min = cpu_to_be16(bw_min);
+       m->bw_max = cpu_to_be16(bw_max);
        m->port = port;
        bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
 
@@ -3294,8 +3300,8 @@ bfa_ablk_port_config(struct bfa_ablk_s *ablk, int port, enum bfa_mode_s mode,
 }
 
 bfa_status_t
-bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, int bw,
-               bfa_ablk_cbfn_t cbfn, void *cbarg)
+bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, u16 bw_min,
+                  u16 bw_max, bfa_ablk_cbfn_t cbfn, void *cbarg)
 {
        struct bfi_ablk_h2i_pf_req_s *m;
 
@@ -3317,7 +3323,8 @@ bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, int bw,
        bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_UPDATE,
                bfa_ioc_portid(ablk->ioc));
        m->pcifn = (u8)pcifn;
-       m->bw = cpu_to_be32(bw);
+       m->bw_min = cpu_to_be16(bw_min);
+       m->bw_max = cpu_to_be16(bw_max);
        bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
 
        return BFA_STATUS_OK;
@@ -4680,22 +4687,25 @@ diag_tempsensor_comp(struct bfa_diag_s *diag, bfi_diag_ts_rsp_t *rsp)
        diag->tsensor.temp->temp = be16_to_cpu(rsp->temp);
        diag->tsensor.temp->ts_junc = rsp->ts_junc;
        diag->tsensor.temp->ts_brd = rsp->ts_brd;
-       diag->tsensor.temp->status = BFA_STATUS_OK;
 
        if (rsp->ts_brd) {
+               /* tsensor.temp->status is brd_temp status */
+               diag->tsensor.temp->status = rsp->status;
                if (rsp->status == BFA_STATUS_OK) {
                        diag->tsensor.temp->brd_temp =
                                be16_to_cpu(rsp->brd_temp);
-               } else {
-                       bfa_trc(diag, rsp->status);
+               } else
                        diag->tsensor.temp->brd_temp = 0;
-                       diag->tsensor.temp->status = BFA_STATUS_DEVBUSY;
-               }
        }
+
+       bfa_trc(diag, rsp->status);
        bfa_trc(diag, rsp->ts_junc);
        bfa_trc(diag, rsp->temp);
        bfa_trc(diag, rsp->ts_brd);
        bfa_trc(diag, rsp->brd_temp);
+
+       /* tsensor status is always good bcos we always have junction temp */
+       diag->tsensor.status = BFA_STATUS_OK;
        diag->tsensor.cbfn(diag->tsensor.cbarg, diag->tsensor.status);
        diag->tsensor.lock = 0;
 }
@@ -4924,6 +4934,7 @@ bfa_diag_tsensor_query(struct bfa_diag_s *diag,
        diag->tsensor.temp = result;
        diag->tsensor.cbfn = cbfn;
        diag->tsensor.cbarg = cbarg;
+       diag->tsensor.status = BFA_STATUS_OK;
 
        /* Send msg to fw */
        diag_tempsensor_send(diag);
@@ -5615,7 +5626,7 @@ bfa_dconf_sm_uninit(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)
                }
                bfa_sm_set_state(dconf, bfa_dconf_sm_flash_read);
                bfa_timer_start(dconf->bfa, &dconf->timer,
-                       bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
+                       bfa_dconf_timer, dconf, 2 * BFA_DCONF_UPDATE_TOV);
                bfa_status = bfa_flash_read_part(BFA_FLASH(dconf->bfa),
                                        BFA_FLASH_PART_DRV, dconf->instance,
                                        dconf->dconf,
@@ -5655,7 +5666,7 @@ bfa_dconf_sm_flash_read(struct bfa_dconf_mod_s *dconf,
                break;
        case BFA_DCONF_SM_TIMEOUT:
                bfa_sm_set_state(dconf, bfa_dconf_sm_ready);
-               bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_IOC_FAILED);
+               bfa_ioc_suspend(&dconf->bfa->ioc);
                break;
        case BFA_DCONF_SM_EXIT:
                bfa_timer_stop(&dconf->timer);
@@ -5853,7 +5864,6 @@ bfa_dconf_init_cb(void *arg, bfa_status_t status)
        struct bfa_s *bfa = arg;
        struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
 
-       bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP);
        if (status == BFA_STATUS_OK) {
                bfa_dconf_read_data_valid(bfa) = BFA_TRUE;
                if (dconf->dconf->hdr.signature != BFI_DCONF_SIGNATURE)
@@ -5861,6 +5871,7 @@ bfa_dconf_init_cb(void *arg, bfa_status_t status)
                if (dconf->dconf->hdr.version != BFI_DCONF_VERSION)
                        dconf->dconf->hdr.version = BFI_DCONF_VERSION;
        }
+       bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP);
        bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_DCONF_DONE);
 }
 
@@ -5945,3 +5956,448 @@ bfa_dconf_modexit(struct bfa_s *bfa)
        struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
        bfa_sm_send_event(dconf, BFA_DCONF_SM_EXIT);
 }
+
+/*
+ * FRU specific functions
+ */
+
+#define BFA_FRU_DMA_BUF_SZ     0x02000         /* 8k dma buffer */
+#define BFA_FRU_CHINOOK_MAX_SIZE 0x10000
+#define BFA_FRU_LIGHTNING_MAX_SIZE 0x200
+
+static void
+bfa_fru_notify(void *cbarg, enum bfa_ioc_event_e event)
+{
+       struct bfa_fru_s *fru = cbarg;
+
+       bfa_trc(fru, event);
+
+       switch (event) {
+       case BFA_IOC_E_DISABLED:
+       case BFA_IOC_E_FAILED:
+               if (fru->op_busy) {
+                       fru->status = BFA_STATUS_IOC_FAILURE;
+                       fru->cbfn(fru->cbarg, fru->status);
+                       fru->op_busy = 0;
+               }
+               break;
+
+       default:
+               break;
+       }
+}
+
+/*
+ * Send fru write request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_fru_write_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type)
+{
+       struct bfa_fru_s *fru = cbarg;
+       struct bfi_fru_write_req_s *msg =
+                       (struct bfi_fru_write_req_s *) fru->mb.msg;
+       u32 len;
+
+       msg->offset = cpu_to_be32(fru->addr_off + fru->offset);
+       len = (fru->residue < BFA_FRU_DMA_BUF_SZ) ?
+                               fru->residue : BFA_FRU_DMA_BUF_SZ;
+       msg->length = cpu_to_be32(len);
+
+       /*
+        * indicate if it's the last msg of the whole write operation
+        */
+       msg->last = (len == fru->residue) ? 1 : 0;
+
+       bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc));
+       bfa_alen_set(&msg->alen, len, fru->dbuf_pa);
+
+       memcpy(fru->dbuf_kva, fru->ubuf + fru->offset, len);
+       bfa_ioc_mbox_queue(fru->ioc, &fru->mb);
+
+       fru->residue -= len;
+       fru->offset += len;
+}
+
+/*
+ * Send fru read request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_fru_read_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type)
+{
+       struct bfa_fru_s *fru = cbarg;
+       struct bfi_fru_read_req_s *msg =
+                       (struct bfi_fru_read_req_s *) fru->mb.msg;
+       u32 len;
+
+       msg->offset = cpu_to_be32(fru->addr_off + fru->offset);
+       len = (fru->residue < BFA_FRU_DMA_BUF_SZ) ?
+                               fru->residue : BFA_FRU_DMA_BUF_SZ;
+       msg->length = cpu_to_be32(len);
+       bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc));
+       bfa_alen_set(&msg->alen, len, fru->dbuf_pa);
+       bfa_ioc_mbox_queue(fru->ioc, &fru->mb);
+}
+
+/*
+ * Flash memory info API.
+ *
+ * @param[in] mincfg - minimal cfg variable
+ */
+u32
+bfa_fru_meminfo(bfa_boolean_t mincfg)
+{
+       /* min driver doesn't need fru */
+       if (mincfg)
+               return 0;
+
+       return BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * Flash attach API.
+ *
+ * @param[in] fru - fru structure
+ * @param[in] ioc  - ioc structure
+ * @param[in] dev  - device structure
+ * @param[in] trcmod - trace module
+ * @param[in] logmod - log module
+ */
+void
+bfa_fru_attach(struct bfa_fru_s *fru, struct bfa_ioc_s *ioc, void *dev,
+       struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)
+{
+       fru->ioc = ioc;
+       fru->trcmod = trcmod;
+       fru->cbfn = NULL;
+       fru->cbarg = NULL;
+       fru->op_busy = 0;
+
+       bfa_ioc_mbox_regisr(fru->ioc, BFI_MC_FRU, bfa_fru_intr, fru);
+       bfa_q_qe_init(&fru->ioc_notify);
+       bfa_ioc_notify_init(&fru->ioc_notify, bfa_fru_notify, fru);
+       list_add_tail(&fru->ioc_notify.qe, &fru->ioc->notify_q);
+
+       /* min driver doesn't need fru */
+       if (mincfg) {
+               fru->dbuf_kva = NULL;
+               fru->dbuf_pa = 0;
+       }
+}
+
+/*
+ * Claim memory for fru
+ *
+ * @param[in] fru - fru structure
+ * @param[in] dm_kva - pointer to virtual memory address
+ * @param[in] dm_pa - frusical memory address
+ * @param[in] mincfg - minimal cfg variable
+ */
+void
+bfa_fru_memclaim(struct bfa_fru_s *fru, u8 *dm_kva, u64 dm_pa,
+       bfa_boolean_t mincfg)
+{
+       if (mincfg)
+               return;
+
+       fru->dbuf_kva = dm_kva;
+       fru->dbuf_pa = dm_pa;
+       memset(fru->dbuf_kva, 0, BFA_FRU_DMA_BUF_SZ);
+       dm_kva += BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+       dm_pa += BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * Update fru vpd image.
+ *
+ * @param[in] fru - fru structure
+ * @param[in] buf - update data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_fruvpd_update(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
+                 bfa_cb_fru_t cbfn, void *cbarg)
+{
+       bfa_trc(fru, BFI_FRUVPD_H2I_WRITE_REQ);
+       bfa_trc(fru, len);
+       bfa_trc(fru, offset);
+
+       if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
+               return BFA_STATUS_FRU_NOT_PRESENT;
+
+       if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK)
+               return BFA_STATUS_CMD_NOTSUPP;
+
+       if (!bfa_ioc_is_operational(fru->ioc))
+               return BFA_STATUS_IOC_NON_OP;
+
+       if (fru->op_busy) {
+               bfa_trc(fru, fru->op_busy);
+               return BFA_STATUS_DEVBUSY;
+       }
+
+       fru->op_busy = 1;
+
+       fru->cbfn = cbfn;
+       fru->cbarg = cbarg;
+       fru->residue = len;
+       fru->offset = 0;
+       fru->addr_off = offset;
+       fru->ubuf = buf;
+
+       bfa_fru_write_send(fru, BFI_FRUVPD_H2I_WRITE_REQ);
+
+       return BFA_STATUS_OK;
+}
+
+/*
+ * Read fru vpd image.
+ *
+ * @param[in] fru - fru structure
+ * @param[in] buf - read data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_fruvpd_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
+               bfa_cb_fru_t cbfn, void *cbarg)
+{
+       bfa_trc(fru, BFI_FRUVPD_H2I_READ_REQ);
+       bfa_trc(fru, len);
+       bfa_trc(fru, offset);
+
+       if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
+               return BFA_STATUS_FRU_NOT_PRESENT;
+
+       if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK)
+               return BFA_STATUS_CMD_NOTSUPP;
+
+       if (!bfa_ioc_is_operational(fru->ioc))
+               return BFA_STATUS_IOC_NON_OP;
+
+       if (fru->op_busy) {
+               bfa_trc(fru, fru->op_busy);
+               return BFA_STATUS_DEVBUSY;
+       }
+
+       fru->op_busy = 1;
+
+       fru->cbfn = cbfn;
+       fru->cbarg = cbarg;
+       fru->residue = len;
+       fru->offset = 0;
+       fru->addr_off = offset;
+       fru->ubuf = buf;
+       bfa_fru_read_send(fru, BFI_FRUVPD_H2I_READ_REQ);
+
+       return BFA_STATUS_OK;
+}
+
+/*
+ * Get maximum size fru vpd image.
+ *
+ * @param[in] fru - fru structure
+ * @param[out] size - maximum size of fru vpd data
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_fruvpd_get_max_size(struct bfa_fru_s *fru, u32 *max_size)
+{
+       if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
+               return BFA_STATUS_FRU_NOT_PRESENT;
+
+       if (!bfa_ioc_is_operational(fru->ioc))
+               return BFA_STATUS_IOC_NON_OP;
+
+       if (fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK)
+               *max_size = BFA_FRU_CHINOOK_MAX_SIZE;
+       else
+               return BFA_STATUS_CMD_NOTSUPP;
+       return BFA_STATUS_OK;
+}
+/*
+ * tfru write.
+ *
+ * @param[in] fru - fru structure
+ * @param[in] buf - update data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_tfru_write(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
+              bfa_cb_fru_t cbfn, void *cbarg)
+{
+       bfa_trc(fru, BFI_TFRU_H2I_WRITE_REQ);
+       bfa_trc(fru, len);
+       bfa_trc(fru, offset);
+       bfa_trc(fru, *((u8 *) buf));
+
+       if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
+               return BFA_STATUS_FRU_NOT_PRESENT;
+
+       if (!bfa_ioc_is_operational(fru->ioc))
+               return BFA_STATUS_IOC_NON_OP;
+
+       if (fru->op_busy) {
+               bfa_trc(fru, fru->op_busy);
+               return BFA_STATUS_DEVBUSY;
+       }
+
+       fru->op_busy = 1;
+
+       fru->cbfn = cbfn;
+       fru->cbarg = cbarg;
+       fru->residue = len;
+       fru->offset = 0;
+       fru->addr_off = offset;
+       fru->ubuf = buf;
+
+       bfa_fru_write_send(fru, BFI_TFRU_H2I_WRITE_REQ);
+
+       return BFA_STATUS_OK;
+}
+
+/*
+ * tfru read.
+ *
+ * @param[in] fru - fru structure
+ * @param[in] buf - read data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_tfru_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
+             bfa_cb_fru_t cbfn, void *cbarg)
+{
+       bfa_trc(fru, BFI_TFRU_H2I_READ_REQ);
+       bfa_trc(fru, len);
+       bfa_trc(fru, offset);
+
+       if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
+               return BFA_STATUS_FRU_NOT_PRESENT;
+
+       if (!bfa_ioc_is_operational(fru->ioc))
+               return BFA_STATUS_IOC_NON_OP;
+
+       if (fru->op_busy) {
+               bfa_trc(fru, fru->op_busy);
+               return BFA_STATUS_DEVBUSY;
+       }
+
+       fru->op_busy = 1;
+
+       fru->cbfn = cbfn;
+       fru->cbarg = cbarg;
+       fru->residue = len;
+       fru->offset = 0;
+       fru->addr_off = offset;
+       fru->ubuf = buf;
+       bfa_fru_read_send(fru, BFI_TFRU_H2I_READ_REQ);
+
+       return BFA_STATUS_OK;
+}
+
+/*
+ * Process fru response messages upon receiving interrupts.
+ *
+ * @param[in] fruarg - fru structure
+ * @param[in] msg - message structure
+ */
+void
+bfa_fru_intr(void *fruarg, struct bfi_mbmsg_s *msg)
+{
+       struct bfa_fru_s *fru = fruarg;
+       struct bfi_fru_rsp_s *rsp = (struct bfi_fru_rsp_s *)msg;
+       u32 status;
+
+       bfa_trc(fru, msg->mh.msg_id);
+
+       if (!fru->op_busy) {
+               /*
+                * receiving response after ioc failure
+                */
+               bfa_trc(fru, 0x9999);
+               return;
+       }
+
+       switch (msg->mh.msg_id) {
+       case BFI_FRUVPD_I2H_WRITE_RSP:
+       case BFI_TFRU_I2H_WRITE_RSP:
+               status = be32_to_cpu(rsp->status);
+               bfa_trc(fru, status);
+
+               if (status != BFA_STATUS_OK || fru->residue == 0) {
+                       fru->status = status;
+                       fru->op_busy = 0;
+                       if (fru->cbfn)
+                               fru->cbfn(fru->cbarg, fru->status);
+               } else {
+                       bfa_trc(fru, fru->offset);
+                       if (msg->mh.msg_id == BFI_FRUVPD_I2H_WRITE_RSP)
+                               bfa_fru_write_send(fru,
+                                       BFI_FRUVPD_H2I_WRITE_REQ);
+                       else
+                               bfa_fru_write_send(fru,
+                                       BFI_TFRU_H2I_WRITE_REQ);
+               }
+               break;
+       case BFI_FRUVPD_I2H_READ_RSP:
+       case BFI_TFRU_I2H_READ_RSP:
+               status = be32_to_cpu(rsp->status);
+               bfa_trc(fru, status);
+
+               if (status != BFA_STATUS_OK) {
+                       fru->status = status;
+                       fru->op_busy = 0;
+                       if (fru->cbfn)
+                               fru->cbfn(fru->cbarg, fru->status);
+               } else {
+                       u32 len = be32_to_cpu(rsp->length);
+
+                       bfa_trc(fru, fru->offset);
+                       bfa_trc(fru, len);
+
+                       memcpy(fru->ubuf + fru->offset, fru->dbuf_kva, len);
+                       fru->residue -= len;
+                       fru->offset += len;
+
+                       if (fru->residue == 0) {
+                               fru->status = status;
+                               fru->op_busy = 0;
+                               if (fru->cbfn)
+                                       fru->cbfn(fru->cbarg, fru->status);
+                       } else {
+                               if (msg->mh.msg_id == BFI_FRUVPD_I2H_READ_RSP)
+                                       bfa_fru_read_send(fru,
+                                               BFI_FRUVPD_H2I_READ_REQ);
+                               else
+                                       bfa_fru_read_send(fru,
+                                               BFI_TFRU_H2I_READ_REQ);
+                       }
+               }
+               break;
+       default:
+               WARN_ON(1);
+       }
+}
index b2856f96567cfca34ba4bdfec447c47ac9c7882d..23a90e7b71071844c3b37c09eee4e6033cccc473 100644 (file)
@@ -701,6 +701,55 @@ void bfa_phy_memclaim(struct bfa_phy_s *phy,
                u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg);
 void bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg);
 
+/*
+ * FRU module specific
+ */
+typedef void (*bfa_cb_fru_t) (void *cbarg, bfa_status_t status);
+
+struct bfa_fru_s {
+       struct bfa_ioc_s *ioc;          /* back pointer to ioc */
+       struct bfa_trc_mod_s *trcmod;   /* trace module */
+       u8              op_busy;        /* operation busy flag */
+       u8              rsv[3];
+       u32             residue;        /* residual length */
+       u32             offset;         /* offset */
+       bfa_status_t    status;         /* status */
+       u8              *dbuf_kva;      /* dma buf virtual address */
+       u64             dbuf_pa;        /* dma buf physical address */
+       struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
+       bfa_cb_fru_t    cbfn;           /* user callback function */
+       void            *cbarg;         /* user callback arg */
+       u8              *ubuf;          /* user supplied buffer */
+       struct bfa_cb_qe_s      hcb_qe; /* comp: BFA callback qelem */
+       u32             addr_off;       /* fru address offset */
+       struct bfa_mbox_cmd_s mb;       /* mailbox */
+       struct bfa_ioc_notify_s ioc_notify; /* ioc event notify */
+       struct bfa_mem_dma_s    fru_dma;
+};
+
+#define BFA_FRU(__bfa) (&(__bfa)->modules.fru)
+#define BFA_MEM_FRU_DMA(__bfa) (&(BFA_FRU(__bfa)->fru_dma))
+
+bfa_status_t bfa_fruvpd_update(struct bfa_fru_s *fru,
+                       void *buf, u32 len, u32 offset,
+                       bfa_cb_fru_t cbfn, void *cbarg);
+bfa_status_t bfa_fruvpd_read(struct bfa_fru_s *fru,
+                       void *buf, u32 len, u32 offset,
+                       bfa_cb_fru_t cbfn, void *cbarg);
+bfa_status_t bfa_fruvpd_get_max_size(struct bfa_fru_s *fru, u32 *max_size);
+bfa_status_t bfa_tfru_write(struct bfa_fru_s *fru,
+                       void *buf, u32 len, u32 offset,
+                       bfa_cb_fru_t cbfn, void *cbarg);
+bfa_status_t bfa_tfru_read(struct bfa_fru_s *fru,
+                       void *buf, u32 len, u32 offset,
+                       bfa_cb_fru_t cbfn, void *cbarg);
+u32    bfa_fru_meminfo(bfa_boolean_t mincfg);
+void bfa_fru_attach(struct bfa_fru_s *fru, struct bfa_ioc_s *ioc,
+               void *dev, struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg);
+void bfa_fru_memclaim(struct bfa_fru_s *fru,
+               u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg);
+void bfa_fru_intr(void *fruarg, struct bfi_mbmsg_s *msg);
+
 /*
  * Driver Config( dconf) specific
  */
@@ -716,6 +765,7 @@ struct bfa_dconf_hdr_s {
 struct bfa_dconf_s {
        struct bfa_dconf_hdr_s          hdr;
        struct bfa_lunmask_cfg_s        lun_mask;
+       struct bfa_throttle_cfg_s       throttle_cfg;
 };
 #pragma pack()
 
@@ -738,6 +788,8 @@ struct bfa_dconf_mod_s {
 #define bfa_dconf_read_data_valid(__bfa)       \
        (BFA_DCONF_MOD(__bfa)->read_data_valid)
 #define BFA_DCONF_UPDATE_TOV   5000    /* memtest timeout in msec */
+#define bfa_dconf_get_min_cfg(__bfa)   \
+       (BFA_DCONF_MOD(__bfa)->min_cfg)
 
 void   bfa_dconf_modinit(struct bfa_s *bfa);
 void   bfa_dconf_modexit(struct bfa_s *bfa);
@@ -761,7 +813,8 @@ bfa_status_t        bfa_dconf_update(struct bfa_s *bfa);
 #define bfa_ioc_maxfrsize(__ioc)       ((__ioc)->attr->maxfrsize)
 #define bfa_ioc_rx_bbcredit(__ioc)     ((__ioc)->attr->rx_bbcredit)
 #define bfa_ioc_speed_sup(__ioc)       \
-       BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop)
+       ((bfa_ioc_is_cna(__ioc)) ? BFA_PORT_SPEED_10GBPS :      \
+        BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop))
 #define bfa_ioc_get_nports(__ioc)      \
        BFI_ADAPTER_GETP(NPORTS, (__ioc)->attr->adapter_prop)
 
@@ -885,12 +938,12 @@ bfa_status_t bfa_ablk_port_config(struct bfa_ablk_s *ablk, int port,
                enum bfa_mode_s mode, int max_pf, int max_vf,
                bfa_ablk_cbfn_t cbfn, void *cbarg);
 bfa_status_t bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn,
-               u8 port, enum bfi_pcifn_class personality, int bw,
-               bfa_ablk_cbfn_t cbfn, void *cbarg);
+               u8 port, enum bfi_pcifn_class personality,
+               u16 bw_min, u16 bw_max, bfa_ablk_cbfn_t cbfn, void *cbarg);
 bfa_status_t bfa_ablk_pf_delete(struct bfa_ablk_s *ablk, int pcifn,
                bfa_ablk_cbfn_t cbfn, void *cbarg);
-bfa_status_t bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, int bw,
-               bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn,
+               u16 bw_min, u16 bw_max, bfa_ablk_cbfn_t cbfn, void *cbarg);
 bfa_status_t bfa_ablk_optrom_en(struct bfa_ablk_s *ablk,
                bfa_ablk_cbfn_t cbfn, void *cbarg);
 bfa_status_t bfa_ablk_optrom_dis(struct bfa_ablk_s *ablk,
index 2eb0c6a2938d68a9276c4f19039445cc3ec93fdd..de4e726a1263cc1ca563d21aec5536b8c51f4a9c 100644 (file)
@@ -57,13 +57,6 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
        u32 usecnt;
        struct bfi_ioc_image_hdr_s fwhdr;
 
-       /*
-        * If bios boot (flash based) -- do not increment usage count
-        */
-       if (bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)) <
-                                               BFA_IOC_FWIMG_MINSZ)
-               return BFA_TRUE;
-
        bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
        usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
 
@@ -114,13 +107,6 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc)
 {
        u32 usecnt;
 
-       /*
-        * If bios boot (flash based) -- do not decrement usage count
-        */
-       if (bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)) <
-                                               BFA_IOC_FWIMG_MINSZ)
-               return;
-
        /*
         * decrement usage count
         */
@@ -400,13 +386,12 @@ static void
 bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc)
 {
 
-       if (bfa_ioc_is_cna(ioc)) {
-               bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
-               writel(0, ioc->ioc_regs.ioc_usage_reg);
-               readl(ioc->ioc_regs.ioc_usage_sem_reg);
-               writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
-       }
+       bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
+       writel(0, ioc->ioc_regs.ioc_usage_reg);
+       readl(ioc->ioc_regs.ioc_usage_sem_reg);
+       writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
 
+       writel(0, ioc->ioc_regs.ioc_fail_sync);
        /*
         * Read the hw sem reg to make sure that it is locked
         * before we clear it. If it is not locked, writing 1
@@ -759,25 +744,6 @@ bfa_ioc_ct2_mem_init(void __iomem *rb)
 void
 bfa_ioc_ct2_mac_reset(void __iomem *rb)
 {
-       u32     r32;
-
-       bfa_ioc_ct2_sclk_init(rb);
-       bfa_ioc_ct2_lclk_init(rb);
-
-       /*
-        * release soft reset on s_clk & l_clk
-        */
-       r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
-       writel(r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET,
-               (rb + CT2_APP_PLL_SCLK_CTL_REG));
-
-       /*
-        * release soft reset on s_clk & l_clk
-        */
-       r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
-       writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET,
-               (rb + CT2_APP_PLL_LCLK_CTL_REG));
-
        /* put port0, port1 MAC & AHB in reset */
        writel((__CSI_MAC_RESET | __CSI_MAC_AHB_RESET),
                rb + CT2_CSI_MAC_CONTROL_REG(0));
@@ -785,8 +751,21 @@ bfa_ioc_ct2_mac_reset(void __iomem *rb)
                rb + CT2_CSI_MAC_CONTROL_REG(1));
 }
 
+static void
+bfa_ioc_ct2_enable_flash(void __iomem *rb)
+{
+       u32 r32;
+
+       r32 = readl((rb + PSS_GPIO_OUT_REG));
+       writel(r32 & ~1, (rb + PSS_GPIO_OUT_REG));
+       r32 = readl((rb + PSS_GPIO_OE_REG));
+       writel(r32 | 1, (rb + PSS_GPIO_OE_REG));
+}
+
 #define CT2_NFC_MAX_DELAY      1000
-#define CT2_NFC_VER_VALID      0x143
+#define CT2_NFC_PAUSE_MAX_DELAY 4000
+#define CT2_NFC_VER_VALID      0x147
+#define CT2_NFC_STATE_RUNNING   0x20000001
 #define BFA_IOC_PLL_POLL       1000000
 
 static bfa_boolean_t
@@ -801,6 +780,20 @@ bfa_ioc_ct2_nfc_halted(void __iomem *rb)
        return BFA_FALSE;
 }
 
+static void
+bfa_ioc_ct2_nfc_halt(void __iomem *rb)
+{
+       int     i;
+
+       writel(__HALT_NFC_CONTROLLER, rb + CT2_NFC_CSR_SET_REG);
+       for (i = 0; i < CT2_NFC_MAX_DELAY; i++) {
+               if (bfa_ioc_ct2_nfc_halted(rb))
+                       break;
+               udelay(1000);
+       }
+       WARN_ON(!bfa_ioc_ct2_nfc_halted(rb));
+}
+
 static void
 bfa_ioc_ct2_nfc_resume(void __iomem *rb)
 {
@@ -817,105 +810,142 @@ bfa_ioc_ct2_nfc_resume(void __iomem *rb)
        WARN_ON(1);
 }
 
-bfa_status_t
-bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode)
+static void
+bfa_ioc_ct2_clk_reset(void __iomem *rb)
 {
-       u32 wgn, r32, nfc_ver, i;
+       u32 r32;
 
-       wgn = readl(rb + CT2_WGN_STATUS);
-       nfc_ver = readl(rb + CT2_RSC_GPR15_REG);
+       bfa_ioc_ct2_sclk_init(rb);
+       bfa_ioc_ct2_lclk_init(rb);
 
-       if ((wgn == (__A2T_AHB_LOAD | __WGN_READY)) &&
-           (nfc_ver >= CT2_NFC_VER_VALID)) {
-               if (bfa_ioc_ct2_nfc_halted(rb))
-                       bfa_ioc_ct2_nfc_resume(rb);
+       /*
+        * release soft reset on s_clk & l_clk
+        */
+       r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+       writel(r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET,
+                       (rb + CT2_APP_PLL_SCLK_CTL_REG));
 
-               writel(__RESET_AND_START_SCLK_LCLK_PLLS,
-                      rb + CT2_CSI_FW_CTL_SET_REG);
+       r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+       writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET,
+                       (rb + CT2_APP_PLL_LCLK_CTL_REG));
 
-               for (i = 0; i < BFA_IOC_PLL_POLL; i++) {
-                       r32 = readl(rb + CT2_APP_PLL_LCLK_CTL_REG);
-                       if (r32 & __RESET_AND_START_SCLK_LCLK_PLLS)
-                               break;
-               }
+}
 
-               WARN_ON(!(r32 & __RESET_AND_START_SCLK_LCLK_PLLS));
+static void
+bfa_ioc_ct2_nfc_clk_reset(void __iomem *rb)
+{
+       u32 r32, i;
 
-               for (i = 0; i < BFA_IOC_PLL_POLL; i++) {
-                       r32 = readl(rb + CT2_APP_PLL_LCLK_CTL_REG);
-                       if (!(r32 & __RESET_AND_START_SCLK_LCLK_PLLS))
-                               break;
-               }
+       r32 = readl((rb + PSS_CTL_REG));
+       r32 |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
+       writel(r32, (rb + PSS_CTL_REG));
+
+       writel(__RESET_AND_START_SCLK_LCLK_PLLS, rb + CT2_CSI_FW_CTL_SET_REG);
 
-               WARN_ON(r32 & __RESET_AND_START_SCLK_LCLK_PLLS);
+       for (i = 0; i < BFA_IOC_PLL_POLL; i++) {
+               r32 = readl(rb + CT2_NFC_FLASH_STS_REG);
+
+               if ((r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS))
+                       break;
+       }
+       WARN_ON(!(r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS));
+
+       for (i = 0; i < BFA_IOC_PLL_POLL; i++) {
+               r32 = readl(rb + CT2_NFC_FLASH_STS_REG);
+
+               if (!(r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS))
+                       break;
+       }
+       WARN_ON((r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS));
+
+       r32 = readl(rb + CT2_CSI_FW_CTL_REG);
+       WARN_ON((r32 & __RESET_AND_START_SCLK_LCLK_PLLS));
+}
+
+static void
+bfa_ioc_ct2_wait_till_nfc_running(void __iomem *rb)
+{
+       u32 r32;
+       int i;
+
+       if (bfa_ioc_ct2_nfc_halted(rb))
+               bfa_ioc_ct2_nfc_resume(rb);
+       for (i = 0; i < CT2_NFC_PAUSE_MAX_DELAY; i++) {
+               r32 = readl(rb + CT2_NFC_STS_REG);
+               if (r32 == CT2_NFC_STATE_RUNNING)
+                       return;
                udelay(1000);
+       }
 
-               r32 = readl(rb + CT2_CSI_FW_CTL_REG);
-               WARN_ON(r32 & __RESET_AND_START_SCLK_LCLK_PLLS);
-       } else {
-               writel(__HALT_NFC_CONTROLLER, rb + CT2_NFC_CSR_SET_REG);
-               for (i = 0; i < CT2_NFC_MAX_DELAY; i++) {
-                       r32 = readl(rb + CT2_NFC_CSR_SET_REG);
-                       if (r32 & __NFC_CONTROLLER_HALTED)
-                               break;
-                       udelay(1000);
-               }
+       r32 = readl(rb + CT2_NFC_STS_REG);
+       WARN_ON(!(r32 == CT2_NFC_STATE_RUNNING));
+}
 
-               bfa_ioc_ct2_mac_reset(rb);
-               bfa_ioc_ct2_sclk_init(rb);
-               bfa_ioc_ct2_lclk_init(rb);
+bfa_status_t
+bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode)
+{
+       u32 wgn, r32, nfc_ver;
 
-               /*
-                * release soft reset on s_clk & l_clk
-                */
-               r32 = readl(rb + CT2_APP_PLL_SCLK_CTL_REG);
-               writel(r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET,
-                      (rb + CT2_APP_PLL_SCLK_CTL_REG));
+       wgn = readl(rb + CT2_WGN_STATUS);
 
+       if (wgn == (__WGN_READY | __GLBL_PF_VF_CFG_RDY)) {
                /*
-                * release soft reset on s_clk & l_clk
+                * If flash is corrupted, enable flash explicitly
                 */
-               r32 = readl(rb + CT2_APP_PLL_LCLK_CTL_REG);
-               writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET,
-                     (rb + CT2_APP_PLL_LCLK_CTL_REG));
-       }
+               bfa_ioc_ct2_clk_reset(rb);
+               bfa_ioc_ct2_enable_flash(rb);
 
-       /*
-        * Announce flash device presence, if flash was corrupted.
-        */
-       if (wgn == (__WGN_READY | __GLBL_PF_VF_CFG_RDY)) {
-               r32 = readl(rb + PSS_GPIO_OUT_REG);
-               writel(r32 & ~1, (rb + PSS_GPIO_OUT_REG));
-               r32 = readl(rb + PSS_GPIO_OE_REG);
-               writel(r32 | 1, (rb + PSS_GPIO_OE_REG));
+               bfa_ioc_ct2_mac_reset(rb);
+
+               bfa_ioc_ct2_clk_reset(rb);
+               bfa_ioc_ct2_enable_flash(rb);
+
+       } else {
+               nfc_ver = readl(rb + CT2_RSC_GPR15_REG);
+
+               if ((nfc_ver >= CT2_NFC_VER_VALID) &&
+                   (wgn == (__A2T_AHB_LOAD | __WGN_READY))) {
+
+                       bfa_ioc_ct2_wait_till_nfc_running(rb);
+
+                       bfa_ioc_ct2_nfc_clk_reset(rb);
+               } else {
+                       bfa_ioc_ct2_nfc_halt(rb);
+
+                       bfa_ioc_ct2_clk_reset(rb);
+                       bfa_ioc_ct2_mac_reset(rb);
+                       bfa_ioc_ct2_clk_reset(rb);
+
+               }
        }
 
        /*
         * Mask the interrupts and clear any
-        * pending interrupts.
+        * pending interrupts left by BIOS/EFI
         */
+
        writel(1, (rb + CT2_LPU0_HOSTFN_MBOX0_MSK));
        writel(1, (rb + CT2_LPU1_HOSTFN_MBOX0_MSK));
 
        /* For first time initialization, no need to clear interrupts */
        r32 = readl(rb + HOST_SEM5_REG);
        if (r32 & 0x1) {
-               r32 = readl(rb + CT2_LPU0_HOSTFN_CMD_STAT);
+               r32 = readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
                if (r32 == 1) {
-                       writel(1, rb + CT2_LPU0_HOSTFN_CMD_STAT);
+                       writel(1, (rb + CT2_LPU0_HOSTFN_CMD_STAT));
                        readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
                }
-               r32 = readl(rb + CT2_LPU1_HOSTFN_CMD_STAT);
+               r32 = readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
                if (r32 == 1) {
-                       writel(1, rb + CT2_LPU1_HOSTFN_CMD_STAT);
-                       readl(rb + CT2_LPU1_HOSTFN_CMD_STAT);
+                       writel(1, (rb + CT2_LPU1_HOSTFN_CMD_STAT));
+                       readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
                }
        }
 
        bfa_ioc_ct2_mem_init(rb);
 
-       writel(BFI_IOC_UNINIT, rb + CT2_BFA_IOC0_STATE_REG);
-       writel(BFI_IOC_UNINIT, rb + CT2_BFA_IOC1_STATE_REG);
+       writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC0_STATE_REG));
+       writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC1_STATE_REG));
 
        return BFA_STATUS_OK;
 }
index 189fff71e3c25842904ff911d0b52d5203897577..a14c784ff3fc2d06338c5aa011f1e035afcd7f05 100644 (file)
@@ -45,6 +45,7 @@ struct bfa_modules_s {
        struct bfa_diag_s       diag_mod;       /*  diagnostics module  */
        struct bfa_phy_s        phy;            /*  phy module          */
        struct bfa_dconf_mod_s  dconf_mod;      /*  DCONF common module */
+       struct bfa_fru_s        fru;            /*  fru module          */
 };
 
 /*
index 95e4ad8759acfbcfc5d7ff27d29b40bac2e2f7b9..8ea7697deb9bdd87f6be661d6cf5a70ff44c171a 100644 (file)
@@ -250,6 +250,12 @@ bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
                return BFA_STATUS_IOC_FAILURE;
        }
 
+       /* if port is d-port enabled, return error */
+       if (port->dport_enabled) {
+               bfa_trc(port, BFA_STATUS_DPORT_ERR);
+               return BFA_STATUS_DPORT_ERR;
+       }
+
        if (port->endis_pending) {
                bfa_trc(port, BFA_STATUS_DEVBUSY);
                return BFA_STATUS_DEVBUSY;
@@ -300,6 +306,12 @@ bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
                return BFA_STATUS_IOC_FAILURE;
        }
 
+       /* if port is d-port enabled, return error */
+       if (port->dport_enabled) {
+               bfa_trc(port, BFA_STATUS_DPORT_ERR);
+               return BFA_STATUS_DPORT_ERR;
+       }
+
        if (port->endis_pending) {
                bfa_trc(port, BFA_STATUS_DEVBUSY);
                return BFA_STATUS_DEVBUSY;
@@ -431,6 +443,10 @@ bfa_port_notify(void *arg, enum bfa_ioc_event_e event)
                        port->endis_cbfn = NULL;
                        port->endis_pending = BFA_FALSE;
                }
+
+               /* clear D-port mode */
+               if (port->dport_enabled)
+                       bfa_port_set_dportenabled(port, BFA_FALSE);
                break;
        default:
                break;
@@ -467,6 +483,7 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
        port->stats_cbfn = NULL;
        port->endis_cbfn = NULL;
        port->pbc_disabled = BFA_FALSE;
+       port->dport_enabled = BFA_FALSE;
 
        bfa_ioc_mbox_regisr(port->ioc, BFI_MC_PORT, bfa_port_isr, port);
        bfa_q_qe_init(&port->ioc_notify);
@@ -482,6 +499,21 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
        bfa_trc(port, 0);
 }
 
+/*
+ * bfa_port_set_dportenabled();
+ *
+ * Port module- set pbc disabled flag
+ *
+ * @param[in] port - Pointer to the Port module data structure
+ *
+ * @return void
+ */
+void
+bfa_port_set_dportenabled(struct bfa_port_s *port, bfa_boolean_t enabled)
+{
+       port->dport_enabled = enabled;
+}
+
 /*
  *     CEE module specific definitions
  */
index 947f897328d6df96111a1ea192c3c22cc0a8ebc8..2fcab6bc62807cdd2ea6fcc1f48131e2fa9944b0 100644 (file)
@@ -45,6 +45,7 @@ struct bfa_port_s {
        bfa_status_t                    endis_status;
        struct bfa_ioc_notify_s         ioc_notify;
        bfa_boolean_t                   pbc_disabled;
+       bfa_boolean_t                   dport_enabled;
        struct bfa_mem_dma_s            port_dma;
 };
 
@@ -66,6 +67,8 @@ bfa_status_t bfa_port_disable(struct bfa_port_s *port,
 u32     bfa_port_meminfo(void);
 void        bfa_port_mem_claim(struct bfa_port_s *port,
                                 u8 *dma_kva, u64 dma_pa);
+void   bfa_port_set_dportenabled(struct bfa_port_s *port,
+                                 bfa_boolean_t enabled);
 
 /*
  * CEE declaration
index b2538d60db34aab67dc8ec69c8da7f49bb05b122..299c1c889b3389d36d896756e638fb6867d91dee 100644 (file)
@@ -67,6 +67,9 @@ enum bfa_fcport_sm_event {
        BFA_FCPORT_SM_LINKDOWN  = 7,    /*  firmware linkup down        */
        BFA_FCPORT_SM_QRESUME   = 8,    /*  CQ space available  */
        BFA_FCPORT_SM_HWFAIL    = 9,    /*  IOC h/w failure             */
+       BFA_FCPORT_SM_DPORTENABLE = 10, /*  enable dport      */
+       BFA_FCPORT_SM_DPORTDISABLE = 11,/*  disable dport     */
+       BFA_FCPORT_SM_FAA_MISCONFIG = 12,       /* FAA misconfiguratin */
 };
 
 /*
@@ -197,6 +200,10 @@ static void     bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
                                        enum bfa_fcport_sm_event event);
 static void     bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
                                        enum bfa_fcport_sm_event event);
+static void    bfa_fcport_sm_dport(struct bfa_fcport_s *fcport,
+                                       enum bfa_fcport_sm_event event);
+static void    bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
+                                       enum bfa_fcport_sm_event event);
 
 static void     bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
                                        enum bfa_fcport_ln_sm_event event);
@@ -226,6 +233,8 @@ static struct bfa_sm_table_s hal_port_sm_table[] = {
        {BFA_SM(bfa_fcport_sm_stopped), BFA_PORT_ST_STOPPED},
        {BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN},
        {BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN},
+       {BFA_SM(bfa_fcport_sm_dport), BFA_PORT_ST_DPORT},
+       {BFA_SM(bfa_fcport_sm_faa_misconfig), BFA_PORT_ST_FAA_MISCONFIG},
 };
 
 
@@ -1244,6 +1253,12 @@ bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
                 * Just ignore
                 */
                break;
+       case BFA_LPS_SM_SET_N2N_PID:
+               /*
+                * When topology is set to loop, bfa_lps_set_n2n_pid() sends
+                * this event. Ignore this event.
+                */
+               break;
 
        default:
                bfa_sm_fault(lps->bfa, event);
@@ -1261,6 +1276,7 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
 
        switch (event) {
        case BFA_LPS_SM_FWRSP:
+       case BFA_LPS_SM_OFFLINE:
                if (lps->status == BFA_STATUS_OK) {
                        bfa_sm_set_state(lps, bfa_lps_sm_online);
                        if (lps->fdisc)
@@ -1289,7 +1305,6 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
                bfa_lps_login_comp(lps);
                break;
 
-       case BFA_LPS_SM_OFFLINE:
        case BFA_LPS_SM_DELETE:
                bfa_sm_set_state(lps, bfa_lps_sm_init);
                break;
@@ -2169,6 +2184,12 @@ bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
                break;
 
+       case BFA_FCPORT_SM_FAA_MISCONFIG:
+               bfa_fcport_reset_linkinfo(fcport);
+               bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
+               bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
+               break;
+
        default:
                bfa_sm_fault(fcport->bfa, event);
        }
@@ -2225,6 +2246,12 @@ bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
                break;
 
+       case BFA_FCPORT_SM_FAA_MISCONFIG:
+               bfa_fcport_reset_linkinfo(fcport);
+               bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
+               bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
+               break;
+
        default:
                bfa_sm_fault(fcport->bfa, event);
        }
@@ -2250,11 +2277,11 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
                if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
 
                        bfa_trc(fcport->bfa,
-                               pevent->link_state.vc_fcf.fcf.fipenabled);
+                               pevent->link_state.attr.vc_fcf.fcf.fipenabled);
                        bfa_trc(fcport->bfa,
-                               pevent->link_state.vc_fcf.fcf.fipfailed);
+                               pevent->link_state.attr.vc_fcf.fcf.fipfailed);
 
-                       if (pevent->link_state.vc_fcf.fcf.fipfailed)
+                       if (pevent->link_state.attr.vc_fcf.fcf.fipfailed)
                                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
                                        BFA_PL_EID_FIP_FCF_DISC, 0,
                                        "FIP FCF Discovery Failed");
@@ -2311,6 +2338,12 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
                break;
 
+       case BFA_FCPORT_SM_FAA_MISCONFIG:
+               bfa_fcport_reset_linkinfo(fcport);
+               bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
+               bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
+               break;
+
        default:
                bfa_sm_fault(fcport->bfa, event);
        }
@@ -2404,6 +2437,12 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
                }
                break;
 
+       case BFA_FCPORT_SM_FAA_MISCONFIG:
+               bfa_fcport_reset_linkinfo(fcport);
+               bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
+               bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
+               break;
+
        default:
                bfa_sm_fault(fcport->bfa, event);
        }
@@ -2449,6 +2488,12 @@ bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
                bfa_reqq_wcancel(&fcport->reqq_wait);
                break;
 
+       case BFA_FCPORT_SM_FAA_MISCONFIG:
+               bfa_fcport_reset_linkinfo(fcport);
+               bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
+               bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
+               break;
+
        default:
                bfa_sm_fault(fcport->bfa, event);
        }
@@ -2600,6 +2645,10 @@ bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
                bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
                break;
 
+       case BFA_FCPORT_SM_DPORTENABLE:
+               bfa_sm_set_state(fcport, bfa_fcport_sm_dport);
+               break;
+
        default:
                bfa_sm_fault(fcport->bfa, event);
        }
@@ -2680,6 +2729,81 @@ bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
        }
 }
 
+static void
+bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event)
+{
+       bfa_trc(fcport->bfa, event);
+
+       switch (event) {
+       case BFA_FCPORT_SM_DPORTENABLE:
+       case BFA_FCPORT_SM_DISABLE:
+       case BFA_FCPORT_SM_ENABLE:
+       case BFA_FCPORT_SM_START:
+               /*
+                * Ignore event for a port that is dport
+                */
+               break;
+
+       case BFA_FCPORT_SM_STOP:
+               bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+               break;
+
+       case BFA_FCPORT_SM_HWFAIL:
+               bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+               break;
+
+       case BFA_FCPORT_SM_DPORTDISABLE:
+               bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+               break;
+
+       default:
+               bfa_sm_fault(fcport->bfa, event);
+       }
+}
+
+static void
+bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
+                           enum bfa_fcport_sm_event event)
+{
+       bfa_trc(fcport->bfa, event);
+
+       switch (event) {
+       case BFA_FCPORT_SM_DPORTENABLE:
+       case BFA_FCPORT_SM_ENABLE:
+       case BFA_FCPORT_SM_START:
+               /*
+                * Ignore event for a port as there is FAA misconfig
+                */
+               break;
+
+       case BFA_FCPORT_SM_DISABLE:
+               if (bfa_fcport_send_disable(fcport))
+                       bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+               else
+                       bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
+
+               bfa_fcport_reset_linkinfo(fcport);
+               bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
+               bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+                            BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+               bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
+               break;
+
+       case BFA_FCPORT_SM_STOP:
+               bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+               break;
+
+       case BFA_FCPORT_SM_HWFAIL:
+               bfa_fcport_reset_linkinfo(fcport);
+               bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
+               bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+               break;
+
+       default:
+               bfa_sm_fault(fcport->bfa, event);
+       }
+}
+
 /*
  * Link state is down
  */
@@ -2943,6 +3067,7 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
         */
        do_gettimeofday(&tv);
        fcport->stats_reset_time = tv.tv_sec;
+       fcport->stats_dma_ready = BFA_FALSE;
 
        /*
         * initialize and set default configuration
@@ -2953,6 +3078,9 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
        port_cfg->maxfrsize = 0;
 
        port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
+       port_cfg->qos_bw.high = BFA_QOS_BW_HIGH;
+       port_cfg->qos_bw.med = BFA_QOS_BW_MED;
+       port_cfg->qos_bw.low = BFA_QOS_BW_LOW;
 
        INIT_LIST_HEAD(&fcport->stats_pending_q);
        INIT_LIST_HEAD(&fcport->statsclr_pending_q);
@@ -2996,6 +3124,21 @@ bfa_fcport_iocdisable(struct bfa_s *bfa)
        bfa_trunk_iocdisable(bfa);
 }
 
+/*
+ * Update loop info in fcport for SCN online
+ */
+static void
+bfa_fcport_update_loop_info(struct bfa_fcport_s *fcport,
+                       struct bfa_fcport_loop_info_s *loop_info)
+{
+       fcport->myalpa = loop_info->myalpa;
+       fcport->alpabm_valid =
+                       loop_info->alpabm_val;
+       memcpy(fcport->alpabm.alpa_bm,
+                       loop_info->alpabm.alpa_bm,
+                       sizeof(struct fc_alpabm_s));
+}
+
 static void
 bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
 {
@@ -3005,12 +3148,15 @@ bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
        fcport->speed = pevent->link_state.speed;
        fcport->topology = pevent->link_state.topology;
 
-       if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP)
-               fcport->myalpa = 0;
+       if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP) {
+               bfa_fcport_update_loop_info(fcport,
+                               &pevent->link_state.attr.loop_info);
+               return;
+       }
 
        /* QoS Details */
        fcport->qos_attr = pevent->link_state.qos_attr;
-       fcport->qos_vc_attr = pevent->link_state.vc_fcf.qos_vc_attr;
+       fcport->qos_vc_attr = pevent->link_state.attr.vc_fcf.qos_vc_attr;
 
        /*
         * update trunk state if applicable
@@ -3019,7 +3165,8 @@ bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
                trunk->attr.state = BFA_TRUNK_DISABLED;
 
        /* update FCoE specific */
-       fcport->fcoe_vlan = be16_to_cpu(pevent->link_state.vc_fcf.fcf.vlan);
+       fcport->fcoe_vlan =
+               be16_to_cpu(pevent->link_state.attr.vc_fcf.fcf.vlan);
 
        bfa_trc(fcport->bfa, fcport->speed);
        bfa_trc(fcport->bfa, fcport->topology);
@@ -3453,6 +3600,7 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
        case BFI_FCPORT_I2H_ENABLE_RSP:
                if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) {
 
+                       fcport->stats_dma_ready = BFA_TRUE;
                        if (fcport->use_flash_cfg) {
                                fcport->cfg = i2hmsg.penable_rsp->port_cfg;
                                fcport->cfg.maxfrsize =
@@ -3468,6 +3616,8 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
                                else
                                        fcport->trunk.attr.state =
                                                BFA_TRUNK_DISABLED;
+                               fcport->qos_attr.qos_bw =
+                                       i2hmsg.penable_rsp->port_cfg.qos_bw;
                                fcport->use_flash_cfg = BFA_FALSE;
                        }
 
@@ -3476,6 +3626,9 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
                        else
                                fcport->qos_attr.state = BFA_QOS_DISABLED;
 
+                       fcport->qos_attr.qos_bw_op =
+                                       i2hmsg.penable_rsp->port_cfg.qos_bw;
+
                        bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
                }
                break;
@@ -3488,8 +3641,17 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
        case BFI_FCPORT_I2H_EVENT:
                if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)
                        bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
-               else
-                       bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKDOWN);
+               else {
+                       if (i2hmsg.event->link_state.linkstate_rsn ==
+                           BFA_PORT_LINKSTATE_RSN_FAA_MISCONFIG)
+                               bfa_sm_send_event(fcport,
+                                                 BFA_FCPORT_SM_FAA_MISCONFIG);
+                       else
+                               bfa_sm_send_event(fcport,
+                                                 BFA_FCPORT_SM_LINKDOWN);
+               }
+               fcport->qos_attr.qos_bw_op =
+                               i2hmsg.event->link_state.qos_attr.qos_bw_op;
                break;
 
        case BFI_FCPORT_I2H_TRUNK_SCN:
@@ -3609,6 +3771,9 @@ bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
 
        if (fcport->cfg.trunked == BFA_TRUE)
                return BFA_STATUS_TRUNK_ENABLED;
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+                       (speed == BFA_PORT_SPEED_16GBPS))
+               return BFA_STATUS_UNSUPP_SPEED;
        if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
                bfa_trc(bfa, fcport->speed_sup);
                return BFA_STATUS_UNSUPP_SPEED;
@@ -3663,7 +3828,26 @@ bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
 
        switch (topology) {
        case BFA_PORT_TOPOLOGY_P2P:
+               break;
+
        case BFA_PORT_TOPOLOGY_LOOP:
+               if ((bfa_fcport_is_qos_enabled(bfa) != BFA_FALSE) ||
+                       (fcport->qos_attr.state != BFA_QOS_DISABLED))
+                       return BFA_STATUS_ERROR_QOS_ENABLED;
+               if (fcport->cfg.ratelimit != BFA_FALSE)
+                       return BFA_STATUS_ERROR_TRL_ENABLED;
+               if ((bfa_fcport_is_trunk_enabled(bfa) != BFA_FALSE) ||
+                       (fcport->trunk.attr.state != BFA_TRUNK_DISABLED))
+                       return BFA_STATUS_ERROR_TRUNK_ENABLED;
+               if ((bfa_fcport_get_speed(bfa) == BFA_PORT_SPEED_16GBPS) ||
+                       (fcport->cfg.speed == BFA_PORT_SPEED_16GBPS))
+                       return BFA_STATUS_UNSUPP_SPEED;
+               if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type))
+                       return BFA_STATUS_LOOP_UNSUPP_MEZZ;
+               if (bfa_fcport_is_dport(bfa) != BFA_FALSE)
+                       return BFA_STATUS_DPORT_ERR;
+               break;
+
        case BFA_PORT_TOPOLOGY_AUTO:
                break;
 
@@ -3686,6 +3870,17 @@ bfa_fcport_get_topology(struct bfa_s *bfa)
        return fcport->topology;
 }
 
+/**
+ * Get config topology.
+ */
+enum bfa_port_topology
+bfa_fcport_get_cfg_topology(struct bfa_s *bfa)
+{
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+       return fcport->cfg.topology;
+}
+
 bfa_status_t
 bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
 {
@@ -3761,9 +3956,11 @@ bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
 u8
 bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
 {
-       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+       if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP)
+               return (BFA_FCPORT_MOD(bfa))->cfg.rx_bbcredit;
 
-       return fcport->cfg.rx_bbcredit;
+       else
+               return 0;
 }
 
 void
@@ -3850,8 +4047,9 @@ bfa_fcport_get_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
 {
        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
 
-       if (bfa_ioc_is_disabled(&bfa->ioc))
-               return BFA_STATUS_IOC_DISABLED;
+       if (!bfa_iocfc_is_operational(bfa) ||
+           !fcport->stats_dma_ready)
+               return BFA_STATUS_IOC_NON_OP;
 
        if (!list_empty(&fcport->statsclr_pending_q))
                return BFA_STATUS_DEVBUSY;
@@ -3876,6 +4074,10 @@ bfa_fcport_clear_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
 {
        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
 
+       if (!bfa_iocfc_is_operational(bfa) ||
+           !fcport->stats_dma_ready)
+               return BFA_STATUS_IOC_NON_OP;
+
        if (!list_empty(&fcport->stats_pending_q))
                return BFA_STATUS_DEVBUSY;
 
@@ -3904,6 +4106,40 @@ bfa_fcport_is_disabled(struct bfa_s *bfa)
 
 }
 
+bfa_boolean_t
+bfa_fcport_is_dport(struct bfa_s *bfa)
+{
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+       return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
+               BFA_PORT_ST_DPORT);
+}
+
+bfa_status_t
+bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw)
+{
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+       enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
+
+       bfa_trc(bfa, ioc_type);
+
+       if ((qos_bw->high == 0) || (qos_bw->med == 0) || (qos_bw->low == 0))
+               return BFA_STATUS_QOS_BW_INVALID;
+
+       if ((qos_bw->high + qos_bw->med + qos_bw->low) != 100)
+               return BFA_STATUS_QOS_BW_INVALID;
+
+       if ((qos_bw->med > qos_bw->high) || (qos_bw->low > qos_bw->med) ||
+           (qos_bw->low > qos_bw->high))
+               return BFA_STATUS_QOS_BW_INVALID;
+
+       if ((ioc_type == BFA_IOC_TYPE_FC) &&
+           (fcport->cfg.topology != BFA_PORT_TOPOLOGY_LOOP))
+               fcport->cfg.qos_bw = *qos_bw;
+
+       return BFA_STATUS_OK;
+}
+
 bfa_boolean_t
 bfa_fcport_is_ratelim(struct bfa_s *bfa)
 {
@@ -3981,6 +4217,26 @@ bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)
        return fcport->cfg.trunked;
 }
 
+void
+bfa_fcport_dportenable(struct bfa_s *bfa)
+{
+       /*
+        * Assume caller check for port is in disable state
+        */
+       bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTENABLE);
+       bfa_port_set_dportenabled(&bfa->modules.port, BFA_TRUE);
+}
+
+void
+bfa_fcport_dportdisable(struct bfa_s *bfa)
+{
+       /*
+        * Assume caller check for port is in disable state
+        */
+       bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTDISABLE);
+       bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE);
+}
+
 /*
  * Rport State machine functions
  */
@@ -4707,6 +4963,21 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
                bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
                break;
 
+       case BFI_RPORT_I2H_LIP_SCN_ONLINE:
+               bfa_fcport_update_loop_info(BFA_FCPORT_MOD(bfa),
+                               &msg.lip_scn->loop_info);
+               bfa_cb_rport_scn_online(bfa);
+               break;
+
+       case BFI_RPORT_I2H_LIP_SCN_OFFLINE:
+               bfa_cb_rport_scn_offline(bfa);
+               break;
+
+       case BFI_RPORT_I2H_NO_DEV:
+               rp = BFA_RPORT_FROM_TAG(bfa, msg.lip_scn->bfa_handle);
+               bfa_cb_rport_scn_no_dev(rp->rport_drv);
+               break;
+
        default:
                bfa_trc(bfa, m->mhdr.msg_id);
                WARN_ON(1);
@@ -5347,6 +5618,37 @@ bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)
        }
 }
 
+/*
+ *     Dport forward declaration
+ */
+
+/*
+ * BFA DPORT state machine events
+ */
+enum bfa_dport_sm_event {
+       BFA_DPORT_SM_ENABLE     = 1,    /* dport enable event         */
+       BFA_DPORT_SM_DISABLE    = 2,    /* dport disable event        */
+       BFA_DPORT_SM_FWRSP      = 3,    /* fw enable/disable rsp      */
+       BFA_DPORT_SM_QRESUME    = 4,    /* CQ space available         */
+       BFA_DPORT_SM_HWFAIL     = 5,    /* IOC h/w failure            */
+};
+
+static void bfa_dport_sm_disabled(struct bfa_dport_s *dport,
+                                 enum bfa_dport_sm_event event);
+static void bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
+                                 enum bfa_dport_sm_event event);
+static void bfa_dport_sm_enabling(struct bfa_dport_s *dport,
+                                 enum bfa_dport_sm_event event);
+static void bfa_dport_sm_enabled(struct bfa_dport_s *dport,
+                                enum bfa_dport_sm_event event);
+static void bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
+                                enum bfa_dport_sm_event event);
+static void bfa_dport_sm_disabling(struct bfa_dport_s *dport,
+                                  enum bfa_dport_sm_event event);
+static void bfa_dport_qresume(void *cbarg);
+static void bfa_dport_req_comp(struct bfa_dport_s *dport,
+                              bfi_diag_dport_rsp_t *msg);
+
 /*
  *     BFA fcdiag module
  */
@@ -5377,15 +5679,24 @@ bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
                struct bfa_pcidev_s *pcidev)
 {
        struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+       struct bfa_dport_s  *dport = &fcdiag->dport;
+
        fcdiag->bfa             = bfa;
        fcdiag->trcmod  = bfa->trcmod;
        /* The common DIAG attach bfa_diag_attach() will do all memory claim */
+       dport->bfa = bfa;
+       bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+       bfa_reqq_winit(&dport->reqq_wait, bfa_dport_qresume, dport);
+       dport->cbfn = NULL;
+       dport->cbarg = NULL;
 }
 
 static void
 bfa_fcdiag_iocdisable(struct bfa_s *bfa)
 {
        struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+       struct bfa_dport_s *dport = &fcdiag->dport;
+
        bfa_trc(fcdiag, fcdiag->lb.lock);
        if (fcdiag->lb.lock) {
                fcdiag->lb.status = BFA_STATUS_IOC_FAILURE;
@@ -5393,6 +5704,8 @@ bfa_fcdiag_iocdisable(struct bfa_s *bfa)
                fcdiag->lb.lock = 0;
                bfa_fcdiag_set_busy_status(fcdiag);
        }
+
+       bfa_sm_send_event(dport, BFA_DPORT_SM_HWFAIL);
 }
 
 static void
@@ -5577,6 +5890,9 @@ bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg)
        case BFI_DIAG_I2H_QTEST:
                bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg);
                break;
+       case BFI_DIAG_I2H_DPORT:
+               bfa_dport_req_comp(&fcdiag->dport, (bfi_diag_dport_rsp_t *)msg);
+               break;
        default:
                bfa_trc(fcdiag, msg->mhdr.msg_id);
                WARN_ON(1);
@@ -5646,12 +5962,18 @@ bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,
                }
        }
 
+       /*
+        * For CT2, 1G is not supported
+        */
+       if ((speed == BFA_PORT_SPEED_1GBPS) &&
+           (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id))) {
+               bfa_trc(fcdiag, speed);
+               return BFA_STATUS_UNSUPP_SPEED;
+       }
+
        /* For Mezz card, port speed entered needs to be checked */
        if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type)) {
                if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
-                       if ((speed == BFA_PORT_SPEED_1GBPS) &&
-                           (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))
-                               return BFA_STATUS_UNSUPP_SPEED;
                        if (!(speed == BFA_PORT_SPEED_1GBPS ||
                              speed == BFA_PORT_SPEED_2GBPS ||
                              speed == BFA_PORT_SPEED_4GBPS ||
@@ -5764,3 +6086,379 @@ bfa_fcdiag_lb_is_running(struct bfa_s *bfa)
        struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
        return fcdiag->lb.lock ?  BFA_STATUS_DIAG_BUSY : BFA_STATUS_OK;
 }
+
+/*
+ *     D-port
+ */
+static bfa_boolean_t bfa_dport_send_req(struct bfa_dport_s *dport,
+                                       enum bfi_dport_req req);
+static void
+bfa_cb_fcdiag_dport(struct bfa_dport_s *dport, bfa_status_t bfa_status)
+{
+       if (dport->cbfn != NULL) {
+               dport->cbfn(dport->cbarg, bfa_status);
+               dport->cbfn = NULL;
+               dport->cbarg = NULL;
+       }
+}
+
+static void
+bfa_dport_sm_disabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
+{
+       bfa_trc(dport->bfa, event);
+
+       switch (event) {
+       case BFA_DPORT_SM_ENABLE:
+               bfa_fcport_dportenable(dport->bfa);
+               if (bfa_dport_send_req(dport, BFI_DPORT_ENABLE))
+                       bfa_sm_set_state(dport, bfa_dport_sm_enabling);
+               else
+                       bfa_sm_set_state(dport, bfa_dport_sm_enabling_qwait);
+               break;
+
+       case BFA_DPORT_SM_DISABLE:
+               /* Already disabled */
+               break;
+
+       case BFA_DPORT_SM_HWFAIL:
+               /* ignore */
+               break;
+
+       default:
+               bfa_sm_fault(dport->bfa, event);
+       }
+}
+
+static void
+bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
+                           enum bfa_dport_sm_event event)
+{
+       bfa_trc(dport->bfa, event);
+
+       switch (event) {
+       case BFA_DPORT_SM_QRESUME:
+               bfa_sm_set_state(dport, bfa_dport_sm_enabling);
+               bfa_dport_send_req(dport, BFI_DPORT_ENABLE);
+               break;
+
+       case BFA_DPORT_SM_HWFAIL:
+               bfa_reqq_wcancel(&dport->reqq_wait);
+               bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+               bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
+               break;
+
+       default:
+               bfa_sm_fault(dport->bfa, event);
+       }
+}
+
+static void
+bfa_dport_sm_enabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
+{
+       bfa_trc(dport->bfa, event);
+
+       switch (event) {
+       case BFA_DPORT_SM_FWRSP:
+               bfa_sm_set_state(dport, bfa_dport_sm_enabled);
+               break;
+
+       case BFA_DPORT_SM_HWFAIL:
+               bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+               bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
+               break;
+
+       default:
+               bfa_sm_fault(dport->bfa, event);
+       }
+}
+
+static void
+bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
+{
+       bfa_trc(dport->bfa, event);
+
+       switch (event) {
+       case BFA_DPORT_SM_ENABLE:
+               /* Already enabled */
+               break;
+
+       case BFA_DPORT_SM_DISABLE:
+               bfa_fcport_dportdisable(dport->bfa);
+               if (bfa_dport_send_req(dport, BFI_DPORT_DISABLE))
+                       bfa_sm_set_state(dport, bfa_dport_sm_disabling);
+               else
+                       bfa_sm_set_state(dport, bfa_dport_sm_disabling_qwait);
+               break;
+
+       case BFA_DPORT_SM_HWFAIL:
+               bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+               break;
+
+       default:
+               bfa_sm_fault(dport->bfa, event);
+       }
+}
+
+static void
+bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
+                            enum bfa_dport_sm_event event)
+{
+       bfa_trc(dport->bfa, event);
+
+       switch (event) {
+       case BFA_DPORT_SM_QRESUME:
+               bfa_sm_set_state(dport, bfa_dport_sm_disabling);
+               bfa_dport_send_req(dport, BFI_DPORT_DISABLE);
+               break;
+
+       case BFA_DPORT_SM_HWFAIL:
+               bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+               bfa_reqq_wcancel(&dport->reqq_wait);
+               bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
+               break;
+
+       default:
+               bfa_sm_fault(dport->bfa, event);
+       }
+}
+
+static void
+bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
+{
+       bfa_trc(dport->bfa, event);
+
+       switch (event) {
+       case BFA_DPORT_SM_FWRSP:
+               bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+               break;
+
+       case BFA_DPORT_SM_HWFAIL:
+               bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+               bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
+               break;
+
+       default:
+               bfa_sm_fault(dport->bfa, event);
+       }
+}
+
+
+static bfa_boolean_t
+bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req)
+{
+       struct bfi_diag_dport_req_s *m;
+
+       /*
+        * Increment message tag before queue check, so that responses to old
+        * requests are discarded.
+        */
+       dport->msgtag++;
+
+       /*
+        * check for room in queue to send request now
+        */
+       m = bfa_reqq_next(dport->bfa, BFA_REQQ_DIAG);
+       if (!m) {
+               bfa_reqq_wait(dport->bfa, BFA_REQQ_PORT, &dport->reqq_wait);
+               return BFA_FALSE;
+       }
+
+       bfi_h2i_set(m->mh, BFI_MC_DIAG, BFI_DIAG_H2I_DPORT,
+                   bfa_fn_lpu(dport->bfa));
+       m->req  = req;
+       m->msgtag = dport->msgtag;
+
+       /*
+        * queue I/O message to firmware
+        */
+       bfa_reqq_produce(dport->bfa, BFA_REQQ_DIAG, m->mh);
+
+       return BFA_TRUE;
+}
+
+static void
+bfa_dport_qresume(void *cbarg)
+{
+       struct bfa_dport_s *dport = cbarg;
+
+       bfa_sm_send_event(dport, BFA_DPORT_SM_QRESUME);
+}
+
+static void
+bfa_dport_req_comp(struct bfa_dport_s *dport, bfi_diag_dport_rsp_t *msg)
+{
+       bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP);
+       bfa_cb_fcdiag_dport(dport, msg->status);
+}
+
+/*
+ * Dport enable
+ *
+ * @param[in] *bfa            - bfa data struct
+ */
+bfa_status_t
+bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
+{
+       struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+       struct bfa_dport_s  *dport = &fcdiag->dport;
+
+       /*
+        * Dport is not support in MEZZ card
+        */
+       if (bfa_mfg_is_mezz(dport->bfa->ioc.attr->card_type)) {
+               bfa_trc(dport->bfa, BFA_STATUS_PBC);
+               return BFA_STATUS_CMD_NOTSUPP_MEZZ;
+       }
+
+       /*
+        * Check to see if IOC is down
+       */
+       if (!bfa_iocfc_is_operational(bfa))
+               return BFA_STATUS_IOC_NON_OP;
+
+       /* if port is PBC disabled, return error */
+       if (bfa_fcport_is_pbcdisabled(bfa)) {
+               bfa_trc(dport->bfa, BFA_STATUS_PBC);
+               return BFA_STATUS_PBC;
+       }
+
+       /*
+        * Check if port mode is FC port
+        */
+       if (bfa_ioc_get_type(&bfa->ioc) != BFA_IOC_TYPE_FC) {
+               bfa_trc(dport->bfa, bfa_ioc_get_type(&bfa->ioc));
+               return BFA_STATUS_CMD_NOTSUPP_CNA;
+       }
+
+       /*
+        * Check if port is in LOOP mode
+        */
+       if ((bfa_fcport_get_cfg_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) ||
+           (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)) {
+               bfa_trc(dport->bfa, 0);
+               return BFA_STATUS_TOPOLOGY_LOOP;
+       }
+
+       /*
+        * Check if port is TRUNK mode
+        */
+       if (bfa_fcport_is_trunk_enabled(bfa)) {
+               bfa_trc(dport->bfa, 0);
+               return BFA_STATUS_ERROR_TRUNK_ENABLED;
+       }
+
+       /*
+        * Check to see if port is disable or in dport state
+        */
+       if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
+           (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
+               bfa_trc(dport->bfa, 0);
+               return BFA_STATUS_PORT_NOT_DISABLED;
+       }
+
+       /*
+        * Check if dport is busy
+        */
+       if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) ||
+           bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) ||
+           bfa_sm_cmp_state(dport, bfa_dport_sm_disabling) ||
+           bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait)) {
+               return BFA_STATUS_DEVBUSY;
+       }
+
+       /*
+        * Check if dport is already enabled
+        */
+       if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
+               bfa_trc(dport->bfa, 0);
+               return BFA_STATUS_DPORT_ENABLED;
+       }
+
+       dport->cbfn = cbfn;
+       dport->cbarg = cbarg;
+
+       bfa_sm_send_event(dport, BFA_DPORT_SM_ENABLE);
+       return BFA_STATUS_OK;
+}
+
+/*
+ *     Dport disable
+ *
+ *     @param[in] *bfa            - bfa data struct
+ */
+bfa_status_t
+bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
+{
+       struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+       struct bfa_dport_s *dport = &fcdiag->dport;
+
+       if (bfa_ioc_is_disabled(&bfa->ioc))
+               return BFA_STATUS_IOC_DISABLED;
+
+       /* if port is PBC disabled, return error */
+       if (bfa_fcport_is_pbcdisabled(bfa)) {
+               bfa_trc(dport->bfa, BFA_STATUS_PBC);
+               return BFA_STATUS_PBC;
+       }
+
+       /*
+        * Check to see if port is disable or in dport state
+        */
+       if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
+           (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
+               bfa_trc(dport->bfa, 0);
+               return BFA_STATUS_PORT_NOT_DISABLED;
+       }
+
+       /*
+        * Check if dport is busy
+        */
+       if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) ||
+           bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) ||
+           bfa_sm_cmp_state(dport, bfa_dport_sm_disabling) ||
+           bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait))
+               return BFA_STATUS_DEVBUSY;
+
+       /*
+        * Check if dport is already disabled
+        */
+       if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabled)) {
+               bfa_trc(dport->bfa, 0);
+               return BFA_STATUS_DPORT_DISABLED;
+       }
+
+       dport->cbfn = cbfn;
+       dport->cbarg = cbarg;
+
+       bfa_sm_send_event(dport, BFA_DPORT_SM_DISABLE);
+       return BFA_STATUS_OK;
+}
+
+/*
+ *     Get D-port state
+ *
+ * @param[in] *bfa            - bfa data struct
+ */
+
+bfa_status_t
+bfa_dport_get_state(struct bfa_s *bfa, enum bfa_dport_state *state)
+{
+       struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+       struct bfa_dport_s *dport = &fcdiag->dport;
+
+       if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabled))
+               *state = BFA_DPORT_ST_ENABLED;
+       else if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) ||
+                bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait))
+               *state = BFA_DPORT_ST_ENABLING;
+       else if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabled))
+               *state = BFA_DPORT_ST_DISABLED;
+       else if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabling) ||
+                bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait))
+               *state = BFA_DPORT_ST_DISABLING;
+       else {
+               bfa_trc(dport->bfa, BFA_STATUS_EINVAL);
+               return BFA_STATUS_EINVAL;
+       }
+       return BFA_STATUS_OK;
+}
index 1abcf7c51661f68cdbe286f29dda5363b2ccb5d9..8d7fbecfcb22d52bafb16b333bd35019ac6c0271 100644 (file)
@@ -474,8 +474,10 @@ struct bfa_fcport_s {
        /*  supported speeds */
        enum bfa_port_speed speed;      /*  current speed */
        enum bfa_port_topology topology;        /*  current topology */
-       u8                      myalpa; /*  my ALPA in LOOP topology */
        u8                      rsvd[3];
+       u8                      myalpa; /*  my ALPA in LOOP topology */
+       u8                      alpabm_valid; /* alpa bitmap valid or not */
+       struct fc_alpabm_s      alpabm; /* alpa bitmap */
        struct bfa_port_cfg_s   cfg;    /*  current port configuration */
        bfa_boolean_t           use_flash_cfg; /* get port cfg from flash */
        struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
@@ -512,6 +514,7 @@ struct bfa_fcport_s {
        struct bfa_fcport_trunk_s trunk;
        u16             fcoe_vlan;
        struct bfa_mem_dma_s    fcport_dma;
+       bfa_boolean_t           stats_dma_ready;
 };
 
 #define BFA_FCPORT_MOD(__bfa)  (&(__bfa)->modules.fcport)
@@ -534,6 +537,7 @@ enum bfa_port_speed bfa_fcport_get_speed(struct bfa_s *bfa);
 bfa_status_t bfa_fcport_cfg_topology(struct bfa_s *bfa,
                                     enum bfa_port_topology topo);
 enum bfa_port_topology bfa_fcport_get_topology(struct bfa_s *bfa);
+enum bfa_port_topology bfa_fcport_get_cfg_topology(struct bfa_s *bfa);
 bfa_status_t bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa);
 bfa_boolean_t bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa);
 u8 bfa_fcport_get_myalpa(struct bfa_s *bfa);
@@ -547,6 +551,9 @@ void bfa_fcport_event_register(struct bfa_s *bfa,
                        void (*event_cbfn) (void *cbarg,
                        enum bfa_port_linkstate event), void *event_cbarg);
 bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa);
+bfa_boolean_t bfa_fcport_is_dport(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_set_qos_bw(struct bfa_s *bfa,
+                                  struct bfa_qos_bw_s *qos_bw);
 enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
 
 void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn);
@@ -560,6 +567,8 @@ bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa,
                        struct bfa_cb_pending_q_s *cb);
 bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa);
 bfa_boolean_t bfa_fcport_is_trunk_enabled(struct bfa_s *bfa);
+void bfa_fcport_dportenable(struct bfa_s *bfa);
+void bfa_fcport_dportdisable(struct bfa_s *bfa);
 bfa_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa);
 void bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state);
 
@@ -575,6 +584,9 @@ void bfa_cb_rport_offline(void *rport);
 void bfa_cb_rport_qos_scn_flowid(void *rport,
                                 struct bfa_rport_qos_attr_s old_qos_attr,
                                 struct bfa_rport_qos_attr_s new_qos_attr);
+void bfa_cb_rport_scn_online(struct bfa_s *bfa);
+void bfa_cb_rport_scn_offline(struct bfa_s *bfa);
+void bfa_cb_rport_scn_no_dev(void *rp);
 void bfa_cb_rport_qos_scn_prio(void *rport,
                               struct bfa_rport_qos_attr_s old_qos_attr,
                               struct bfa_rport_qos_attr_s new_qos_attr);
@@ -697,11 +709,21 @@ struct bfa_fcdiag_lb_s {
        u32        status;
 };
 
+struct bfa_dport_s {
+       struct bfa_s    *bfa;           /* Back pointer to BFA  */
+       bfa_sm_t        sm;             /* finite state machine */
+       u32             msgtag;         /* firmware msg tag for reply */
+       struct bfa_reqq_wait_s reqq_wait;
+       bfa_cb_diag_t   cbfn;
+       void            *cbarg;
+};
+
 struct bfa_fcdiag_s {
        struct bfa_s    *bfa;           /* Back pointer to BFA */
        struct bfa_trc_mod_s   *trcmod;
        struct bfa_fcdiag_lb_s lb;
        struct bfa_fcdiag_qtest_s qtest;
+       struct bfa_dport_s      dport;
 };
 
 #define BFA_FCDIAG_MOD(__bfa)  (&(__bfa)->modules.fcdiag)
@@ -717,5 +739,11 @@ bfa_status_t       bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 ignore,
                        u32 queue, struct bfa_diag_qtest_result_s *result,
                        bfa_cb_diag_t cbfn, void *cbarg);
 bfa_status_t   bfa_fcdiag_lb_is_running(struct bfa_s *bfa);
+bfa_status_t   bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn,
+                                void *cbarg);
+bfa_status_t   bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn,
+                                 void *cbarg);
+bfa_status_t   bfa_dport_get_state(struct bfa_s *bfa,
+                                   enum bfa_dport_state *state);
 
 #endif /* __BFA_SVC_H__ */
index c37494916a1af1c3a7599db6926ff5242624d538..895b0e516e07cfb6d724ae39bdb6fe2992583b79 100644 (file)
@@ -63,9 +63,9 @@ int           max_rport_logins = BFA_FCS_MAX_RPORT_LOGINS;
 u32    bfi_image_cb_size, bfi_image_ct_size, bfi_image_ct2_size;
 u32    *bfi_image_cb, *bfi_image_ct, *bfi_image_ct2;
 
-#define BFAD_FW_FILE_CB                "cbfw.bin"
-#define BFAD_FW_FILE_CT                "ctfw.bin"
-#define BFAD_FW_FILE_CT2       "ct2fw.bin"
+#define BFAD_FW_FILE_CB                "cbfw-3.1.0.0.bin"
+#define BFAD_FW_FILE_CT                "ctfw-3.1.0.0.bin"
+#define BFAD_FW_FILE_CT2       "ct2fw-3.1.0.0.bin"
 
 static u32 *bfad_load_fwimg(struct pci_dev *pdev);
 static void bfad_free_fwimg(void);
index 0afa39076cef4e95f06c26f2c4e17916ed01c3d3..555e7db94a1c1b7e5bb3d4f3f69ce5d327f3f65c 100644 (file)
@@ -33,7 +33,7 @@ bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd)
        /* If IOC is not in disabled state - return */
        if (!bfa_ioc_is_disabled(&bfad->bfa.ioc)) {
                spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-               iocmd->status = BFA_STATUS_IOC_FAILURE;
+               iocmd->status = BFA_STATUS_OK;
                return rc;
        }
 
@@ -54,6 +54,12 @@ bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd)
        unsigned long   flags;
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
+       if (bfa_ioc_is_disabled(&bfad->bfa.ioc)) {
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               iocmd->status = BFA_STATUS_OK;
+               return rc;
+       }
+
        if (bfad->disable_active) {
                spin_unlock_irqrestore(&bfad->bfad_lock, flags);
                return -EBUSY;
@@ -101,9 +107,10 @@ bfad_iocmd_ioc_get_info(struct bfad_s *bfad, void *cmd)
 
        /* set adapter hw path */
        strcpy(iocmd->adapter_hwpath, bfad->pci_name);
-       i = strlen(iocmd->adapter_hwpath) - 1;
-       while (iocmd->adapter_hwpath[i] != '.')
-               i--;
+       for (i = 0; iocmd->adapter_hwpath[i] != ':' && i < BFA_STRING_32; i++)
+               ;
+       for (; iocmd->adapter_hwpath[++i] != ':' && i < BFA_STRING_32; )
+               ;
        iocmd->adapter_hwpath[i] = '\0';
        iocmd->status = BFA_STATUS_OK;
        return 0;
@@ -879,6 +886,19 @@ out:
        return 0;
 }
 
+int
+bfad_iocmd_qos_set_bw(struct bfad_s *bfad, void *pcmd)
+{
+       struct bfa_bsg_qos_bw_s *iocmd = (struct bfa_bsg_qos_bw_s *)pcmd;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_fcport_set_qos_bw(&bfad->bfa, &iocmd->qos_bw);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       return 0;
+}
+
 int
 bfad_iocmd_ratelim(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
 {
@@ -888,16 +908,22 @@ bfad_iocmd_ratelim(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
 
-       if (cmd == IOCMD_RATELIM_ENABLE)
-               fcport->cfg.ratelimit = BFA_TRUE;
-       else if (cmd == IOCMD_RATELIM_DISABLE)
-               fcport->cfg.ratelimit = BFA_FALSE;
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+               iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+       else {
+               if (cmd == IOCMD_RATELIM_ENABLE)
+                       fcport->cfg.ratelimit = BFA_TRUE;
+               else if (cmd == IOCMD_RATELIM_DISABLE)
+                       fcport->cfg.ratelimit = BFA_FALSE;
 
-       if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN)
-               fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS;
+               if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN)
+                       fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS;
+
+               iocmd->status = BFA_STATUS_OK;
+       }
 
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-       iocmd->status = BFA_STATUS_OK;
 
        return 0;
 }
@@ -919,8 +945,13 @@ bfad_iocmd_ratelim_speed(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
                return 0;
        }
 
-       fcport->cfg.trl_def_speed = iocmd->speed;
-       iocmd->status = BFA_STATUS_OK;
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+               iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+       else {
+               fcport->cfg.trl_def_speed = iocmd->speed;
+               iocmd->status = BFA_STATUS_OK;
+       }
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
        return 0;
@@ -1167,8 +1198,8 @@ bfad_iocmd_pcifn_create(struct bfad_s *bfad, void *cmd)
        spin_lock_irqsave(&bfad->bfad_lock, flags);
        iocmd->status = bfa_ablk_pf_create(&bfad->bfa.modules.ablk,
                                &iocmd->pcifn_id, iocmd->port,
-                               iocmd->pcifn_class, iocmd->bandwidth,
-                               bfad_hcb_comp, &fcomp);
+                               iocmd->pcifn_class, iocmd->bw_min,
+                               iocmd->bw_max, bfad_hcb_comp, &fcomp);
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
        if (iocmd->status != BFA_STATUS_OK)
                goto out;
@@ -1211,8 +1242,8 @@ bfad_iocmd_pcifn_bw(struct bfad_s *bfad, void *cmd)
        init_completion(&fcomp.comp);
        spin_lock_irqsave(&bfad->bfad_lock, flags);
        iocmd->status = bfa_ablk_pf_update(&bfad->bfa.modules.ablk,
-                               iocmd->pcifn_id, iocmd->bandwidth,
-                               bfad_hcb_comp, &fcomp);
+                               iocmd->pcifn_id, iocmd->bw_min,
+                               iocmd->bw_max, bfad_hcb_comp, &fcomp);
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
        bfa_trc(bfad, iocmd->status);
        if (iocmd->status != BFA_STATUS_OK)
@@ -1735,6 +1766,52 @@ bfad_iocmd_diag_lb_stat(struct bfad_s *bfad, void *cmd)
        return 0;
 }
 
+int
+bfad_iocmd_diag_cfg_dport(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
+{
+       struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
+       unsigned long   flags;
+       struct bfad_hal_comp fcomp;
+
+       init_completion(&fcomp.comp);
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       if (cmd == IOCMD_DIAG_DPORT_ENABLE)
+               iocmd->status = bfa_dport_enable(&bfad->bfa,
+                                       bfad_hcb_comp, &fcomp);
+       else if (cmd == IOCMD_DIAG_DPORT_DISABLE)
+               iocmd->status = bfa_dport_disable(&bfad->bfa,
+                                       bfad_hcb_comp, &fcomp);
+       else {
+               bfa_trc(bfad, 0);
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               return -EINVAL;
+       }
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       if (iocmd->status != BFA_STATUS_OK)
+               bfa_trc(bfad, iocmd->status);
+       else {
+               wait_for_completion(&fcomp.comp);
+               iocmd->status = fcomp.status;
+       }
+
+       return 0;
+}
+
+int
+bfad_iocmd_diag_dport_get_state(struct bfad_s *bfad, void *pcmd)
+{
+       struct bfa_bsg_diag_dport_get_state_s *iocmd =
+                       (struct bfa_bsg_diag_dport_get_state_s *)pcmd;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_dport_get_state(&bfad->bfa, &iocmd->state);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       return 0;
+}
+
 int
 bfad_iocmd_phy_get_attr(struct bfad_s *bfad, void *cmd)
 {
@@ -2052,7 +2129,7 @@ bfad_iocmd_boot_cfg(struct bfad_s *bfad, void *cmd)
        init_completion(&fcomp.comp);
        spin_lock_irqsave(&bfad->bfad_lock, flags);
        iocmd->status = bfa_flash_update_part(BFA_FLASH(&bfad->bfa),
-                       BFA_FLASH_PART_BOOT, PCI_FUNC(bfad->pcidev->devfn),
+                       BFA_FLASH_PART_BOOT, bfad->bfa.ioc.port_id,
                        &iocmd->cfg, sizeof(struct bfa_boot_cfg_s), 0,
                        bfad_hcb_comp, &fcomp);
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -2074,7 +2151,7 @@ bfad_iocmd_boot_query(struct bfad_s *bfad, void *cmd)
        init_completion(&fcomp.comp);
        spin_lock_irqsave(&bfad->bfad_lock, flags);
        iocmd->status = bfa_flash_read_part(BFA_FLASH(&bfad->bfa),
-                       BFA_FLASH_PART_BOOT, PCI_FUNC(bfad->pcidev->devfn),
+                       BFA_FLASH_PART_BOOT, bfad->bfa.ioc.port_id,
                        &iocmd->cfg, sizeof(struct bfa_boot_cfg_s), 0,
                        bfad_hcb_comp, &fcomp);
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -2161,22 +2238,31 @@ bfad_iocmd_cfg_trunk(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
 
-       if (v_cmd == IOCMD_TRUNK_ENABLE) {
-               trunk->attr.state = BFA_TRUNK_OFFLINE;
-               bfa_fcport_disable(&bfad->bfa);
-               fcport->cfg.trunked = BFA_TRUE;
-       } else if (v_cmd == IOCMD_TRUNK_DISABLE) {
-               trunk->attr.state = BFA_TRUNK_DISABLED;
-               bfa_fcport_disable(&bfad->bfa);
-               fcport->cfg.trunked = BFA_FALSE;
-       }
+       if (bfa_fcport_is_dport(&bfad->bfa))
+               return BFA_STATUS_DPORT_ERR;
 
-       if (!bfa_fcport_is_disabled(&bfad->bfa))
-               bfa_fcport_enable(&bfad->bfa);
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) ||
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+               iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+       else {
+               if (v_cmd == IOCMD_TRUNK_ENABLE) {
+                       trunk->attr.state = BFA_TRUNK_OFFLINE;
+                       bfa_fcport_disable(&bfad->bfa);
+                       fcport->cfg.trunked = BFA_TRUE;
+               } else if (v_cmd == IOCMD_TRUNK_DISABLE) {
+                       trunk->attr.state = BFA_TRUNK_DISABLED;
+                       bfa_fcport_disable(&bfad->bfa);
+                       fcport->cfg.trunked = BFA_FALSE;
+               }
+
+               if (!bfa_fcport_is_disabled(&bfad->bfa))
+                       bfa_fcport_enable(&bfad->bfa);
+
+               iocmd->status = BFA_STATUS_OK;
+       }
 
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
-       iocmd->status = BFA_STATUS_OK;
        return 0;
 }
 
@@ -2189,12 +2275,17 @@ bfad_iocmd_trunk_get_attr(struct bfad_s *bfad, void *cmd)
        unsigned long   flags;
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
-       memcpy((void *)&iocmd->attr, (void *)&trunk->attr,
-               sizeof(struct bfa_trunk_attr_s));
-       iocmd->attr.port_id = bfa_lps_get_base_pid(&bfad->bfa);
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) ||
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+               iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+       else {
+               memcpy((void *)&iocmd->attr, (void *)&trunk->attr,
+                       sizeof(struct bfa_trunk_attr_s));
+               iocmd->attr.port_id = bfa_lps_get_base_pid(&bfad->bfa);
+               iocmd->status = BFA_STATUS_OK;
+       }
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
-       iocmd->status = BFA_STATUS_OK;
        return 0;
 }
 
@@ -2207,14 +2298,22 @@ bfad_iocmd_qos(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
        if (bfa_ioc_get_type(&bfad->bfa.ioc) == BFA_IOC_TYPE_FC) {
-               if (v_cmd == IOCMD_QOS_ENABLE)
-                       fcport->cfg.qos_enabled = BFA_TRUE;
-               else if (v_cmd == IOCMD_QOS_DISABLE)
-                       fcport->cfg.qos_enabled = BFA_FALSE;
+               if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+                       iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+               else {
+                       if (v_cmd == IOCMD_QOS_ENABLE)
+                               fcport->cfg.qos_enabled = BFA_TRUE;
+                       else if (v_cmd == IOCMD_QOS_DISABLE) {
+                               fcport->cfg.qos_enabled = BFA_FALSE;
+                               fcport->cfg.qos_bw.high = BFA_QOS_BW_HIGH;
+                               fcport->cfg.qos_bw.med = BFA_QOS_BW_MED;
+                               fcport->cfg.qos_bw.low = BFA_QOS_BW_LOW;
+                       }
+               }
        }
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
-       iocmd->status = BFA_STATUS_OK;
        return 0;
 }
 
@@ -2226,11 +2325,21 @@ bfad_iocmd_qos_get_attr(struct bfad_s *bfad, void *cmd)
        unsigned long   flags;
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
-       iocmd->attr.state = fcport->qos_attr.state;
-       iocmd->attr.total_bb_cr = be32_to_cpu(fcport->qos_attr.total_bb_cr);
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+               iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+       else {
+               iocmd->attr.state = fcport->qos_attr.state;
+               iocmd->attr.total_bb_cr =
+                       be32_to_cpu(fcport->qos_attr.total_bb_cr);
+               iocmd->attr.qos_bw.high = fcport->cfg.qos_bw.high;
+               iocmd->attr.qos_bw.med = fcport->cfg.qos_bw.med;
+               iocmd->attr.qos_bw.low = fcport->cfg.qos_bw.low;
+               iocmd->attr.qos_bw_op = fcport->qos_attr.qos_bw_op;
+               iocmd->status = BFA_STATUS_OK;
+       }
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
-       iocmd->status = BFA_STATUS_OK;
        return 0;
 }
 
@@ -2274,6 +2383,7 @@ bfad_iocmd_qos_get_stats(struct bfad_s *bfad, void *cmd)
        struct bfad_hal_comp fcomp;
        unsigned long   flags;
        struct bfa_cb_pending_q_s cb_qe;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
 
        init_completion(&fcomp.comp);
        bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
@@ -2281,7 +2391,11 @@ bfad_iocmd_qos_get_stats(struct bfad_s *bfad, void *cmd)
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
        WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc));
-       iocmd->status = bfa_fcport_get_stats(&bfad->bfa, &cb_qe);
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+               iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+       else
+               iocmd->status = bfa_fcport_get_stats(&bfad->bfa, &cb_qe);
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
        if (iocmd->status != BFA_STATUS_OK) {
                bfa_trc(bfad, iocmd->status);
@@ -2300,6 +2414,7 @@ bfad_iocmd_qos_reset_stats(struct bfad_s *bfad, void *cmd)
        struct bfad_hal_comp fcomp;
        unsigned long   flags;
        struct bfa_cb_pending_q_s cb_qe;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
 
        init_completion(&fcomp.comp);
        bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
@@ -2307,7 +2422,11 @@ bfad_iocmd_qos_reset_stats(struct bfad_s *bfad, void *cmd)
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
        WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc));
-       iocmd->status = bfa_fcport_clear_stats(&bfad->bfa, &cb_qe);
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+               iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+       else
+               iocmd->status = bfa_fcport_clear_stats(&bfad->bfa, &cb_qe);
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
        if (iocmd->status != BFA_STATUS_OK) {
                bfa_trc(bfad, iocmd->status);
@@ -2435,6 +2554,139 @@ bfad_iocmd_fcpim_cfg_lunmask(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
        return 0;
 }
 
+int
+bfad_iocmd_fcpim_throttle_query(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_fcpim_throttle_s *iocmd =
+                       (struct bfa_bsg_fcpim_throttle_s *)cmd;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_fcpim_throttle_get(&bfad->bfa,
+                               (void *)&iocmd->throttle);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       return 0;
+}
+
+int
+bfad_iocmd_fcpim_throttle_set(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_fcpim_throttle_s *iocmd =
+                       (struct bfa_bsg_fcpim_throttle_s *)cmd;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_fcpim_throttle_set(&bfad->bfa,
+                               iocmd->throttle.cfg_value);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       return 0;
+}
+
+int
+bfad_iocmd_tfru_read(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_tfru_s *iocmd =
+                       (struct bfa_bsg_tfru_s *)cmd;
+       struct bfad_hal_comp fcomp;
+       unsigned long flags = 0;
+
+       init_completion(&fcomp.comp);
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_tfru_read(BFA_FRU(&bfad->bfa),
+                               &iocmd->data, iocmd->len, iocmd->offset,
+                               bfad_hcb_comp, &fcomp);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       if (iocmd->status == BFA_STATUS_OK) {
+               wait_for_completion(&fcomp.comp);
+               iocmd->status = fcomp.status;
+       }
+
+       return 0;
+}
+
+int
+bfad_iocmd_tfru_write(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_tfru_s *iocmd =
+                       (struct bfa_bsg_tfru_s *)cmd;
+       struct bfad_hal_comp fcomp;
+       unsigned long flags = 0;
+
+       init_completion(&fcomp.comp);
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_tfru_write(BFA_FRU(&bfad->bfa),
+                               &iocmd->data, iocmd->len, iocmd->offset,
+                               bfad_hcb_comp, &fcomp);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       if (iocmd->status == BFA_STATUS_OK) {
+               wait_for_completion(&fcomp.comp);
+               iocmd->status = fcomp.status;
+       }
+
+       return 0;
+}
+
+int
+bfad_iocmd_fruvpd_read(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_fruvpd_s *iocmd =
+                       (struct bfa_bsg_fruvpd_s *)cmd;
+       struct bfad_hal_comp fcomp;
+       unsigned long flags = 0;
+
+       init_completion(&fcomp.comp);
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_fruvpd_read(BFA_FRU(&bfad->bfa),
+                               &iocmd->data, iocmd->len, iocmd->offset,
+                               bfad_hcb_comp, &fcomp);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       if (iocmd->status == BFA_STATUS_OK) {
+               wait_for_completion(&fcomp.comp);
+               iocmd->status = fcomp.status;
+       }
+
+       return 0;
+}
+
+int
+bfad_iocmd_fruvpd_update(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_fruvpd_s *iocmd =
+                       (struct bfa_bsg_fruvpd_s *)cmd;
+       struct bfad_hal_comp fcomp;
+       unsigned long flags = 0;
+
+       init_completion(&fcomp.comp);
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_fruvpd_update(BFA_FRU(&bfad->bfa),
+                               &iocmd->data, iocmd->len, iocmd->offset,
+                               bfad_hcb_comp, &fcomp);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       if (iocmd->status == BFA_STATUS_OK) {
+               wait_for_completion(&fcomp.comp);
+               iocmd->status = fcomp.status;
+       }
+
+       return 0;
+}
+
+int
+bfad_iocmd_fruvpd_get_max_size(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_fruvpd_max_size_s *iocmd =
+                       (struct bfa_bsg_fruvpd_max_size_s *)cmd;
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_fruvpd_get_max_size(BFA_FRU(&bfad->bfa),
+                                               &iocmd->max_size);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       return 0;
+}
+
 static int
 bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
                unsigned int payload_len)
@@ -2660,6 +2912,13 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
        case IOCMD_DIAG_LB_STAT:
                rc = bfad_iocmd_diag_lb_stat(bfad, iocmd);
                break;
+       case IOCMD_DIAG_DPORT_ENABLE:
+       case IOCMD_DIAG_DPORT_DISABLE:
+               rc = bfad_iocmd_diag_cfg_dport(bfad, cmd, iocmd);
+               break;
+       case IOCMD_DIAG_DPORT_GET_STATE:
+               rc = bfad_iocmd_diag_dport_get_state(bfad, iocmd);
+               break;
        case IOCMD_PHY_GET_ATTR:
                rc = bfad_iocmd_phy_get_attr(bfad, iocmd);
                break;
@@ -2741,6 +3000,9 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
        case IOCMD_QOS_RESET_STATS:
                rc = bfad_iocmd_qos_reset_stats(bfad, iocmd);
                break;
+       case IOCMD_QOS_SET_BW:
+               rc = bfad_iocmd_qos_set_bw(bfad, iocmd);
+               break;
        case IOCMD_VF_GET_STATS:
                rc = bfad_iocmd_vf_get_stats(bfad, iocmd);
                break;
@@ -2759,6 +3021,29 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
        case IOCMD_FCPIM_LUNMASK_DELETE:
                rc = bfad_iocmd_fcpim_cfg_lunmask(bfad, iocmd, cmd);
                break;
+       case IOCMD_FCPIM_THROTTLE_QUERY:
+               rc = bfad_iocmd_fcpim_throttle_query(bfad, iocmd);
+               break;
+       case IOCMD_FCPIM_THROTTLE_SET:
+               rc = bfad_iocmd_fcpim_throttle_set(bfad, iocmd);
+               break;
+       /* TFRU */
+       case IOCMD_TFRU_READ:
+               rc = bfad_iocmd_tfru_read(bfad, iocmd);
+               break;
+       case IOCMD_TFRU_WRITE:
+               rc = bfad_iocmd_tfru_write(bfad, iocmd);
+               break;
+       /* FRU */
+       case IOCMD_FRUVPD_READ:
+               rc = bfad_iocmd_fruvpd_read(bfad, iocmd);
+               break;
+       case IOCMD_FRUVPD_UPDATE:
+               rc = bfad_iocmd_fruvpd_update(bfad, iocmd);
+               break;
+       case IOCMD_FRUVPD_GET_MAX_SIZE:
+               rc = bfad_iocmd_fruvpd_get_max_size(bfad, iocmd);
+               break;
        default:
                rc = -EINVAL;
                break;
index 8c569ddb750da571e368a490ea3884751db88c07..15e1fc8e796bc86d94862e0a0a1bab202c413b2e 100644 (file)
@@ -141,6 +141,17 @@ enum {
        IOCMD_FCPIM_LUNMASK_QUERY,
        IOCMD_FCPIM_LUNMASK_ADD,
        IOCMD_FCPIM_LUNMASK_DELETE,
+       IOCMD_DIAG_DPORT_ENABLE,
+       IOCMD_DIAG_DPORT_DISABLE,
+       IOCMD_DIAG_DPORT_GET_STATE,
+       IOCMD_QOS_SET_BW,
+       IOCMD_FCPIM_THROTTLE_QUERY,
+       IOCMD_FCPIM_THROTTLE_SET,
+       IOCMD_TFRU_READ,
+       IOCMD_TFRU_WRITE,
+       IOCMD_FRUVPD_READ,
+       IOCMD_FRUVPD_UPDATE,
+       IOCMD_FRUVPD_GET_MAX_SIZE,
 };
 
 struct bfa_bsg_gen_s {
@@ -463,7 +474,8 @@ struct bfa_bsg_pcifn_s {
        bfa_status_t            status;
        u16                     bfad_num;
        u16                     pcifn_id;
-       u32                     bandwidth;
+       u16                     bw_min;
+       u16                     bw_max;
        u8                      port;
        enum bfi_pcifn_class    pcifn_class;
        u8                      rsvd[1];
@@ -613,6 +625,13 @@ struct bfa_bsg_diag_lb_stat_s {
        u16             rsvd;
 };
 
+struct bfa_bsg_diag_dport_get_state_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       enum bfa_dport_state state;
+};
+
 struct bfa_bsg_phy_attr_s {
        bfa_status_t    status;
        u16     bfad_num;
@@ -694,6 +713,13 @@ struct bfa_bsg_qos_vc_attr_s {
        struct bfa_qos_vc_attr_s attr;
 };
 
+struct bfa_bsg_qos_bw_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       struct bfa_qos_bw_s qos_bw;
+};
+
 struct bfa_bsg_vf_stats_s {
        bfa_status_t    status;
        u16             bfad_num;
@@ -722,6 +748,41 @@ struct bfa_bsg_fcpim_lunmask_s {
        struct scsi_lun lun;
 };
 
+struct bfa_bsg_fcpim_throttle_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             vf_id;
+       struct bfa_defs_fcpim_throttle_s throttle;
+};
+
+#define BFA_TFRU_DATA_SIZE             64
+#define BFA_MAX_FRUVPD_TRANSFER_SIZE   0x1000
+
+struct bfa_bsg_tfru_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       u32             offset;
+       u32             len;
+       u8              data[BFA_TFRU_DATA_SIZE];
+};
+
+struct bfa_bsg_fruvpd_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       u32             offset;
+       u32             len;
+       u8              data[BFA_MAX_FRUVPD_TRANSFER_SIZE];
+};
+
+struct bfa_bsg_fruvpd_max_size_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             rsvd;
+       u32             max_size;
+};
+
 struct bfa_bsg_fcpt_s {
        bfa_status_t    status;
        u16             vf_id;
index 1840651ce1d49c141b4e064d30efe35067cf2c46..0c64a04f01fa65be82983f21e258c8129cb82a4c 100644 (file)
@@ -57,7 +57,7 @@
 #ifdef BFA_DRIVER_VERSION
 #define BFAD_DRIVER_VERSION    BFA_DRIVER_VERSION
 #else
-#define BFAD_DRIVER_VERSION    "3.1.2.0"
+#define BFAD_DRIVER_VERSION    "3.1.2.1"
 #endif
 
 #define BFAD_PROTO_NAME FCPI_NAME
index b2ba0b2e91b2cdfe03bed11ce417c95b880313e7..57b146bca18cea05beed14e22664303d62fa71cd 100644 (file)
@@ -210,7 +210,8 @@ enum bfi_mclass {
        BFI_MC_PORT             = 21,   /*  Physical port                   */
        BFI_MC_SFP              = 22,   /*  SFP module  */
        BFI_MC_PHY              = 25,   /*  External PHY message class  */
-       BFI_MC_MAX              = 32
+       BFI_MC_FRU              = 34,
+       BFI_MC_MAX              = 35
 };
 
 #define BFI_IOC_MAX_CQS                4
@@ -288,6 +289,9 @@ struct bfi_ioc_attr_s {
        char            optrom_version[BFA_VERSION_LEN];
        struct          bfa_mfg_vpd_s   vpd;
        u32     card_type;      /*  card type                   */
+       u8      mfg_day;        /* manufacturing day */
+       u8      mfg_month;      /* manufacturing month */
+       u16     mfg_year;       /* manufacturing year */
 };
 
 /*
@@ -687,7 +691,8 @@ struct bfi_ablk_h2i_pf_req_s {
        u8                      pcifn;
        u8                      port;
        u16                     pers;
-       u32                     bw;
+       u16                     bw_min; /* percent BW @ max speed */
+       u16                     bw_max; /* percent BW @ max speed */
 };
 
 /* BFI_ABLK_H2I_OPTROM_ENABLE, BFI_ABLK_H2I_OPTROM_DISABLE */
@@ -957,6 +962,7 @@ enum bfi_diag_h2i {
        BFI_DIAG_H2I_TEMPSENSOR = 4,
        BFI_DIAG_H2I_LEDTEST = 5,
        BFI_DIAG_H2I_QTEST      = 6,
+       BFI_DIAG_H2I_DPORT      = 7,
 };
 
 enum bfi_diag_i2h {
@@ -966,6 +972,7 @@ enum bfi_diag_i2h {
        BFI_DIAG_I2H_TEMPSENSOR = BFA_I2HM(BFI_DIAG_H2I_TEMPSENSOR),
        BFI_DIAG_I2H_LEDTEST = BFA_I2HM(BFI_DIAG_H2I_LEDTEST),
        BFI_DIAG_I2H_QTEST      = BFA_I2HM(BFI_DIAG_H2I_QTEST),
+       BFI_DIAG_I2H_DPORT      = BFA_I2HM(BFI_DIAG_H2I_DPORT),
 };
 
 #define BFI_DIAG_MAX_SGES      2
@@ -1051,6 +1058,23 @@ struct bfi_diag_qtest_req_s {
 };
 #define bfi_diag_qtest_rsp_t struct bfi_diag_qtest_req_s
 
+/*
+ *     D-port test
+ */
+enum bfi_dport_req {
+       BFI_DPORT_DISABLE       = 0,    /* disable dport request        */
+       BFI_DPORT_ENABLE        = 1,    /* enable dport request         */
+};
+
+struct bfi_diag_dport_req_s {
+       struct bfi_mhdr_s       mh;     /* 4 bytes                      */
+       u8                      req;    /* request 1: enable 0: disable */
+       u8                      status; /* reply status                 */
+       u8                      rsvd[2];
+       u32                     msgtag; /* msgtag for reply             */
+};
+#define bfi_diag_dport_rsp_t struct bfi_diag_dport_req_s
+
 /*
  *     PHY module specific
  */
@@ -1147,6 +1171,50 @@ struct bfi_phy_write_rsp_s {
        u32                     length;
 };
 
+enum bfi_fru_h2i_msgs {
+       BFI_FRUVPD_H2I_WRITE_REQ = 1,
+       BFI_FRUVPD_H2I_READ_REQ = 2,
+       BFI_TFRU_H2I_WRITE_REQ = 3,
+       BFI_TFRU_H2I_READ_REQ = 4,
+};
+
+enum bfi_fru_i2h_msgs {
+       BFI_FRUVPD_I2H_WRITE_RSP = BFA_I2HM(1),
+       BFI_FRUVPD_I2H_READ_RSP = BFA_I2HM(2),
+       BFI_TFRU_I2H_WRITE_RSP = BFA_I2HM(3),
+       BFI_TFRU_I2H_READ_RSP = BFA_I2HM(4),
+};
+
+/*
+ * FRU write request
+ */
+struct bfi_fru_write_req_s {
+       struct bfi_mhdr_s       mh;     /* Common msg header */
+       u8                      last;
+       u8                      rsv[3];
+       u32                     offset;
+       u32                     length;
+       struct bfi_alen_s       alen;
+};
+
+/*
+ * FRU read request
+ */
+struct bfi_fru_read_req_s {
+       struct bfi_mhdr_s       mh;     /* Common msg header */
+       u32                     offset;
+       u32                     length;
+       struct bfi_alen_s       alen;
+};
+
+/*
+ * FRU response
+ */
+struct bfi_fru_rsp_s {
+       struct bfi_mhdr_s       mh;     /* Common msg header */
+       u32                     status;
+       u32                     length;
+};
 #pragma pack()
 
 #endif /* __BFI_H__ */
index d4220e13cafa09a4d8e90193e75514f691f596be..5ae2c167b2c8e2e2d7a5e546e592c551a5d61e78 100644 (file)
@@ -426,6 +426,7 @@ struct bfi_lps_login_req_s {
        u8              auth_en;
        u8              lps_role;
        u8              bb_scn;
+       u32             vvl_flag;
 };
 
 struct bfi_lps_login_rsp_s {
@@ -499,6 +500,9 @@ enum bfi_rport_i2h_msgs {
        BFI_RPORT_I2H_CREATE_RSP = BFA_I2HM(1),
        BFI_RPORT_I2H_DELETE_RSP = BFA_I2HM(2),
        BFI_RPORT_I2H_QOS_SCN    = BFA_I2HM(3),
+       BFI_RPORT_I2H_LIP_SCN_ONLINE =  BFA_I2HM(4),
+       BFI_RPORT_I2H_LIP_SCN_OFFLINE = BFA_I2HM(5),
+       BFI_RPORT_I2H_NO_DEV    = BFA_I2HM(6),
 };
 
 struct bfi_rport_create_req_s {
@@ -551,6 +555,14 @@ struct bfi_rport_qos_scn_s {
        struct bfa_rport_qos_attr_s new_qos_attr;  /* New QoS Attributes */
 };
 
+struct bfi_rport_lip_scn_s {
+       struct bfi_mhdr_s  mh;          /*!< common msg header  */
+       u16     bfa_handle;     /*!< host rport handle  */
+       u8              status;         /*!< scn online status  */
+       u8              rsvd;
+       struct bfa_fcport_loop_info_s   loop_info;
+};
+
 union bfi_rport_h2i_msg_u {
        struct bfi_msg_s                *msg;
        struct bfi_rport_create_req_s   *create_req;
@@ -563,6 +575,7 @@ union bfi_rport_i2h_msg_u {
        struct bfi_rport_create_rsp_s   *create_rsp;
        struct bfi_rport_delete_rsp_s   *delete_rsp;
        struct bfi_rport_qos_scn_s      *qos_scn_evt;
+       struct bfi_rport_lip_scn_s      *lip_scn;
 };
 
 /*
@@ -828,6 +841,7 @@ enum bfi_tskim_status {
         */
        BFI_TSKIM_STS_TIMEOUT  = 10,    /*  TM request timedout */
        BFI_TSKIM_STS_ABORTED  = 11,    /*  Aborted on host request */
+       BFI_TSKIM_STS_UTAG     = 12,    /*  unknown tag for request */
 };
 
 struct bfi_tskim_rsp_s {
index ed5f159e18671383569522922d6cb9134849c0e2..99133bcf53f99f0ec6b9812fff8b173e5398fcbe 100644 (file)
@@ -338,6 +338,7 @@ enum {
 #define __A2T_AHB_LOAD                 0x00000800
 #define __WGN_READY                    0x00000400
 #define __GLBL_PF_VF_CFG_RDY           0x00000200
+#define CT2_NFC_STS_REG                        0x00027410
 #define CT2_NFC_CSR_CLR_REG            0x00027420
 #define CT2_NFC_CSR_SET_REG            0x00027424
 #define __HALT_NFC_CONTROLLER          0x00000002
@@ -355,6 +356,8 @@ enum {
        (CT2_CSI_MAC0_CONTROL_REG +     \
        (__n) * (CT2_CSI_MAC1_CONTROL_REG - CT2_CSI_MAC0_CONTROL_REG))
 
+#define CT2_NFC_FLASH_STS_REG          0x00014834
+#define __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS 0x00000020
 /*
  * Name semaphore registers based on usage
  */
index 078d262ac7ccf568a8840ec894ddd42136e9a46b..666b7ac4475f6921237d3cbb6f60e15b14fed936 100644 (file)
@@ -1643,7 +1643,7 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
        skb_reset_network_header(skb);
        skb->mac_len = elen;
        skb->protocol = htons(ETH_P_FCOE);
-       skb->priority = port->priority;
+       skb->priority = fcoe->priority;
 
        if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN &&
            fcoe->realdev->features & NETIF_F_HW_VLAN_TX) {
@@ -1917,7 +1917,6 @@ static int fcoe_dcb_app_notification(struct notifier_block *notifier,
        struct fcoe_ctlr *ctlr;
        struct fcoe_interface *fcoe;
        struct net_device *netdev;
-       struct fcoe_port *port;
        int prio;
 
        if (entry->app.selector != DCB_APP_IDTYPE_ETHTYPE)
@@ -1946,10 +1945,8 @@ static int fcoe_dcb_app_notification(struct notifier_block *notifier,
            entry->app.protocol == ETH_P_FCOE)
                ctlr->priority = prio;
 
-       if (entry->app.protocol == ETH_P_FCOE) {
-               port = lport_priv(ctlr->lp);
-               port->priority = prio;
-       }
+       if (entry->app.protocol == ETH_P_FCOE)
+               fcoe->priority = prio;
 
        return NOTIFY_OK;
 }
@@ -2180,7 +2177,6 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe)
        u8 fup, up;
        struct net_device *netdev = fcoe->realdev;
        struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe);
-       struct fcoe_port *port = lport_priv(ctlr->lp);
        struct dcb_app app = {
                                .priority = 0,
                                .protocol = ETH_P_FCOE
@@ -2202,8 +2198,8 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe)
                        fup = dcb_getapp(netdev, &app);
                }
 
-               port->priority = ffs(up) ? ffs(up) - 1 : 0;
-               ctlr->priority = ffs(fup) ? ffs(fup) - 1 : port->priority;
+               fcoe->priority = ffs(up) ? ffs(up) - 1 : 0;
+               ctlr->priority = ffs(fup) ? ffs(fup) - 1 : fcoe->priority;
        }
 #endif
 }
index a624add4f8ecbae730b01f6daab8b8f88ba1ea4d..b42dc32cb5eb1fc4a6c24b19961c8f05b41465ce 100644 (file)
@@ -71,6 +71,7 @@ do {                                                                  \
  * @oem:             The offload exchange manager for all local port
  *                   instances associated with this port
  * @removed:         Indicates fcoe interface removed from net device
+ * @priority:        Priority for the FCoE packet (DCB)
  * This structure is 1:1 with a net device.
  */
 struct fcoe_interface {
@@ -81,6 +82,7 @@ struct fcoe_interface {
        struct packet_type fip_packet_type;
        struct fc_exch_mgr *oem;
        u8      removed;
+       u8      priority;
 };
 
 #define fcoe_to_ctlr(x)                                                \
index 14243fa5f8e83fcc6208ddc340cfee7ab49dd2d8..fcb9d0b20ee4baa463dc34bf7fa4684d9f2fd6f2 100644 (file)
@@ -851,7 +851,8 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
                        fc_rp_info = (struct fcp_resp_rsp_info *)(rp_ex + 1);
                        if (flags & FCP_RSP_LEN_VAL) {
                                respl = ntohl(rp_ex->fr_rsp_len);
-                               if (respl != sizeof(*fc_rp_info))
+                               if ((respl != FCP_RESP_RSP_INFO_LEN4) &&
+                                   (respl != FCP_RESP_RSP_INFO_LEN8))
                                        goto len_err;
                                if (fsp->wait_for_comp) {
                                        /* Abuse cdb_status for rsp code */
index a184c2443a6401132f2c7edb1614f29e75ad3b90..69b59935b53f57787c6763ceae545886db641d43 100644 (file)
@@ -27,6 +27,8 @@
 
 struct lpfc_sli2_slim;
 
+#define ELX_MODEL_NAME_SIZE    80
+
 #define LPFC_PCI_DEV_LP                0x1
 #define LPFC_PCI_DEV_OC                0x2
 
index b032562aa0d9d32217487a3f7fb0a840c5e5580e..ad16e54ac383107749cfb783648fb932708a55b1 100644 (file)
@@ -3935,6 +3935,12 @@ MODULE_PARM_DESC(lpfc_fcp_look_ahead, "Look ahead for completions");
 #      - Only meaningful if BG is turned on (lpfc_enable_bg=1).
 #      - Allows you to ultimately specify which profiles to use
 #      - Default will result in registering capabilities for all profiles.
+#      - SHOST_DIF_TYPE1_PROTECTION    1
+#              HBA supports T10 DIF Type 1: HBA to Target Type 1 Protection
+#      - SHOST_DIX_TYPE0_PROTECTION    8
+#              HBA supports DIX Type 0: Host to HBA protection only
+#      - SHOST_DIX_TYPE1_PROTECTION    16
+#              HBA supports DIX Type 1: Host to HBA  Type 1 protection
 #
 */
 unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION |
@@ -3947,7 +3953,7 @@ MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask");
 /*
 # lpfc_prot_guard: i
 #      - Bit mask of protection guard types to register with the SCSI mid-layer
-#      - Guard types are currently either 1) IP checksum 2) T10-DIF CRC
+#      - Guard types are currently either 1) T10-DIF CRC 2) IP checksum
 #      - Allows you to ultimately specify which profiles to use
 #      - Default will result in registering capabilities for all guard types
 #
index e470c489de071b151c29191046472108fac9697c..4380a44000bc71df81f252b504f93a732991b12e 100644 (file)
@@ -467,3 +467,4 @@ int lpfc_sli4_read_config(struct lpfc_hba *);
 void lpfc_sli4_node_prep(struct lpfc_hba *);
 int lpfc_sli4_xri_sgl_update(struct lpfc_hba *);
 void lpfc_free_sgl_list(struct lpfc_hba *, struct list_head *);
+uint32_t lpfc_sli_port_speed_get(struct lpfc_hba *);
index cfe533bc97909cbda098734e3a4e2e99cee1de85..f19e9b6f9f133de56e484bc275109377dbc58664 100644 (file)
@@ -809,6 +809,8 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        phba->fc_ratov = FF_DEF_RATOV;
        rc = memcmp(&vport->fc_portname, &sp->portName,
                    sizeof(vport->fc_portname));
+       memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
+
        if (rc >= 0) {
                /* This side will initiate the PLOGI */
                spin_lock_irq(shost->host_lock);
@@ -3160,7 +3162,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                                retry = 1;
                                break;
                        }
-                       if (cmd == ELS_CMD_PLOGI) {
+                       if ((cmd == ELS_CMD_PLOGI) ||
+                           (cmd == ELS_CMD_PRLI)) {
                                delay = 1000;
                                maxretry = lpfc_max_els_tries + 1;
                                retry = 1;
@@ -3305,7 +3308,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                        ndlp->nlp_prev_state = ndlp->nlp_state;
                        if (cmd == ELS_CMD_PRLI)
                                lpfc_nlp_set_state(vport, ndlp,
-                                       NLP_STE_REG_LOGIN_ISSUE);
+                                       NLP_STE_PRLI_ISSUE);
                        else
                                lpfc_nlp_set_state(vport, ndlp,
                                        NLP_STE_NPR_NODE);
index e9845d2ecf10db6f6fd9eca8681aba1febee305a..d7096ad94d3fd2781fe44c5cbb1cf0e52f508199 100644 (file)
@@ -1506,9 +1506,10 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba,
                }
        }
 
-       /* If FCF not available return 0 */
+       /* FCF not valid/available or solicitation in progress */
        if (!bf_get(lpfc_fcf_record_fcf_avail, new_fcf_record) ||
-               !bf_get(lpfc_fcf_record_fcf_valid, new_fcf_record))
+           !bf_get(lpfc_fcf_record_fcf_valid, new_fcf_record) ||
+           bf_get(lpfc_fcf_record_fcf_sol, new_fcf_record))
                return 0;
 
        if (!(phba->hba_flag & HBA_FIP_SUPPORT)) {
@@ -1842,6 +1843,7 @@ lpfc_sli4_log_fcf_record_info(struct lpfc_hba *phba,
                        "\tFCF_Index     : x%x\n"
                        "\tFCF_Avail     : x%x\n"
                        "\tFCF_Valid     : x%x\n"
+                       "\tFCF_SOL       : x%x\n"
                        "\tFIP_Priority  : x%x\n"
                        "\tMAC_Provider  : x%x\n"
                        "\tLowest VLANID : x%x\n"
@@ -1852,6 +1854,7 @@ lpfc_sli4_log_fcf_record_info(struct lpfc_hba *phba,
                        bf_get(lpfc_fcf_record_fcf_index, fcf_record),
                        bf_get(lpfc_fcf_record_fcf_avail, fcf_record),
                        bf_get(lpfc_fcf_record_fcf_valid, fcf_record),
+                       bf_get(lpfc_fcf_record_fcf_sol, fcf_record),
                        fcf_record->fip_priority,
                        bf_get(lpfc_fcf_record_mac_addr_prov, fcf_record),
                        vlan_id,
@@ -2185,12 +2188,14 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                                               new_fcf_record));
                lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
                                "2781 FCF (x%x) failed connection "
-                               "list check: (x%x/x%x)\n",
+                               "list check: (x%x/x%x/%x)\n",
                                bf_get(lpfc_fcf_record_fcf_index,
                                       new_fcf_record),
                                bf_get(lpfc_fcf_record_fcf_avail,
                                       new_fcf_record),
                                bf_get(lpfc_fcf_record_fcf_valid,
+                                      new_fcf_record),
+                               bf_get(lpfc_fcf_record_fcf_sol,
                                       new_fcf_record));
                if ((phba->fcf.fcf_flag & FCF_IN_USE) &&
                    lpfc_sli4_fcf_record_match(phba, &phba->fcf.current_rec,
index 834b699cac7673db4972c82381bdf5e0a222bab0..2cdeb5434fb7760457761bab3f6c40607fc7d0f6 100644 (file)
@@ -1305,6 +1305,11 @@ struct lpfc_mbx_mq_create_ext {
 #define lpfc_mbx_mq_create_ext_async_evt_link_SHIFT    LPFC_TRAILER_CODE_LINK
 #define lpfc_mbx_mq_create_ext_async_evt_link_MASK     0x00000001
 #define lpfc_mbx_mq_create_ext_async_evt_link_WORD     async_evt_bmap
+#define LPFC_EVT_CODE_LINK_NO_LINK     0x0
+#define LPFC_EVT_CODE_LINK_10_MBIT     0x1
+#define LPFC_EVT_CODE_LINK_100_MBIT    0x2
+#define LPFC_EVT_CODE_LINK_1_GBIT      0x3
+#define LPFC_EVT_CODE_LINK_10_GBIT     0x4
 #define lpfc_mbx_mq_create_ext_async_evt_fip_SHIFT     LPFC_TRAILER_CODE_FCOE
 #define lpfc_mbx_mq_create_ext_async_evt_fip_MASK      0x00000001
 #define lpfc_mbx_mq_create_ext_async_evt_fip_WORD      async_evt_bmap
@@ -1314,6 +1319,13 @@ struct lpfc_mbx_mq_create_ext {
 #define lpfc_mbx_mq_create_ext_async_evt_fc_SHIFT      LPFC_TRAILER_CODE_FC
 #define lpfc_mbx_mq_create_ext_async_evt_fc_MASK       0x00000001
 #define lpfc_mbx_mq_create_ext_async_evt_fc_WORD       async_evt_bmap
+#define LPFC_EVT_CODE_FC_NO_LINK       0x0
+#define LPFC_EVT_CODE_FC_1_GBAUD       0x1
+#define LPFC_EVT_CODE_FC_2_GBAUD       0x2
+#define LPFC_EVT_CODE_FC_4_GBAUD       0x4
+#define LPFC_EVT_CODE_FC_8_GBAUD       0x8
+#define LPFC_EVT_CODE_FC_10_GBAUD      0xA
+#define LPFC_EVT_CODE_FC_16_GBAUD      0x10
 #define lpfc_mbx_mq_create_ext_async_evt_sli_SHIFT     LPFC_TRAILER_CODE_SLI
 #define lpfc_mbx_mq_create_ext_async_evt_sli_MASK      0x00000001
 #define lpfc_mbx_mq_create_ext_async_evt_sli_WORD      async_evt_bmap
@@ -1695,8 +1707,14 @@ struct fcf_record {
 #define lpfc_fcf_record_fc_map_2_MASK          0x000000FF
 #define lpfc_fcf_record_fc_map_2_WORD          word7
 #define lpfc_fcf_record_fcf_valid_SHIFT                24
-#define lpfc_fcf_record_fcf_valid_MASK         0x000000FF
+#define lpfc_fcf_record_fcf_valid_MASK         0x00000001
 #define lpfc_fcf_record_fcf_valid_WORD         word7
+#define lpfc_fcf_record_fcf_fc_SHIFT           25
+#define lpfc_fcf_record_fcf_fc_MASK            0x00000001
+#define lpfc_fcf_record_fcf_fc_WORD            word7
+#define lpfc_fcf_record_fcf_sol_SHIFT          31
+#define lpfc_fcf_record_fcf_sol_MASK           0x00000001
+#define lpfc_fcf_record_fcf_sol_WORD           word7
        uint32_t word8;
 #define lpfc_fcf_record_fcf_index_SHIFT                0
 #define lpfc_fcf_record_fcf_index_MASK         0x0000FFFF
index 8a55a586dd6540fd9acb4f18bdf41a7c3645e3ee..7dc4218d9c4c53c2ea57d81cee7f0b9d8803d21b 100644 (file)
@@ -1892,8 +1892,10 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
                max_speed = 4;
        else if (phba->lmt & LMT_2Gb)
                max_speed = 2;
-       else
+       else if (phba->lmt & LMT_1Gb)
                max_speed = 1;
+       else
+               max_speed = 0;
 
        vp = &phba->vpd;
 
@@ -2078,9 +2080,13 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
        if (descp && descp[0] == '\0') {
                if (oneConnect)
                        snprintf(descp, 255,
-                               "Emulex OneConnect %s, %s Initiator, Port %s",
+                               "Emulex OneConnect %s, %s Initiator %s",
                                m.name, m.function,
                                phba->Port);
+               else if (max_speed == 0)
+                       snprintf(descp, 255,
+                               "Emulex %s %s %s ",
+                               m.name, m.bus, m.function);
                else
                        snprintf(descp, 255,
                                "Emulex %s %d%s %s %s",
@@ -3501,6 +3507,119 @@ lpfc_sli4_parse_latt_link_speed(struct lpfc_hba *phba,
        return link_speed;
 }
 
+/**
+ * lpfc_sli_port_speed_get - Get sli3 link speed code to link speed
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is to get an SLI3 FC port's link speed in Mbps.
+ *
+ * Return: link speed in terms of Mbps.
+ **/
+uint32_t
+lpfc_sli_port_speed_get(struct lpfc_hba *phba)
+{
+       uint32_t link_speed;
+
+       if (!lpfc_is_link_up(phba))
+               return 0;
+
+       switch (phba->fc_linkspeed) {
+       case LPFC_LINK_SPEED_1GHZ:
+               link_speed = 1000;
+               break;
+       case LPFC_LINK_SPEED_2GHZ:
+               link_speed = 2000;
+               break;
+       case LPFC_LINK_SPEED_4GHZ:
+               link_speed = 4000;
+               break;
+       case LPFC_LINK_SPEED_8GHZ:
+               link_speed = 8000;
+               break;
+       case LPFC_LINK_SPEED_10GHZ:
+               link_speed = 10000;
+               break;
+       case LPFC_LINK_SPEED_16GHZ:
+               link_speed = 16000;
+               break;
+       default:
+               link_speed = 0;
+       }
+       return link_speed;
+}
+
+/**
+ * lpfc_sli4_port_speed_parse - Parse async evt link speed code to link speed
+ * @phba: pointer to lpfc hba data structure.
+ * @evt_code: asynchronous event code.
+ * @speed_code: asynchronous event link speed code.
+ *
+ * This routine is to parse the giving SLI4 async event link speed code into
+ * value of Mbps for the link speed.
+ *
+ * Return: link speed in terms of Mbps.
+ **/
+static uint32_t
+lpfc_sli4_port_speed_parse(struct lpfc_hba *phba, uint32_t evt_code,
+                          uint8_t speed_code)
+{
+       uint32_t port_speed;
+
+       switch (evt_code) {
+       case LPFC_TRAILER_CODE_LINK:
+               switch (speed_code) {
+               case LPFC_EVT_CODE_LINK_NO_LINK:
+                       port_speed = 0;
+                       break;
+               case LPFC_EVT_CODE_LINK_10_MBIT:
+                       port_speed = 10;
+                       break;
+               case LPFC_EVT_CODE_LINK_100_MBIT:
+                       port_speed = 100;
+                       break;
+               case LPFC_EVT_CODE_LINK_1_GBIT:
+                       port_speed = 1000;
+                       break;
+               case LPFC_EVT_CODE_LINK_10_GBIT:
+                       port_speed = 10000;
+                       break;
+               default:
+                       port_speed = 0;
+               }
+               break;
+       case LPFC_TRAILER_CODE_FC:
+               switch (speed_code) {
+               case LPFC_EVT_CODE_FC_NO_LINK:
+                       port_speed = 0;
+                       break;
+               case LPFC_EVT_CODE_FC_1_GBAUD:
+                       port_speed = 1000;
+                       break;
+               case LPFC_EVT_CODE_FC_2_GBAUD:
+                       port_speed = 2000;
+                       break;
+               case LPFC_EVT_CODE_FC_4_GBAUD:
+                       port_speed = 4000;
+                       break;
+               case LPFC_EVT_CODE_FC_8_GBAUD:
+                       port_speed = 8000;
+                       break;
+               case LPFC_EVT_CODE_FC_10_GBAUD:
+                       port_speed = 10000;
+                       break;
+               case LPFC_EVT_CODE_FC_16_GBAUD:
+                       port_speed = 16000;
+                       break;
+               default:
+                       port_speed = 0;
+               }
+               break;
+       default:
+               port_speed = 0;
+       }
+       return port_speed;
+}
+
 /**
  * lpfc_sli4_async_link_evt - Process the asynchronous FCoE link event
  * @phba: pointer to lpfc hba data structure.
@@ -3558,7 +3677,8 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba,
 
        /* Keep the link status for extra SLI4 state machine reference */
        phba->sli4_hba.link_state.speed =
-                               bf_get(lpfc_acqe_link_speed, acqe_link);
+                       lpfc_sli4_port_speed_parse(phba, LPFC_TRAILER_CODE_LINK,
+                               bf_get(lpfc_acqe_link_speed, acqe_link));
        phba->sli4_hba.link_state.duplex =
                                bf_get(lpfc_acqe_link_duplex, acqe_link);
        phba->sli4_hba.link_state.status =
@@ -3570,7 +3690,8 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba,
        phba->sli4_hba.link_state.fault =
                                bf_get(lpfc_acqe_link_fault, acqe_link);
        phba->sli4_hba.link_state.logical_speed =
-                       bf_get(lpfc_acqe_logical_link_speed, acqe_link);
+                       bf_get(lpfc_acqe_logical_link_speed, acqe_link) * 10;
+
        lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
                        "2900 Async FC/FCoE Link event - Speed:%dGBit "
                        "duplex:x%x LA Type:x%x Port Type:%d Port Number:%d "
@@ -3580,7 +3701,7 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba,
                        phba->sli4_hba.link_state.status,
                        phba->sli4_hba.link_state.type,
                        phba->sli4_hba.link_state.number,
-                       phba->sli4_hba.link_state.logical_speed * 10,
+                       phba->sli4_hba.link_state.logical_speed,
                        phba->sli4_hba.link_state.fault);
        /*
         * For FC Mode: issue the READ_TOPOLOGY mailbox command to fetch
@@ -3652,7 +3773,8 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
        }
        /* Keep the link status for extra SLI4 state machine reference */
        phba->sli4_hba.link_state.speed =
-                               bf_get(lpfc_acqe_fc_la_speed, acqe_fc);
+                       lpfc_sli4_port_speed_parse(phba, LPFC_TRAILER_CODE_FC,
+                               bf_get(lpfc_acqe_fc_la_speed, acqe_fc));
        phba->sli4_hba.link_state.duplex = LPFC_ASYNC_LINK_DUPLEX_FULL;
        phba->sli4_hba.link_state.topology =
                                bf_get(lpfc_acqe_fc_la_topology, acqe_fc);
@@ -3665,7 +3787,7 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
        phba->sli4_hba.link_state.fault =
                                bf_get(lpfc_acqe_link_fault, acqe_fc);
        phba->sli4_hba.link_state.logical_speed =
-                               bf_get(lpfc_acqe_fc_la_llink_spd, acqe_fc);
+                               bf_get(lpfc_acqe_fc_la_llink_spd, acqe_fc) * 10;
        lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
                        "2896 Async FC event - Speed:%dGBaud Topology:x%x "
                        "LA Type:x%x Port Type:%d Port Number:%d Logical speed:"
@@ -3675,7 +3797,7 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
                        phba->sli4_hba.link_state.status,
                        phba->sli4_hba.link_state.type,
                        phba->sli4_hba.link_state.number,
-                       phba->sli4_hba.link_state.logical_speed * 10,
+                       phba->sli4_hba.link_state.logical_speed,
                        phba->sli4_hba.link_state.fault);
        pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        if (!pmb) {
@@ -3783,14 +3905,18 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
        case LPFC_SLI_EVENT_STATUS_VALID:
                return; /* no message if the sfp is okay */
        case LPFC_SLI_EVENT_STATUS_NOT_PRESENT:
-               sprintf(message, "Not installed");
+               sprintf(message, "Optics faulted/incorrectly installed/not " \
+                               "installed - Reseat optics, if issue not "
+                               "resolved, replace.");
                break;
        case LPFC_SLI_EVENT_STATUS_WRONG_TYPE:
                sprintf(message,
-                       "Optics of two types installed");
+                       "Optics of two types installed - Remove one optic or " \
+                       "install matching pair of optics.");
                break;
        case LPFC_SLI_EVENT_STATUS_UNSUPPORTED:
-               sprintf(message, "Incompatible optics");
+               sprintf(message, "Incompatible optics - Replace with " \
+                               "compatible optics for card to function.");
                break;
        default:
                /* firmware is reporting a status we don't know about */
@@ -4161,11 +4287,11 @@ lpfc_sli4_async_grp5_evt(struct lpfc_hba *phba,
        phba->fcoe_eventtag = acqe_grp5->event_tag;
        prev_ll_spd = phba->sli4_hba.link_state.logical_speed;
        phba->sli4_hba.link_state.logical_speed =
-               (bf_get(lpfc_acqe_grp5_llink_spd, acqe_grp5));
+               (bf_get(lpfc_acqe_grp5_llink_spd, acqe_grp5)) * 10;
        lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
                        "2789 GRP5 Async Event: Updating logical link speed "
-                       "from %dMbps to %dMbps\n", (prev_ll_spd * 10),
-                       (phba->sli4_hba.link_state.logical_speed*10));
+                       "from %dMbps to %dMbps\n", prev_ll_spd,
+                       phba->sli4_hba.link_state.logical_speed);
 }
 
 /**
@@ -4947,7 +5073,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
        }
 
        phba->sli4_hba.msix_entries = kzalloc((sizeof(struct msix_entry) *
-                                     phba->sli4_hba.cfg_eqn), GFP_KERNEL);
+                                     phba->cfg_fcp_io_channel), GFP_KERNEL);
        if (!phba->sli4_hba.msix_entries) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "2573 Failed allocate memory for msi-x "
@@ -6559,7 +6685,8 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba)
                i++;
        }
        if (i < cfg_fcp_io_channel) {
-               lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
+               lpfc_printf_log(phba,
+                               KERN_ERR, LOG_INIT,
                                "3188 Reducing IO channels to match number of "
                                "CPUs: from %d to %d\n", cfg_fcp_io_channel, i);
                cfg_fcp_io_channel = i;
@@ -6567,8 +6694,8 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba)
 
        if (cfg_fcp_io_channel >
            phba->sli4_hba.max_cfg_param.max_eq) {
-               cfg_fcp_io_channel = phba->sli4_hba.max_cfg_param.max_eq;
-               if (cfg_fcp_io_channel < LPFC_FCP_IO_CHAN_MIN) {
+               if (phba->sli4_hba.max_cfg_param.max_eq <
+                   LPFC_FCP_IO_CHAN_MIN) {
                        lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                        "2574 Not enough EQs (%d) from the "
                                        "pci function for supporting FCP "
@@ -6577,13 +6704,12 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba)
                                        phba->cfg_fcp_io_channel);
                        goto out_error;
                }
-               lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
-                               "2575 Not enough EQs (%d) from the pci "
-                               "function for supporting the requested "
-                               "FCP EQs (%d), the actual FCP EQs can "
-                               "be supported: %d\n",
-                               phba->sli4_hba.max_cfg_param.max_eq,
-                               phba->cfg_fcp_io_channel, cfg_fcp_io_channel);
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "2575 Reducing IO channels to match number of "
+                               "available EQs: from %d to %d\n",
+                               cfg_fcp_io_channel,
+                               phba->sli4_hba.max_cfg_param.max_eq);
+               cfg_fcp_io_channel = phba->sli4_hba.max_cfg_param.max_eq;
        }
 
        /* Eventually cfg_fcp_eq_count / cfg_fcp_wq_count will be depricated */
@@ -6592,7 +6718,6 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba)
        phba->cfg_fcp_eq_count = cfg_fcp_io_channel;
        phba->cfg_fcp_wq_count = cfg_fcp_io_channel;
        phba->cfg_fcp_io_channel = cfg_fcp_io_channel;
-       phba->sli4_hba.cfg_eqn = cfg_fcp_io_channel;
 
        /* Get EQ depth from module parameter, fake the default for now */
        phba->sli4_hba.eq_esize = LPFC_EQE_SIZE_4B;
@@ -8095,11 +8220,11 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
        int vectors, rc, index;
 
        /* Set up MSI-X multi-message vectors */
-       for (index = 0; index < phba->sli4_hba.cfg_eqn; index++)
+       for (index = 0; index < phba->cfg_fcp_io_channel; index++)
                phba->sli4_hba.msix_entries[index].entry = index;
 
        /* Configure MSI-X capability structure */
-       vectors = phba->sli4_hba.cfg_eqn;
+       vectors = phba->cfg_fcp_io_channel;
 enable_msix_vectors:
        rc = pci_enable_msix(phba->pcidev, phba->sli4_hba.msix_entries,
                             vectors);
@@ -8142,8 +8267,14 @@ enable_msix_vectors:
                        goto cfg_fail_out;
                }
        }
-       phba->sli4_hba.msix_vec_nr = vectors;
 
+       if (vectors != phba->cfg_fcp_io_channel) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "3238 Reducing IO channels to match number of "
+                               "MSI-X vectors, requested %d got %d\n",
+                               phba->cfg_fcp_io_channel, vectors);
+               phba->cfg_fcp_io_channel = vectors;
+       }
        return rc;
 
 cfg_fail_out:
@@ -8171,7 +8302,7 @@ lpfc_sli4_disable_msix(struct lpfc_hba *phba)
        int index;
 
        /* Free up MSI-X multi-message vectors */
-       for (index = 0; index < phba->sli4_hba.msix_vec_nr; index++)
+       for (index = 0; index < phba->cfg_fcp_io_channel; index++)
                free_irq(phba->sli4_hba.msix_entries[index].vector,
                         &phba->sli4_hba.fcp_eq_hdl[index]);
 
@@ -9304,23 +9435,28 @@ lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *phba)
 
 /**
  * lpfc_write_firmware - attempt to write a firmware image to the port
- * @phba: pointer to lpfc hba data structure.
  * @fw: pointer to firmware image returned from request_firmware.
+ * @phba: pointer to lpfc hba data structure.
  *
- * returns the number of bytes written if write is successful.
- * returns a negative error value if there were errors.
- * returns 0 if firmware matches currently active firmware on port.
  **/
-int
-lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
+static void
+lpfc_write_firmware(const struct firmware *fw, void *context)
 {
+       struct lpfc_hba *phba = (struct lpfc_hba *)context;
        char fwrev[FW_REV_STR_SIZE];
-       struct lpfc_grp_hdr *image = (struct lpfc_grp_hdr *)fw->data;
+       struct lpfc_grp_hdr *image;
        struct list_head dma_buffer_list;
        int i, rc = 0;
        struct lpfc_dmabuf *dmabuf, *next;
        uint32_t offset = 0, temp_offset = 0;
 
+       /* It can be null, sanity check */
+       if (!fw) {
+               rc = -ENXIO;
+               goto out;
+       }
+       image = (struct lpfc_grp_hdr *)fw->data;
+
        INIT_LIST_HEAD(&dma_buffer_list);
        if ((be32_to_cpu(image->magic_number) != LPFC_GROUP_OJECT_MAGIC_NUM) ||
            (bf_get_be32(lpfc_grp_hdr_file_type, image) !=
@@ -9333,12 +9469,13 @@ lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
                                be32_to_cpu(image->magic_number),
                                bf_get_be32(lpfc_grp_hdr_file_type, image),
                                bf_get_be32(lpfc_grp_hdr_id, image));
-               return -EINVAL;
+               rc = -EINVAL;
+               goto release_out;
        }
        lpfc_decode_firmware_rev(phba, fwrev, 1);
        if (strncmp(fwrev, image->revision, strnlen(image->revision, 16))) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "3023 Updating Firmware. Current Version:%s "
+                               "3023 Updating Firmware, Current Version:%s "
                                "New Version:%s\n",
                                fwrev, image->revision);
                for (i = 0; i < LPFC_MBX_WR_CONFIG_MAX_BDE; i++) {
@@ -9346,7 +9483,7 @@ lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
                                         GFP_KERNEL);
                        if (!dmabuf) {
                                rc = -ENOMEM;
-                               goto out;
+                               goto release_out;
                        }
                        dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev,
                                                          SLI4_PAGE_SIZE,
@@ -9355,7 +9492,7 @@ lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
                        if (!dmabuf->virt) {
                                kfree(dmabuf);
                                rc = -ENOMEM;
-                               goto out;
+                               goto release_out;
                        }
                        list_add_tail(&dmabuf->list, &dma_buffer_list);
                }
@@ -9375,23 +9512,24 @@ lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
                        }
                        rc = lpfc_wr_object(phba, &dma_buffer_list,
                                    (fw->size - offset), &offset);
-                       if (rc) {
-                               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                                               "3024 Firmware update failed. "
-                                               "%d\n", rc);
-                               goto out;
-                       }
+                       if (rc)
+                               goto release_out;
                }
                rc = offset;
        }
-out:
+
+release_out:
        list_for_each_entry_safe(dmabuf, next, &dma_buffer_list, list) {
                list_del(&dmabuf->list);
                dma_free_coherent(&phba->pcidev->dev, SLI4_PAGE_SIZE,
                                  dmabuf->virt, dmabuf->phys);
                kfree(dmabuf);
        }
-       return rc;
+       release_firmware(fw);
+out:
+       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                       "3024 Firmware update done: %d.", rc);
+       return;
 }
 
 /**
@@ -9418,12 +9556,11 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        struct lpfc_hba   *phba;
        struct lpfc_vport *vport = NULL;
        struct Scsi_Host  *shost = NULL;
-       int error;
+       int error, ret;
        uint32_t cfg_mode, intr_mode;
        int mcnt;
        int adjusted_fcp_io_channel;
-       const struct firmware *fw;
-       uint8_t file_name[16];
+       uint8_t file_name[ELX_MODEL_NAME_SIZE];
 
        /* Allocate memory for HBA structure */
        phba = lpfc_hba_alloc(pdev);
@@ -9525,9 +9662,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
                /* Default to single EQ for non-MSI-X */
                if (phba->intr_type != MSIX)
                        adjusted_fcp_io_channel = 1;
-               else if (phba->sli4_hba.msix_vec_nr <
-                                       phba->cfg_fcp_io_channel)
-                       adjusted_fcp_io_channel = phba->sli4_hba.msix_vec_nr;
                else
                        adjusted_fcp_io_channel = phba->cfg_fcp_io_channel;
                phba->cfg_fcp_io_channel = adjusted_fcp_io_channel;
@@ -9572,12 +9706,12 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        /* check for firmware upgrade or downgrade (if_type 2 only) */
        if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
            LPFC_SLI_INTF_IF_TYPE_2) {
-               snprintf(file_name, 16, "%s.grp", phba->ModelName);
-               error = request_firmware(&fw, file_name, &phba->pcidev->dev);
-               if (!error) {
-                       lpfc_write_firmware(phba, fw);
-                       release_firmware(fw);
-               }
+               snprintf(file_name, ELX_MODEL_NAME_SIZE, "%s.grp",
+                        phba->ModelName);
+               ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+                                       file_name, &phba->pcidev->dev,
+                                       GFP_KERNEL, (void *)phba,
+                                       lpfc_write_firmware);
        }
 
        /* Check if there are static vports to be created. */
index 64013f3097ad2dc4cecc2df4bb7d50fe128d6b05..7f45ac9964a9222dff88a4de4a56cacc80ae7932 100644 (file)
@@ -3829,9 +3829,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
        cmd->scsi_done(cmd);
 
        if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
-               spin_lock_irq(&phba->hbalock);
+               spin_lock_irqsave(&phba->hbalock, flags);
                lpfc_cmd->pCmd = NULL;
-               spin_unlock_irq(&phba->hbalock);
+               spin_unlock_irqrestore(&phba->hbalock, flags);
 
                /*
                 * If there is a thread waiting for command completion
@@ -3871,9 +3871,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
                }
        }
 
-       spin_lock_irq(&phba->hbalock);
+       spin_lock_irqsave(&phba->hbalock, flags);
        lpfc_cmd->pCmd = NULL;
-       spin_unlock_irq(&phba->hbalock);
+       spin_unlock_irqrestore(&phba->hbalock, flags);
 
        /*
         * If there is a thread waiting for command completion
@@ -4163,7 +4163,7 @@ lpfc_info(struct Scsi_Host *host)
 {
        struct lpfc_vport *vport = (struct lpfc_vport *) host->hostdata;
        struct lpfc_hba   *phba = vport->phba;
-       int len;
+       int len, link_speed = 0;
        static char  lpfcinfobuf[384];
 
        memset(lpfcinfobuf,0,384);
@@ -4184,12 +4184,18 @@ lpfc_info(struct Scsi_Host *host)
                                 phba->Port);
                }
                len = strlen(lpfcinfobuf);
-               if (phba->sli4_hba.link_state.logical_speed) {
-                       snprintf(lpfcinfobuf + len,
-                                384-len,
-                                " Logical Link Speed: %d Mbps",
-                                phba->sli4_hba.link_state.logical_speed * 10);
+               if (phba->sli_rev <= LPFC_SLI_REV3) {
+                       link_speed = lpfc_sli_port_speed_get(phba);
+               } else {
+                       if (phba->sli4_hba.link_state.logical_speed)
+                               link_speed =
+                                     phba->sli4_hba.link_state.logical_speed;
+                       else
+                               link_speed = phba->sli4_hba.link_state.speed;
                }
+               if (link_speed != 0)
+                       snprintf(lpfcinfobuf + len, 384-len,
+                                " Logical Link Speed: %d Mbps", link_speed);
        }
        return lpfcinfobuf;
 }
@@ -4398,16 +4404,17 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
        struct lpfc_scsi_buf *lpfc_cmd;
        IOCB_t *cmd, *icmd;
        int ret = SUCCESS, status = 0;
+       unsigned long flags;
        DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
 
        status = fc_block_scsi_eh(cmnd);
        if (status != 0 && status != SUCCESS)
                return status;
 
-       spin_lock_irq(&phba->hbalock);
+       spin_lock_irqsave(&phba->hbalock, flags);
        /* driver queued commands are in process of being flushed */
        if (phba->hba_flag & HBA_FCP_IOQ_FLUSH) {
-               spin_unlock_irq(&phba->hbalock);
+               spin_unlock_irqrestore(&phba->hbalock, flags);
                lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
                        "3168 SCSI Layer abort requested I/O has been "
                        "flushed by LLD.\n");
@@ -4416,7 +4423,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
 
        lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
        if (!lpfc_cmd || !lpfc_cmd->pCmd) {
-               spin_unlock_irq(&phba->hbalock);
+               spin_unlock_irqrestore(&phba->hbalock, flags);
                lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
                         "2873 SCSI Layer I/O Abort Request IO CMPL Status "
                         "x%x ID %d LUN %d\n",
@@ -4427,7 +4434,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
        iocb = &lpfc_cmd->cur_iocbq;
        /* the command is in process of being cancelled */
        if (!(iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ)) {
-               spin_unlock_irq(&phba->hbalock);
+               spin_unlock_irqrestore(&phba->hbalock, flags);
                lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
                        "3169 SCSI Layer abort requested I/O has been "
                        "cancelled by LLD.\n");
@@ -4484,7 +4491,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
        abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
        abtsiocb->vport = vport;
        /* no longer need the lock after this point */
-       spin_unlock_irq(&phba->hbalock);
+       spin_unlock_irqrestore(&phba->hbalock, flags);
 
        if (lpfc_sli_issue_iocb(phba, LPFC_FCP_RING, abtsiocb, 0) ==
            IOCB_ERROR) {
@@ -4516,7 +4523,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
        goto out;
 
 out_unlock:
-       spin_unlock_irq(&phba->hbalock);
+       spin_unlock_irqrestore(&phba->hbalock, flags);
 out:
        lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
                         "0749 SCSI Layer I/O Abort Request Status x%x ID %d "
index 219bf534ef9934584cdd3c24365c8766040ba75d..d7f3313ef8869d2d72a975b47c4cb5987a48f43d 100644 (file)
@@ -3964,9 +3964,9 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba)
        pci_write_config_word(phba->pcidev, PCI_COMMAND, (cfg_value &
                              ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
 
-       /* Perform FCoE PCI function reset */
-       lpfc_sli4_queue_destroy(phba);
+       /* Perform FCoE PCI function reset before freeing queue memory */
        rc = lpfc_pci_function_reset(phba);
+       lpfc_sli4_queue_destroy(phba);
 
        /* Restore PCI cmd register */
        pci_write_config_word(phba->pcidev, PCI_COMMAND, cfg_value);
@@ -7071,6 +7071,40 @@ lpfc_sli4_async_mbox_unblock(struct lpfc_hba *phba)
        lpfc_worker_wake_up(phba);
 }
 
+/**
+ * lpfc_sli4_wait_bmbx_ready - Wait for bootstrap mailbox register ready
+ * @phba: Pointer to HBA context object.
+ * @mboxq: Pointer to mailbox object.
+ *
+ * The function waits for the bootstrap mailbox register ready bit from
+ * port for twice the regular mailbox command timeout value.
+ *
+ *      0 - no timeout on waiting for bootstrap mailbox register ready.
+ *      MBXERR_ERROR - wait for bootstrap mailbox register timed out.
+ **/
+static int
+lpfc_sli4_wait_bmbx_ready(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
+{
+       uint32_t db_ready;
+       unsigned long timeout;
+       struct lpfc_register bmbx_reg;
+
+       timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mboxq)
+                                  * 1000) + jiffies;
+
+       do {
+               bmbx_reg.word0 = readl(phba->sli4_hba.BMBXregaddr);
+               db_ready = bf_get(lpfc_bmbx_rdy, &bmbx_reg);
+               if (!db_ready)
+                       msleep(2);
+
+               if (time_after(jiffies, timeout))
+                       return MBXERR_ERROR;
+       } while (!db_ready);
+
+       return 0;
+}
+
 /**
  * lpfc_sli4_post_sync_mbox - Post an SLI4 mailbox to the bootstrap mailbox
  * @phba: Pointer to HBA context object.
@@ -7092,15 +7126,12 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 {
        int rc = MBX_SUCCESS;
        unsigned long iflag;
-       uint32_t db_ready;
        uint32_t mcqe_status;
        uint32_t mbx_cmnd;
-       unsigned long timeout;
        struct lpfc_sli *psli = &phba->sli;
        struct lpfc_mqe *mb = &mboxq->u.mqe;
        struct lpfc_bmbx_create *mbox_rgn;
        struct dma_address *dma_address;
-       struct lpfc_register bmbx_reg;
 
        /*
         * Only one mailbox can be active to the bootstrap mailbox region
@@ -7124,6 +7155,11 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
        phba->sli.mbox_active = mboxq;
        spin_unlock_irqrestore(&phba->hbalock, iflag);
 
+       /* wait for bootstrap mbox register for readyness */
+       rc = lpfc_sli4_wait_bmbx_ready(phba, mboxq);
+       if (rc)
+               goto exit;
+
        /*
         * Initialize the bootstrap memory region to avoid stale data areas
         * in the mailbox post.  Then copy the caller's mailbox contents to
@@ -7138,35 +7174,18 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
        dma_address = &phba->sli4_hba.bmbx.dma_address;
        writel(dma_address->addr_hi, phba->sli4_hba.BMBXregaddr);
 
-       timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mboxq)
-                                  * 1000) + jiffies;
-       do {
-               bmbx_reg.word0 = readl(phba->sli4_hba.BMBXregaddr);
-               db_ready = bf_get(lpfc_bmbx_rdy, &bmbx_reg);
-               if (!db_ready)
-                       msleep(2);
-
-               if (time_after(jiffies, timeout)) {
-                       rc = MBXERR_ERROR;
-                       goto exit;
-               }
-       } while (!db_ready);
+       /* wait for bootstrap mbox register for hi-address write done */
+       rc = lpfc_sli4_wait_bmbx_ready(phba, mboxq);
+       if (rc)
+               goto exit;
 
        /* Post the low mailbox dma address to the port. */
        writel(dma_address->addr_lo, phba->sli4_hba.BMBXregaddr);
-       timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mboxq)
-                                  * 1000) + jiffies;
-       do {
-               bmbx_reg.word0 = readl(phba->sli4_hba.BMBXregaddr);
-               db_ready = bf_get(lpfc_bmbx_rdy, &bmbx_reg);
-               if (!db_ready)
-                       msleep(2);
 
-               if (time_after(jiffies, timeout)) {
-                       rc = MBXERR_ERROR;
-                       goto exit;
-               }
-       } while (!db_ready);
+       /* wait for bootstrap mbox register for low address write done */
+       rc = lpfc_sli4_wait_bmbx_ready(phba, mboxq);
+       if (rc)
+               goto exit;
 
        /*
         * Read the CQ to ensure the mailbox has completed.
@@ -8090,6 +8109,8 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                bf_set(wqe_lenloc, &wqe->fcp_icmd.wqe_com,
                       LPFC_WQE_LENLOC_NONE);
                bf_set(wqe_ebde_cnt, &wqe->fcp_icmd.wqe_com, 0);
+               bf_set(wqe_erp, &wqe->fcp_icmd.wqe_com,
+                      iocbq->iocb.ulpFCP2Rcvy);
                break;
        case CMD_GEN_REQUEST64_CR:
                /* For this command calculate the xmit length of the
@@ -12099,6 +12120,7 @@ lpfc_modify_fcp_eq_delay(struct lpfc_hba *phba, uint16_t startq)
        struct lpfc_queue *eq;
        int cnt, rc, length, status = 0;
        uint32_t shdr_status, shdr_add_status;
+       uint32_t result;
        int fcp_eqidx;
        union lpfc_sli4_cfg_shdr *shdr;
        uint16_t dmult;
@@ -12117,8 +12139,11 @@ lpfc_modify_fcp_eq_delay(struct lpfc_hba *phba, uint16_t startq)
        eq_delay = &mbox->u.mqe.un.eq_delay;
 
        /* Calculate delay multiper from maximum interrupt per second */
-       dmult = phba->cfg_fcp_imax / phba->cfg_fcp_io_channel;
-       dmult = LPFC_DMULT_CONST/dmult - 1;
+       result = phba->cfg_fcp_imax / phba->cfg_fcp_io_channel;
+       if (result > LPFC_DMULT_CONST)
+               dmult = 0;
+       else
+               dmult = LPFC_DMULT_CONST/result - 1;
 
        cnt = 0;
        for (fcp_eqidx = startq; fcp_eqidx < phba->cfg_fcp_io_channel;
@@ -12174,7 +12199,7 @@ lpfc_modify_fcp_eq_delay(struct lpfc_hba *phba, uint16_t startq)
  * fails this function will return -ENXIO.
  **/
 uint32_t
-lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint16_t imax)
+lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax)
 {
        struct lpfc_mbx_eq_create *eq_create;
        LPFC_MBOXQ_t *mbox;
@@ -12206,7 +12231,10 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint16_t imax)
               LPFC_EQE_SIZE);
        bf_set(lpfc_eq_context_valid, &eq_create->u.request.context, 1);
        /* Calculate delay multiper from maximum interrupt per second */
-       dmult = LPFC_DMULT_CONST/imax - 1;
+       if (imax > LPFC_DMULT_CONST)
+               dmult = 0;
+       else
+               dmult = LPFC_DMULT_CONST/imax - 1;
        bf_set(lpfc_eq_context_delay_multi, &eq_create->u.request.context,
               dmult);
        switch (eq->entry_count) {
index bd4bc4342ae227b43824277985d1103b70a17695..f44a06a4c6e743fc32af95b1984d0e824865e3c0 100644 (file)
@@ -37,7 +37,7 @@
 /* Multi-queue arrangement for FCP EQ/CQ/WQ tuples */
 #define LPFC_FCP_IO_CHAN_DEF       4
 #define LPFC_FCP_IO_CHAN_MIN       1
-#define LPFC_FCP_IO_CHAN_MAX       8
+#define LPFC_FCP_IO_CHAN_MAX       16
 
 /*
  * Provide the default FCF Record attributes used by the driver
@@ -168,7 +168,7 @@ struct lpfc_queue {
 };
 
 struct lpfc_sli4_link {
-       uint8_t speed;
+       uint16_t speed;
        uint8_t duplex;
        uint8_t status;
        uint8_t type;
@@ -490,8 +490,6 @@ struct lpfc_sli4_hba {
        struct lpfc_pc_sli4_params pc_sli4_params;
        struct msix_entry *msix_entries;
        uint8_t handler_name[LPFC_FCP_IO_CHAN_MAX][LPFC_SLI4_HANDLER_NAME_SZ];
-       uint32_t cfg_eqn;
-       uint32_t msix_vec_nr;
        struct lpfc_fcp_eq_hdl *fcp_eq_hdl; /* FCP per-WQ handle */
 
        /* Pointers to the constructed SLI4 queues */
@@ -626,7 +624,7 @@ void lpfc_sli4_hba_reset(struct lpfc_hba *);
 struct lpfc_queue *lpfc_sli4_queue_alloc(struct lpfc_hba *, uint32_t,
                        uint32_t);
 void lpfc_sli4_queue_free(struct lpfc_queue *);
-uint32_t lpfc_eq_create(struct lpfc_hba *, struct lpfc_queue *, uint16_t);
+uint32_t lpfc_eq_create(struct lpfc_hba *, struct lpfc_queue *, uint32_t);
 uint32_t lpfc_modify_fcp_eq_delay(struct lpfc_hba *, uint16_t);
 uint32_t lpfc_cq_create(struct lpfc_hba *, struct lpfc_queue *,
                        struct lpfc_queue *, uint32_t, uint32_t);
index 04265a1c4e52e6e11cfaccea9b05fdcb0582bf34..0c2149189dda625769cee4ec88ee579ec8f51456 100644 (file)
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.3.34"
+#define LPFC_DRIVER_VERSION "8.3.35"
 #define LPFC_DRIVER_NAME               "lpfc"
 
 /* Used for SLI 2/3 */
index fcb005fa4bd136480367d7fe92bdd55b30a5f7df..16b7a72a70c4aae344cefb39f64d4b9ca5155eb8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Linux MegaRAID driver for SAS based RAID controllers
  *
- *  Copyright (c) 2009-2011  LSI Corporation.
+ *  Copyright (c) 2003-2012  LSI Corporation.
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
@@ -33,9 +33,9 @@
 /*
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION                                "00.00.06.18-rc1"
-#define MEGASAS_RELDATE                                "Jun. 17, 2012"
-#define MEGASAS_EXT_VERSION                    "Tue. Jun. 17 17:00:00 PDT 2012"
+#define MEGASAS_VERSION                                "06.504.01.00-rc1"
+#define MEGASAS_RELDATE                                "Oct. 1, 2012"
+#define MEGASAS_EXT_VERSION                    "Mon. Oct. 1 17:00:00 PDT 2012"
 
 /*
  * Device IDs
index 0393ec478cdf41257aebbf2e7e2cee7a244583eb..d2c5366aff7fba67ffa0bdef6007d69ff8e37de2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Linux MegaRAID driver for SAS based RAID controllers
  *
- *  Copyright (c) 2009-2011  LSI Corporation.
+ *  Copyright (c) 2003-2012  LSI Corporation.
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
@@ -18,7 +18,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  *  FILE: megaraid_sas_base.c
- *  Version : v00.00.06.18-rc1
+ *  Version : v06.504.01.00-rc1
  *
  *  Authors: LSI Corporation
  *           Sreenivas Bagalkote
@@ -71,6 +71,10 @@ static int msix_disable;
 module_param(msix_disable, int, S_IRUGO);
 MODULE_PARM_DESC(msix_disable, "Disable MSI-X interrupt handling. Default: 0");
 
+static unsigned int msix_vectors;
+module_param(msix_vectors, int, S_IRUGO);
+MODULE_PARM_DESC(msix_vectors, "MSI-X max vector count. Default: Set by FW");
+
 static int throttlequeuedepth = MEGASAS_THROTTLE_QUEUE_DEPTH;
 module_param(throttlequeuedepth, int, S_IRUGO);
 MODULE_PARM_DESC(throttlequeuedepth,
@@ -3520,6 +3524,10 @@ static int megasas_init_fw(struct megasas_instance *instance)
                        instance->msix_vectors = (readl(&instance->reg_set->
                                                        outbound_scratch_pad_2
                                                          ) & 0x1F) + 1;
+                       if (msix_vectors)
+                               instance->msix_vectors =
+                                       min(msix_vectors,
+                                           instance->msix_vectors);
                } else
                        instance->msix_vectors = 1;
                /* Don't bother allocating more MSI-X vectors than cpus */
@@ -5233,7 +5241,6 @@ megasas_aen_polling(struct work_struct *work)
 
                case MR_EVT_PD_REMOVED:
                        if (megasas_get_pd_list(instance) == 0) {
-                       megasas_get_pd_list(instance);
                        for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
                                for (j = 0;
                                j < MEGASAS_MAX_DEV_PER_CHANNEL;
index e3d251a2e26a027dd1ef43f891aa6e27d1cdd83a..a11df82474ef7308599fc094df341f19c109ed60 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Linux MegaRAID driver for SAS based RAID controllers
  *
- *  Copyright (c) 2009-2011  LSI Corporation.
+ *  Copyright (c) 2009-2012  LSI Corporation.
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
index ddf094e7d0acf8b628745389ee87d206da80e4c4..74030aff69ade500943cfce018f699af67e670cb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Linux MegaRAID driver for SAS based RAID controllers
  *
- *  Copyright (c) 2009-2011  LSI Corporation.
+ *  Copyright (c) 2009-2012  LSI Corporation.
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
@@ -1184,8 +1184,6 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
                io_request->CDB.EEDP32.PrimaryReferenceTag =
                        cpu_to_be32(ref_tag);
                io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff;
-
-               io_request->DataLength = num_blocks * 512;
                io_request->IoFlags = 32; /* Specify 32-byte cdb */
 
                /* Transfer length */
@@ -1329,7 +1327,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
                          struct megasas_cmd_fusion *cmd)
 {
        u8 fp_possible;
-       u32 start_lba_lo, start_lba_hi, device_id;
+       u32 start_lba_lo, start_lba_hi, device_id, datalength = 0;
        struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
        union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
        struct IO_REQUEST_INFO io_info;
@@ -1355,7 +1353,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
         * 6-byte READ(0x08) or WRITE(0x0A) cdb
         */
        if (scp->cmd_len == 6) {
-               io_request->DataLength = (u32) scp->cmnd[4];
+               datalength = (u32) scp->cmnd[4];
                start_lba_lo = ((u32) scp->cmnd[1] << 16) |
                        ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3];
 
@@ -1366,7 +1364,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
         * 10-byte READ(0x28) or WRITE(0x2A) cdb
         */
        else if (scp->cmd_len == 10) {
-               io_request->DataLength = (u32) scp->cmnd[8] |
+               datalength = (u32) scp->cmnd[8] |
                        ((u32) scp->cmnd[7] << 8);
                start_lba_lo = ((u32) scp->cmnd[2] << 24) |
                        ((u32) scp->cmnd[3] << 16) |
@@ -1377,7 +1375,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
         * 12-byte READ(0xA8) or WRITE(0xAA) cdb
         */
        else if (scp->cmd_len == 12) {
-               io_request->DataLength = ((u32) scp->cmnd[6] << 24) |
+               datalength = ((u32) scp->cmnd[6] << 24) |
                        ((u32) scp->cmnd[7] << 16) |
                        ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
                start_lba_lo = ((u32) scp->cmnd[2] << 24) |
@@ -1389,7 +1387,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
         * 16-byte READ(0x88) or WRITE(0x8A) cdb
         */
        else if (scp->cmd_len == 16) {
-               io_request->DataLength = ((u32) scp->cmnd[10] << 24) |
+               datalength = ((u32) scp->cmnd[10] << 24) |
                        ((u32) scp->cmnd[11] << 16) |
                        ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13];
                start_lba_lo = ((u32) scp->cmnd[6] << 24) |
@@ -1403,8 +1401,9 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
 
        memset(&io_info, 0, sizeof(struct IO_REQUEST_INFO));
        io_info.ldStartBlock = ((u64)start_lba_hi << 32) | start_lba_lo;
-       io_info.numBlocks = io_request->DataLength;
+       io_info.numBlocks = datalength;
        io_info.ldTgtId = device_id;
+       io_request->DataLength = scsi_bufflen(scp);
 
        if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
                io_info.isRead = 1;
@@ -1431,7 +1430,6 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
        if (fp_possible) {
                megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp,
                                   local_map_ptr, start_lba_lo);
-               io_request->DataLength = scsi_bufflen(scp);
                io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
                cmd->request_desc->SCSIIO.RequestFlags =
                        (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY
@@ -1510,7 +1508,8 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
        local_map_ptr = fusion->ld_map[(instance->map_id & 1)];
 
        /* Check if this is a system PD I/O */
-       if (instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) {
+       if (scmd->device->channel < MEGASAS_MAX_PD_CHANNELS &&
+           instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) {
                io_request->Function = 0;
                io_request->DevHandle =
                        local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
@@ -1525,6 +1524,8 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
                cmd->request_desc->SCSIIO.RequestFlags =
                        (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
                         MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+               cmd->request_desc->SCSIIO.DevHandle =
+                       local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
        } else {
                io_request->Function  = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
                io_request->DevHandle = device_id;
@@ -1732,8 +1733,6 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
        if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
                return IRQ_NONE;
 
-       d_val.word = desc->Words;
-
        num_completed = 0;
 
        while ((d_val.u.low != UINT_MAX) && (d_val.u.high != UINT_MAX)) {
@@ -1855,10 +1854,8 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
        }
        spin_unlock_irqrestore(&instance->hba_lock, flags);
 
-       spin_lock_irqsave(&instance->completion_lock, flags);
        for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++)
                complete_cmd_fusion(instance, MSIxIndex);
-       spin_unlock_irqrestore(&instance->completion_lock, flags);
 }
 
 /**
index 088c9f91da95fc4f2a0da32e427502dcde3ea267..a7c64f0519965b348c596f968cd0a1ea6eee1587 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Linux MegaRAID driver for SAS based RAID controllers
  *
- *  Copyright (c) 2009-2011  LSI Corporation.
+ *  Copyright (c) 2009-2012  LSI Corporation.
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
index 783edc7c6b9849a8ee4af732e9c8c3207daf672c..c585a925b3cd1e159832b86a8b531b011059ec91 100644 (file)
 #include <linux/io.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_eh.h>
 #include <linux/uaccess.h>
+#include <linux/kthread.h>
 
 #include "mvumi.h"
 
@@ -48,6 +50,7 @@ MODULE_DESCRIPTION("Marvell UMI Driver");
 
 static DEFINE_PCI_DEVICE_TABLE(mvumi_pci_table) = {
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_2, PCI_DEVICE_ID_MARVELL_MV9143) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_2, PCI_DEVICE_ID_MARVELL_MV9580) },
        { 0 }
 };
 
@@ -118,7 +121,7 @@ static int mvumi_map_pci_addr(struct pci_dev *dev, void **addr_array)
 static struct mvumi_res *mvumi_alloc_mem_resource(struct mvumi_hba *mhba,
                                enum resource_type type, unsigned int size)
 {
-       struct mvumi_res *res = kzalloc(sizeof(*res), GFP_KERNEL);
+       struct mvumi_res *res = kzalloc(sizeof(*res), GFP_ATOMIC);
 
        if (!res) {
                dev_err(&mhba->pdev->dev,
@@ -128,7 +131,7 @@ static struct mvumi_res *mvumi_alloc_mem_resource(struct mvumi_hba *mhba,
 
        switch (type) {
        case RESOURCE_CACHED_MEMORY:
-               res->virt_addr = kzalloc(size, GFP_KERNEL);
+               res->virt_addr = kzalloc(size, GFP_ATOMIC);
                if (!res->virt_addr) {
                        dev_err(&mhba->pdev->dev,
                                "unable to allocate memory,size = %d.\n", size);
@@ -222,11 +225,11 @@ static int mvumi_make_sgl(struct mvumi_hba *mhba, struct scsi_cmnd *scmd,
                        m_sg->baseaddr_l = cpu_to_le32(lower_32_bits(busaddr));
                        m_sg->baseaddr_h = cpu_to_le32(upper_32_bits(busaddr));
                        m_sg->flags = 0;
-                       m_sg->size = cpu_to_le32(sg_dma_len(&sg[i]));
+                       sgd_setsz(mhba, m_sg, cpu_to_le32(sg_dma_len(&sg[i])));
                        if ((i + 1) == *sg_count)
-                               m_sg->flags |= SGD_EOT;
+                               m_sg->flags |= 1U << mhba->eot_flag;
 
-                       m_sg++;
+                       sgd_inc(mhba, m_sg);
                }
        } else {
                scmd->SCp.dma_handle = scsi_bufflen(scmd) ?
@@ -237,8 +240,8 @@ static int mvumi_make_sgl(struct mvumi_hba *mhba, struct scsi_cmnd *scmd,
                busaddr = scmd->SCp.dma_handle;
                m_sg->baseaddr_l = cpu_to_le32(lower_32_bits(busaddr));
                m_sg->baseaddr_h = cpu_to_le32(upper_32_bits(busaddr));
-               m_sg->flags = SGD_EOT;
-               m_sg->size = cpu_to_le32(scsi_bufflen(scmd));
+               m_sg->flags = 1U << mhba->eot_flag;
+               sgd_setsz(mhba, m_sg, cpu_to_le32(scsi_bufflen(scmd)));
                *sg_count = 1;
        }
 
@@ -267,8 +270,8 @@ static int mvumi_internal_cmd_sgl(struct mvumi_hba *mhba, struct mvumi_cmd *cmd,
 
        m_sg->baseaddr_l = cpu_to_le32(lower_32_bits(phy_addr));
        m_sg->baseaddr_h = cpu_to_le32(upper_32_bits(phy_addr));
-       m_sg->flags = SGD_EOT;
-       m_sg->size = cpu_to_le32(size);
+       m_sg->flags = 1U << mhba->eot_flag;
+       sgd_setsz(mhba, m_sg, cpu_to_le32(size));
 
        return 0;
 }
@@ -285,7 +288,8 @@ static struct mvumi_cmd *mvumi_create_internal_cmd(struct mvumi_hba *mhba,
        }
        INIT_LIST_HEAD(&cmd->queue_pointer);
 
-       cmd->frame = kzalloc(mhba->ib_max_size, GFP_KERNEL);
+       cmd->frame = pci_alloc_consistent(mhba->pdev,
+                               mhba->ib_max_size, &cmd->frame_phys);
        if (!cmd->frame) {
                dev_err(&mhba->pdev->dev, "failed to allocate memory for FW"
                        " frame,size = %d.\n", mhba->ib_max_size);
@@ -297,7 +301,8 @@ static struct mvumi_cmd *mvumi_create_internal_cmd(struct mvumi_hba *mhba,
                if (mvumi_internal_cmd_sgl(mhba, cmd, buf_size)) {
                        dev_err(&mhba->pdev->dev, "failed to allocate memory"
                                                " for internal frame\n");
-                       kfree(cmd->frame);
+                       pci_free_consistent(mhba->pdev, mhba->ib_max_size,
+                                       cmd->frame, cmd->frame_phys);
                        kfree(cmd);
                        return NULL;
                }
@@ -317,7 +322,7 @@ static void mvumi_delete_internal_cmd(struct mvumi_hba *mhba,
        if (cmd && cmd->frame) {
                if (cmd->frame->sg_counts) {
                        m_sg = (struct mvumi_sgl *) &cmd->frame->payload[0];
-                       size = m_sg->size;
+                       sgd_getsz(mhba, m_sg, size);
 
                        phy_addr = (dma_addr_t) m_sg->baseaddr_l |
                                (dma_addr_t) ((m_sg->baseaddr_h << 16) << 16);
@@ -325,7 +330,8 @@ static void mvumi_delete_internal_cmd(struct mvumi_hba *mhba,
                        pci_free_consistent(mhba->pdev, size, cmd->data_buf,
                                                                phy_addr);
                }
-               kfree(cmd->frame);
+               pci_free_consistent(mhba->pdev, mhba->ib_max_size,
+                               cmd->frame, cmd->frame_phys);
                kfree(cmd);
        }
 }
@@ -374,7 +380,8 @@ static void mvumi_free_cmds(struct mvumi_hba *mhba)
                cmd = list_first_entry(&mhba->cmd_pool, struct mvumi_cmd,
                                                        queue_pointer);
                list_del(&cmd->queue_pointer);
-               kfree(cmd->frame);
+               if (!(mhba->hba_capability & HS_CAPABILITY_SUPPORT_DYN_SRC))
+                       kfree(cmd->frame);
                kfree(cmd);
        }
 }
@@ -396,7 +403,12 @@ static int mvumi_alloc_cmds(struct mvumi_hba *mhba)
 
                INIT_LIST_HEAD(&cmd->queue_pointer);
                list_add_tail(&cmd->queue_pointer, &mhba->cmd_pool);
-               cmd->frame = kzalloc(mhba->ib_max_size, GFP_KERNEL);
+               if (mhba->hba_capability & HS_CAPABILITY_SUPPORT_DYN_SRC) {
+                       cmd->frame = mhba->ib_frame + i * mhba->ib_max_size;
+                       cmd->frame_phys = mhba->ib_frame_phys
+                                               + i * mhba->ib_max_size;
+               } else
+                       cmd->frame = kzalloc(mhba->ib_max_size, GFP_KERNEL);
                if (!cmd->frame)
                        goto err_exit;
        }
@@ -409,48 +421,71 @@ err_exit:
                cmd = list_first_entry(&mhba->cmd_pool, struct mvumi_cmd,
                                                queue_pointer);
                list_del(&cmd->queue_pointer);
-               kfree(cmd->frame);
+               if (!(mhba->hba_capability & HS_CAPABILITY_SUPPORT_DYN_SRC))
+                       kfree(cmd->frame);
                kfree(cmd);
        }
        return -ENOMEM;
 }
 
-static int mvumi_get_ib_list_entry(struct mvumi_hba *mhba, void **ib_entry)
+static unsigned int mvumi_check_ib_list_9143(struct mvumi_hba *mhba)
 {
-       unsigned int ib_rp_reg, cur_ib_entry;
+       unsigned int ib_rp_reg;
+       struct mvumi_hw_regs *regs = mhba->regs;
+
+       ib_rp_reg = ioread32(mhba->regs->inb_read_pointer);
 
+       if (unlikely(((ib_rp_reg & regs->cl_slot_num_mask) ==
+                       (mhba->ib_cur_slot & regs->cl_slot_num_mask)) &&
+                       ((ib_rp_reg & regs->cl_pointer_toggle)
+                        != (mhba->ib_cur_slot & regs->cl_pointer_toggle)))) {
+               dev_warn(&mhba->pdev->dev, "no free slot to use.\n");
+               return 0;
+       }
        if (atomic_read(&mhba->fw_outstanding) >= mhba->max_io) {
                dev_warn(&mhba->pdev->dev, "firmware io overflow.\n");
-               return -1;
+               return 0;
+       } else {
+               return mhba->max_io - atomic_read(&mhba->fw_outstanding);
        }
-       ib_rp_reg = ioread32(mhba->mmio + CLA_INB_READ_POINTER);
+}
 
-       if (unlikely(((ib_rp_reg & CL_SLOT_NUM_MASK) ==
-                       (mhba->ib_cur_slot & CL_SLOT_NUM_MASK)) &&
-                       ((ib_rp_reg & CL_POINTER_TOGGLE) !=
-                       (mhba->ib_cur_slot & CL_POINTER_TOGGLE)))) {
-               dev_warn(&mhba->pdev->dev, "no free slot to use.\n");
-               return -1;
-       }
+static unsigned int mvumi_check_ib_list_9580(struct mvumi_hba *mhba)
+{
+       unsigned int count;
+       if (atomic_read(&mhba->fw_outstanding) >= (mhba->max_io - 1))
+               return 0;
+       count = ioread32(mhba->ib_shadow);
+       if (count == 0xffff)
+               return 0;
+       return count;
+}
+
+static void mvumi_get_ib_list_entry(struct mvumi_hba *mhba, void **ib_entry)
+{
+       unsigned int cur_ib_entry;
 
-       cur_ib_entry = mhba->ib_cur_slot & CL_SLOT_NUM_MASK;
+       cur_ib_entry = mhba->ib_cur_slot & mhba->regs->cl_slot_num_mask;
        cur_ib_entry++;
        if (cur_ib_entry >= mhba->list_num_io) {
                cur_ib_entry -= mhba->list_num_io;
-               mhba->ib_cur_slot ^= CL_POINTER_TOGGLE;
+               mhba->ib_cur_slot ^= mhba->regs->cl_pointer_toggle;
+       }
+       mhba->ib_cur_slot &= ~mhba->regs->cl_slot_num_mask;
+       mhba->ib_cur_slot |= (cur_ib_entry & mhba->regs->cl_slot_num_mask);
+       if (mhba->hba_capability & HS_CAPABILITY_SUPPORT_DYN_SRC) {
+               *ib_entry = mhba->ib_list + cur_ib_entry *
+                               sizeof(struct mvumi_dyn_list_entry);
+       } else {
+               *ib_entry = mhba->ib_list + cur_ib_entry * mhba->ib_max_size;
        }
-       mhba->ib_cur_slot &= ~CL_SLOT_NUM_MASK;
-       mhba->ib_cur_slot |= (cur_ib_entry & CL_SLOT_NUM_MASK);
-       *ib_entry = mhba->ib_list + cur_ib_entry * mhba->ib_max_size;
        atomic_inc(&mhba->fw_outstanding);
-
-       return 0;
 }
 
 static void mvumi_send_ib_list_entry(struct mvumi_hba *mhba)
 {
-       iowrite32(0xfff, mhba->ib_shadow);
-       iowrite32(mhba->ib_cur_slot, mhba->mmio + CLA_INB_WRITE_POINTER);
+       iowrite32(0xffff, mhba->ib_shadow);
+       iowrite32(mhba->ib_cur_slot, mhba->regs->inb_write_pointer);
 }
 
 static char mvumi_check_ob_frame(struct mvumi_hba *mhba,
@@ -480,31 +515,59 @@ static char mvumi_check_ob_frame(struct mvumi_hba *mhba,
        return 0;
 }
 
-static void mvumi_receive_ob_list_entry(struct mvumi_hba *mhba)
+static int mvumi_check_ob_list_9143(struct mvumi_hba *mhba,
+                       unsigned int *cur_obf, unsigned int *assign_obf_end)
 {
-       unsigned int ob_write_reg, ob_write_shadow_reg;
-       unsigned int cur_obf, assign_obf_end, i;
-       struct mvumi_ob_data *ob_data;
-       struct mvumi_rsp_frame *p_outb_frame;
+       unsigned int ob_write, ob_write_shadow;
+       struct mvumi_hw_regs *regs = mhba->regs;
 
        do {
-               ob_write_reg = ioread32(mhba->mmio + CLA_OUTB_COPY_POINTER);
-               ob_write_shadow_reg = ioread32(mhba->ob_shadow);
-       } while ((ob_write_reg & CL_SLOT_NUM_MASK) != ob_write_shadow_reg);
+               ob_write = ioread32(regs->outb_copy_pointer);
+               ob_write_shadow = ioread32(mhba->ob_shadow);
+       } while ((ob_write & regs->cl_slot_num_mask) != ob_write_shadow);
 
-       cur_obf = mhba->ob_cur_slot & CL_SLOT_NUM_MASK;
-       assign_obf_end = ob_write_reg & CL_SLOT_NUM_MASK;
+       *cur_obf = mhba->ob_cur_slot & mhba->regs->cl_slot_num_mask;
+       *assign_obf_end = ob_write & mhba->regs->cl_slot_num_mask;
 
-       if ((ob_write_reg & CL_POINTER_TOGGLE) !=
-                               (mhba->ob_cur_slot & CL_POINTER_TOGGLE)) {
-               assign_obf_end += mhba->list_num_io;
+       if ((ob_write & regs->cl_pointer_toggle) !=
+                       (mhba->ob_cur_slot & regs->cl_pointer_toggle)) {
+               *assign_obf_end += mhba->list_num_io;
        }
+       return 0;
+}
+
+static int mvumi_check_ob_list_9580(struct mvumi_hba *mhba,
+                       unsigned int *cur_obf, unsigned int *assign_obf_end)
+{
+       unsigned int ob_write;
+       struct mvumi_hw_regs *regs = mhba->regs;
+
+       ob_write = ioread32(regs->outb_read_pointer);
+       ob_write = ioread32(regs->outb_copy_pointer);
+       *cur_obf = mhba->ob_cur_slot & mhba->regs->cl_slot_num_mask;
+       *assign_obf_end = ob_write & mhba->regs->cl_slot_num_mask;
+       if (*assign_obf_end < *cur_obf)
+               *assign_obf_end += mhba->list_num_io;
+       else if (*assign_obf_end == *cur_obf)
+               return -1;
+       return 0;
+}
+
+static void mvumi_receive_ob_list_entry(struct mvumi_hba *mhba)
+{
+       unsigned int cur_obf, assign_obf_end, i;
+       struct mvumi_ob_data *ob_data;
+       struct mvumi_rsp_frame *p_outb_frame;
+       struct mvumi_hw_regs *regs = mhba->regs;
+
+       if (mhba->instancet->check_ob_list(mhba, &cur_obf, &assign_obf_end))
+               return;
 
        for (i = (assign_obf_end - cur_obf); i != 0; i--) {
                cur_obf++;
                if (cur_obf >= mhba->list_num_io) {
                        cur_obf -= mhba->list_num_io;
-                       mhba->ob_cur_slot ^= CL_POINTER_TOGGLE;
+                       mhba->ob_cur_slot ^= regs->cl_pointer_toggle;
                }
 
                p_outb_frame = mhba->ob_list + cur_obf * mhba->ob_max_size;
@@ -528,7 +591,7 @@ static void mvumi_receive_ob_list_entry(struct mvumi_hba *mhba)
                        ob_data = NULL;
                        if (cur_obf == 0) {
                                cur_obf = mhba->list_num_io - 1;
-                               mhba->ob_cur_slot ^= CL_POINTER_TOGGLE;
+                               mhba->ob_cur_slot ^= regs->cl_pointer_toggle;
                        } else
                                cur_obf -= 1;
                        break;
@@ -539,18 +602,20 @@ static void mvumi_receive_ob_list_entry(struct mvumi_hba *mhba)
 
                list_add_tail(&ob_data->list, &mhba->free_ob_list);
        }
-       mhba->ob_cur_slot &= ~CL_SLOT_NUM_MASK;
-       mhba->ob_cur_slot |= (cur_obf & CL_SLOT_NUM_MASK);
-       iowrite32(mhba->ob_cur_slot, mhba->mmio + CLA_OUTB_READ_POINTER);
+       mhba->ob_cur_slot &= ~regs->cl_slot_num_mask;
+       mhba->ob_cur_slot |= (cur_obf & regs->cl_slot_num_mask);
+       iowrite32(mhba->ob_cur_slot, regs->outb_read_pointer);
 }
 
-static void mvumi_reset(void *regs)
+static void mvumi_reset(struct mvumi_hba *mhba)
 {
-       iowrite32(0, regs + CPU_ENPOINTA_MASK_REG);
-       if (ioread32(regs + CPU_ARM_TO_PCIEA_MSG1) != HANDSHAKE_DONESTATE)
+       struct mvumi_hw_regs *regs = mhba->regs;
+
+       iowrite32(0, regs->enpointa_mask_reg);
+       if (ioread32(regs->arm_to_pciea_msg1) != HANDSHAKE_DONESTATE)
                return;
 
-       iowrite32(DRBL_SOFT_RESET, regs + CPU_PCIEA_TO_ARM_DRBL_REG);
+       iowrite32(DRBL_SOFT_RESET, regs->pciea_to_arm_drbl_reg);
 }
 
 static unsigned char mvumi_start(struct mvumi_hba *mhba);
@@ -558,7 +623,7 @@ static unsigned char mvumi_start(struct mvumi_hba *mhba);
 static int mvumi_wait_for_outstanding(struct mvumi_hba *mhba)
 {
        mhba->fw_state = FW_STATE_ABORT;
-       mvumi_reset(mhba->mmio);
+       mvumi_reset(mhba);
 
        if (mvumi_start(mhba))
                return FAILED;
@@ -566,6 +631,98 @@ static int mvumi_wait_for_outstanding(struct mvumi_hba *mhba)
                return SUCCESS;
 }
 
+static int mvumi_wait_for_fw(struct mvumi_hba *mhba)
+{
+       struct mvumi_hw_regs *regs = mhba->regs;
+       u32 tmp;
+       unsigned long before;
+       before = jiffies;
+
+       iowrite32(0, regs->enpointa_mask_reg);
+       tmp = ioread32(regs->arm_to_pciea_msg1);
+       while (tmp != HANDSHAKE_READYSTATE) {
+               iowrite32(DRBL_MU_RESET, regs->pciea_to_arm_drbl_reg);
+               if (time_after(jiffies, before + FW_MAX_DELAY * HZ)) {
+                       dev_err(&mhba->pdev->dev,
+                               "FW reset failed [0x%x].\n", tmp);
+                       return FAILED;
+               }
+
+               msleep(500);
+               rmb();
+               tmp = ioread32(regs->arm_to_pciea_msg1);
+       }
+
+       return SUCCESS;
+}
+
+static void mvumi_backup_bar_addr(struct mvumi_hba *mhba)
+{
+       unsigned char i;
+
+       for (i = 0; i < MAX_BASE_ADDRESS; i++) {
+               pci_read_config_dword(mhba->pdev, 0x10 + i * 4,
+                                               &mhba->pci_base[i]);
+       }
+}
+
+static void mvumi_restore_bar_addr(struct mvumi_hba *mhba)
+{
+       unsigned char i;
+
+       for (i = 0; i < MAX_BASE_ADDRESS; i++) {
+               if (mhba->pci_base[i])
+                       pci_write_config_dword(mhba->pdev, 0x10 + i * 4,
+                                               mhba->pci_base[i]);
+       }
+}
+
+static unsigned int mvumi_pci_set_master(struct pci_dev *pdev)
+{
+       unsigned int ret = 0;
+       pci_set_master(pdev);
+
+       if (IS_DMA64) {
+               if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))
+                       ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+       } else
+               ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+
+       return ret;
+}
+
+static int mvumi_reset_host_9580(struct mvumi_hba *mhba)
+{
+       mhba->fw_state = FW_STATE_ABORT;
+
+       iowrite32(0, mhba->regs->reset_enable);
+       iowrite32(0xf, mhba->regs->reset_request);
+
+       iowrite32(0x10, mhba->regs->reset_enable);
+       iowrite32(0x10, mhba->regs->reset_request);
+       msleep(100);
+       pci_disable_device(mhba->pdev);
+
+       if (pci_enable_device(mhba->pdev)) {
+               dev_err(&mhba->pdev->dev, "enable device failed\n");
+               return FAILED;
+       }
+       if (mvumi_pci_set_master(mhba->pdev)) {
+               dev_err(&mhba->pdev->dev, "set master failed\n");
+               return FAILED;
+       }
+       mvumi_restore_bar_addr(mhba);
+       if (mvumi_wait_for_fw(mhba) == FAILED)
+               return FAILED;
+
+       return mvumi_wait_for_outstanding(mhba);
+}
+
+static int mvumi_reset_host_9143(struct mvumi_hba *mhba)
+{
+       return mvumi_wait_for_outstanding(mhba);
+}
+
 static int mvumi_host_reset(struct scsi_cmnd *scmd)
 {
        struct mvumi_hba *mhba;
@@ -575,7 +732,7 @@ static int mvumi_host_reset(struct scsi_cmnd *scmd)
        scmd_printk(KERN_NOTICE, scmd, "RESET -%ld cmd=%x retries=%x\n",
                        scmd->serial_number, scmd->cmnd[0], scmd->retries);
 
-       return mvumi_wait_for_outstanding(mhba);
+       return mhba->instancet->reset_host(mhba);
 }
 
 static int mvumi_issue_blocked_cmd(struct mvumi_hba *mhba,
@@ -628,7 +785,9 @@ static void mvumi_release_fw(struct mvumi_hba *mhba)
        mvumi_free_cmds(mhba);
        mvumi_release_mem_resource(mhba);
        mvumi_unmap_pci_addr(mhba->pdev, mhba->base_addr);
-       kfree(mhba->handshake_page);
+       pci_free_consistent(mhba->pdev, HSP_MAX_SIZE,
+               mhba->handshake_page, mhba->handshake_page_phys);
+       kfree(mhba->regs);
        pci_release_regions(mhba->pdev);
 }
 
@@ -665,6 +824,7 @@ get_cmd:    cmd = mvumi_create_internal_cmd(mhba, 0);
                frame->cdb_length = MAX_COMMAND_SIZE;
                memset(frame->cdb, 0, MAX_COMMAND_SIZE);
                frame->cdb[0] = SCSI_CMD_MARVELL_SPECIFIC;
+               frame->cdb[1] = CDB_CORE_MODULE;
                frame->cdb[2] = CDB_CORE_SHUTDOWN;
 
                mvumi_issue_blocked_cmd(mhba, cmd);
@@ -695,7 +855,7 @@ mvumi_calculate_checksum(struct mvumi_hs_header *p_header,
        return ret;
 }
 
-void mvumi_hs_build_page(struct mvumi_hba *mhba,
+static void mvumi_hs_build_page(struct mvumi_hba *mhba,
                                struct mvumi_hs_header *hs_header)
 {
        struct mvumi_hs_page2 *hs_page2;
@@ -710,6 +870,8 @@ void mvumi_hs_build_page(struct mvumi_hba *mhba,
                hs_header->frame_length = sizeof(*hs_page2) - 4;
                memset(hs_header->frame_content, 0, hs_header->frame_length);
                hs_page2->host_type = 3; /* 3 mean linux*/
+               if (mhba->hba_capability & HS_CAPABILITY_SUPPORT_DYN_SRC)
+                       hs_page2->host_cap = 0x08;/* host dynamic source mode */
                hs_page2->host_ver.ver_major = VER_MAJOR;
                hs_page2->host_ver.ver_minor = VER_MINOR;
                hs_page2->host_ver.ver_oem = VER_OEM;
@@ -745,8 +907,18 @@ void mvumi_hs_build_page(struct mvumi_hba *mhba,
                hs_page4->ob_baseaddr_h = upper_32_bits(mhba->ob_list_phys);
                hs_page4->ib_entry_size = mhba->ib_max_size_setting;
                hs_page4->ob_entry_size = mhba->ob_max_size_setting;
-               hs_page4->ob_depth = mhba->list_num_io;
-               hs_page4->ib_depth = mhba->list_num_io;
+               if (mhba->hba_capability
+                       & HS_CAPABILITY_NEW_PAGE_IO_DEPTH_DEF) {
+                       hs_page4->ob_depth = find_first_bit((unsigned long *)
+                                                           &mhba->list_num_io,
+                                                           BITS_PER_LONG);
+                       hs_page4->ib_depth = find_first_bit((unsigned long *)
+                                                           &mhba->list_num_io,
+                                                           BITS_PER_LONG);
+               } else {
+                       hs_page4->ob_depth = (u8) mhba->list_num_io;
+                       hs_page4->ib_depth = (u8) mhba->list_num_io;
+               }
                hs_header->checksum = mvumi_calculate_checksum(hs_header,
                                                hs_header->frame_length);
                break;
@@ -774,8 +946,11 @@ static int mvumi_init_data(struct mvumi_hba *mhba)
                return 0;
 
        tmp_size = mhba->ib_max_size * mhba->max_io;
+       if (mhba->hba_capability & HS_CAPABILITY_SUPPORT_DYN_SRC)
+               tmp_size += sizeof(struct mvumi_dyn_list_entry) * mhba->max_io;
+
        tmp_size += 128 + mhba->ob_max_size * mhba->max_io;
-       tmp_size += 8 + sizeof(u32) + 16;
+       tmp_size += 8 + sizeof(u32)*2 + 16;
 
        res_mgnt = mvumi_alloc_mem_resource(mhba,
                                        RESOURCE_UNCACHED_MEMORY, tmp_size);
@@ -793,24 +968,41 @@ static int mvumi_init_data(struct mvumi_hba *mhba)
        v += offset;
        mhba->ib_list = v;
        mhba->ib_list_phys = p;
+       if (mhba->hba_capability & HS_CAPABILITY_SUPPORT_DYN_SRC) {
+               v += sizeof(struct mvumi_dyn_list_entry) * mhba->max_io;
+               p += sizeof(struct mvumi_dyn_list_entry) * mhba->max_io;
+               mhba->ib_frame = v;
+               mhba->ib_frame_phys = p;
+       }
        v += mhba->ib_max_size * mhba->max_io;
        p += mhba->ib_max_size * mhba->max_io;
+
        /* ib shadow */
        offset = round_up(p, 8) - p;
        p += offset;
        v += offset;
        mhba->ib_shadow = v;
        mhba->ib_shadow_phys = p;
-       p += sizeof(u32);
-       v += sizeof(u32);
+       p += sizeof(u32)*2;
+       v += sizeof(u32)*2;
        /* ob shadow */
-       offset = round_up(p, 8) - p;
-       p += offset;
-       v += offset;
-       mhba->ob_shadow = v;
-       mhba->ob_shadow_phys = p;
-       p += 8;
-       v += 8;
+       if (mhba->pdev->device == PCI_DEVICE_ID_MARVELL_MV9580) {
+               offset = round_up(p, 8) - p;
+               p += offset;
+               v += offset;
+               mhba->ob_shadow = v;
+               mhba->ob_shadow_phys = p;
+               p += 8;
+               v += 8;
+       } else {
+               offset = round_up(p, 4) - p;
+               p += offset;
+               v += offset;
+               mhba->ob_shadow = v;
+               mhba->ob_shadow_phys = p;
+               p += 4;
+               v += 4;
+       }
 
        /* ob list */
        offset = round_up(p, 128) - p;
@@ -902,6 +1094,12 @@ static int mvumi_hs_process_page(struct mvumi_hba *mhba,
                dev_dbg(&mhba->pdev->dev, "FW version:%d\n",
                                                hs_page1->fw_ver.ver_build);
 
+               if (mhba->hba_capability & HS_CAPABILITY_SUPPORT_COMPACT_SG)
+                       mhba->eot_flag = 22;
+               else
+                       mhba->eot_flag = 27;
+               if (mhba->hba_capability & HS_CAPABILITY_NEW_PAGE_IO_DEPTH_DEF)
+                       mhba->list_num_io = 1 << hs_page1->cl_inout_list_depth;
                break;
        default:
                dev_err(&mhba->pdev->dev, "handshake: page code error\n");
@@ -923,12 +1121,12 @@ static int mvumi_handshake(struct mvumi_hba *mhba)
 {
        unsigned int hs_state, tmp, hs_fun;
        struct mvumi_hs_header *hs_header;
-       void *regs = mhba->mmio;
+       struct mvumi_hw_regs *regs = mhba->regs;
 
        if (mhba->fw_state == FW_STATE_STARTING)
                hs_state = HS_S_START;
        else {
-               tmp = ioread32(regs + CPU_ARM_TO_PCIEA_MSG0);
+               tmp = ioread32(regs->arm_to_pciea_msg0);
                hs_state = HS_GET_STATE(tmp);
                dev_dbg(&mhba->pdev->dev, "handshake state[0x%x].\n", hs_state);
                if (HS_GET_STATUS(tmp) != HS_STATUS_OK) {
@@ -943,21 +1141,20 @@ static int mvumi_handshake(struct mvumi_hba *mhba)
                mhba->fw_state = FW_STATE_HANDSHAKING;
                HS_SET_STATUS(hs_fun, HS_STATUS_OK);
                HS_SET_STATE(hs_fun, HS_S_RESET);
-               iowrite32(HANDSHAKE_SIGNATURE, regs + CPU_PCIEA_TO_ARM_MSG1);
-               iowrite32(hs_fun, regs + CPU_PCIEA_TO_ARM_MSG0);
-               iowrite32(DRBL_HANDSHAKE, regs + CPU_PCIEA_TO_ARM_DRBL_REG);
+               iowrite32(HANDSHAKE_SIGNATURE, regs->pciea_to_arm_msg1);
+               iowrite32(hs_fun, regs->pciea_to_arm_msg0);
+               iowrite32(DRBL_HANDSHAKE, regs->pciea_to_arm_drbl_reg);
                break;
 
        case HS_S_RESET:
                iowrite32(lower_32_bits(mhba->handshake_page_phys),
-                                       regs + CPU_PCIEA_TO_ARM_MSG1);
+                                       regs->pciea_to_arm_msg1);
                iowrite32(upper_32_bits(mhba->handshake_page_phys),
-                                       regs + CPU_ARM_TO_PCIEA_MSG1);
+                                       regs->arm_to_pciea_msg1);
                HS_SET_STATUS(hs_fun, HS_STATUS_OK);
                HS_SET_STATE(hs_fun, HS_S_PAGE_ADDR);
-               iowrite32(hs_fun, regs + CPU_PCIEA_TO_ARM_MSG0);
-               iowrite32(DRBL_HANDSHAKE, regs + CPU_PCIEA_TO_ARM_DRBL_REG);
-
+               iowrite32(hs_fun, regs->pciea_to_arm_msg0);
+               iowrite32(DRBL_HANDSHAKE, regs->pciea_to_arm_drbl_reg);
                break;
 
        case HS_S_PAGE_ADDR:
@@ -997,30 +1194,37 @@ static int mvumi_handshake(struct mvumi_hba *mhba)
                        HS_SET_STATE(hs_fun, HS_S_END);
 
                HS_SET_STATUS(hs_fun, HS_STATUS_OK);
-               iowrite32(hs_fun, regs + CPU_PCIEA_TO_ARM_MSG0);
-               iowrite32(DRBL_HANDSHAKE, regs + CPU_PCIEA_TO_ARM_DRBL_REG);
+               iowrite32(hs_fun, regs->pciea_to_arm_msg0);
+               iowrite32(DRBL_HANDSHAKE, regs->pciea_to_arm_drbl_reg);
                break;
 
        case HS_S_END:
                /* Set communication list ISR */
-               tmp = ioread32(regs + CPU_ENPOINTA_MASK_REG);
-               tmp |= INT_MAP_COMAOUT | INT_MAP_COMAERR;
-               iowrite32(tmp, regs + CPU_ENPOINTA_MASK_REG);
+               tmp = ioread32(regs->enpointa_mask_reg);
+               tmp |= regs->int_comaout | regs->int_comaerr;
+               iowrite32(tmp, regs->enpointa_mask_reg);
                iowrite32(mhba->list_num_io, mhba->ib_shadow);
                /* Set InBound List Available count shadow */
                iowrite32(lower_32_bits(mhba->ib_shadow_phys),
-                                       regs + CLA_INB_AVAL_COUNT_BASEL);
+                                       regs->inb_aval_count_basel);
                iowrite32(upper_32_bits(mhba->ib_shadow_phys),
-                                       regs + CLA_INB_AVAL_COUNT_BASEH);
-
-               /* Set OutBound List Available count shadow */
-               iowrite32((mhba->list_num_io-1) | CL_POINTER_TOGGLE,
-                                               mhba->ob_shadow);
-               iowrite32(lower_32_bits(mhba->ob_shadow_phys), regs + 0x5B0);
-               iowrite32(upper_32_bits(mhba->ob_shadow_phys), regs + 0x5B4);
+                                       regs->inb_aval_count_baseh);
+
+               if (mhba->pdev->device == PCI_DEVICE_ID_MARVELL_MV9143) {
+                       /* Set OutBound List Available count shadow */
+                       iowrite32((mhba->list_num_io-1) |
+                                                       regs->cl_pointer_toggle,
+                                                       mhba->ob_shadow);
+                       iowrite32(lower_32_bits(mhba->ob_shadow_phys),
+                                                       regs->outb_copy_basel);
+                       iowrite32(upper_32_bits(mhba->ob_shadow_phys),
+                                                       regs->outb_copy_baseh);
+               }
 
-               mhba->ib_cur_slot = (mhba->list_num_io - 1) | CL_POINTER_TOGGLE;
-               mhba->ob_cur_slot = (mhba->list_num_io - 1) | CL_POINTER_TOGGLE;
+               mhba->ib_cur_slot = (mhba->list_num_io - 1) |
+                                                       regs->cl_pointer_toggle;
+               mhba->ob_cur_slot = (mhba->list_num_io - 1) |
+                                                       regs->cl_pointer_toggle;
                mhba->fw_state = FW_STATE_STARTED;
 
                break;
@@ -1040,7 +1244,7 @@ static unsigned char mvumi_handshake_event(struct mvumi_hba *mhba)
        before = jiffies;
        mvumi_handshake(mhba);
        do {
-               isr_status = mhba->instancet->read_fw_status_reg(mhba->mmio);
+               isr_status = mhba->instancet->read_fw_status_reg(mhba);
 
                if (mhba->fw_state == FW_STATE_STARTED)
                        return 0;
@@ -1062,16 +1266,15 @@ static unsigned char mvumi_handshake_event(struct mvumi_hba *mhba)
 
 static unsigned char mvumi_check_handshake(struct mvumi_hba *mhba)
 {
-       void *regs = mhba->mmio;
        unsigned int tmp;
        unsigned long before;
 
        before = jiffies;
-       tmp = ioread32(regs + CPU_ARM_TO_PCIEA_MSG1);
+       tmp = ioread32(mhba->regs->arm_to_pciea_msg1);
        while ((tmp != HANDSHAKE_READYSTATE) && (tmp != HANDSHAKE_DONESTATE)) {
                if (tmp != HANDSHAKE_READYSTATE)
                        iowrite32(DRBL_MU_RESET,
-                                       regs + CPU_PCIEA_TO_ARM_DRBL_REG);
+                                       mhba->regs->pciea_to_arm_drbl_reg);
                if (time_after(jiffies, before + FW_MAX_DELAY * HZ)) {
                        dev_err(&mhba->pdev->dev,
                                "invalid signature [0x%x].\n", tmp);
@@ -1079,7 +1282,7 @@ static unsigned char mvumi_check_handshake(struct mvumi_hba *mhba)
                }
                usleep_range(1000, 2000);
                rmb();
-               tmp = ioread32(regs + CPU_ARM_TO_PCIEA_MSG1);
+               tmp = ioread32(mhba->regs->arm_to_pciea_msg1);
        }
 
        mhba->fw_state = FW_STATE_STARTING;
@@ -1100,15 +1303,17 @@ static unsigned char mvumi_check_handshake(struct mvumi_hba *mhba)
 
 static unsigned char mvumi_start(struct mvumi_hba *mhba)
 {
-       void *regs = mhba->mmio;
        unsigned int tmp;
+       struct mvumi_hw_regs *regs = mhba->regs;
+
        /* clear Door bell */
-       tmp = ioread32(regs + CPU_ARM_TO_PCIEA_DRBL_REG);
-       iowrite32(tmp, regs + CPU_ARM_TO_PCIEA_DRBL_REG);
+       tmp = ioread32(regs->arm_to_pciea_drbl_reg);
+       iowrite32(tmp, regs->arm_to_pciea_drbl_reg);
 
-       iowrite32(0x3FFFFFFF, regs + CPU_ARM_TO_PCIEA_MASK_REG);
-       tmp = ioread32(regs + CPU_ENPOINTA_MASK_REG) | INT_MAP_DL_CPU2PCIEA;
-       iowrite32(tmp, regs + CPU_ENPOINTA_MASK_REG);
+       iowrite32(regs->int_drbl_int_mask, regs->arm_to_pciea_mask_reg);
+       tmp = ioread32(regs->enpointa_mask_reg) | regs->int_dl_cpu2pciea;
+       iowrite32(tmp, regs->enpointa_mask_reg);
+       msleep(100);
        if (mvumi_check_handshake(mhba))
                return -1;
 
@@ -1166,6 +1371,7 @@ static void mvumi_complete_cmd(struct mvumi_hba *mhba, struct mvumi_cmd *cmd,
        cmd->scmd->scsi_done(scmd);
        mvumi_return_cmd(mhba, cmd);
 }
+
 static void mvumi_complete_internal_cmd(struct mvumi_hba *mhba,
                                                struct mvumi_cmd *cmd,
                                        struct mvumi_rsp_frame *ob_frame)
@@ -1210,6 +1416,304 @@ static void mvumi_show_event(struct mvumi_hba *mhba,
        }
 }
 
+static int mvumi_handle_hotplug(struct mvumi_hba *mhba, u16 devid, int status)
+{
+       struct scsi_device *sdev;
+       int ret = -1;
+
+       if (status == DEVICE_OFFLINE) {
+               sdev = scsi_device_lookup(mhba->shost, 0, devid, 0);
+               if (sdev) {
+                       dev_dbg(&mhba->pdev->dev, "remove disk %d-%d-%d.\n", 0,
+                                                               sdev->id, 0);
+                       scsi_remove_device(sdev);
+                       scsi_device_put(sdev);
+                       ret = 0;
+               } else
+                       dev_err(&mhba->pdev->dev, " no disk[%d] to remove\n",
+                                                                       devid);
+       } else if (status == DEVICE_ONLINE) {
+               sdev = scsi_device_lookup(mhba->shost, 0, devid, 0);
+               if (!sdev) {
+                       scsi_add_device(mhba->shost, 0, devid, 0);
+                       dev_dbg(&mhba->pdev->dev, " add disk %d-%d-%d.\n", 0,
+                                                               devid, 0);
+                       ret = 0;
+               } else {
+                       dev_err(&mhba->pdev->dev, " don't add disk %d-%d-%d.\n",
+                                                               0, devid, 0);
+                       scsi_device_put(sdev);
+               }
+       }
+       return ret;
+}
+
+static u64 mvumi_inquiry(struct mvumi_hba *mhba,
+       unsigned int id, struct mvumi_cmd *cmd)
+{
+       struct mvumi_msg_frame *frame;
+       u64 wwid = 0;
+       int cmd_alloc = 0;
+       int data_buf_len = 64;
+
+       if (!cmd) {
+               cmd = mvumi_create_internal_cmd(mhba, data_buf_len);
+               if (cmd)
+                       cmd_alloc = 1;
+               else
+                       return 0;
+       } else {
+               memset(cmd->data_buf, 0, data_buf_len);
+       }
+       cmd->scmd = NULL;
+       cmd->cmd_status = REQ_STATUS_PENDING;
+       atomic_set(&cmd->sync_cmd, 0);
+       frame = cmd->frame;
+       frame->device_id = (u16) id;
+       frame->cmd_flag = CMD_FLAG_DATA_IN;
+       frame->req_function = CL_FUN_SCSI_CMD;
+       frame->cdb_length = 6;
+       frame->data_transfer_length = MVUMI_INQUIRY_LENGTH;
+       memset(frame->cdb, 0, frame->cdb_length);
+       frame->cdb[0] = INQUIRY;
+       frame->cdb[4] = frame->data_transfer_length;
+
+       mvumi_issue_blocked_cmd(mhba, cmd);
+
+       if (cmd->cmd_status == SAM_STAT_GOOD) {
+               if (mhba->pdev->device == PCI_DEVICE_ID_MARVELL_MV9143)
+                       wwid = id + 1;
+               else
+                       memcpy((void *)&wwid,
+                              (cmd->data_buf + MVUMI_INQUIRY_UUID_OFF),
+                              MVUMI_INQUIRY_UUID_LEN);
+               dev_dbg(&mhba->pdev->dev,
+                       "inquiry device(0:%d:0) wwid(%llx)\n", id, wwid);
+       } else {
+               wwid = 0;
+       }
+       if (cmd_alloc)
+               mvumi_delete_internal_cmd(mhba, cmd);
+
+       return wwid;
+}
+
+static void mvumi_detach_devices(struct mvumi_hba *mhba)
+{
+       struct mvumi_device *mv_dev = NULL , *dev_next;
+       struct scsi_device *sdev = NULL;
+
+       mutex_lock(&mhba->device_lock);
+
+       /* detach Hard Disk */
+       list_for_each_entry_safe(mv_dev, dev_next,
+               &mhba->shost_dev_list, list) {
+               mvumi_handle_hotplug(mhba, mv_dev->id, DEVICE_OFFLINE);
+               list_del_init(&mv_dev->list);
+               dev_dbg(&mhba->pdev->dev, "release device(0:%d:0) wwid(%llx)\n",
+                       mv_dev->id, mv_dev->wwid);
+               kfree(mv_dev);
+       }
+       list_for_each_entry_safe(mv_dev, dev_next, &mhba->mhba_dev_list, list) {
+               list_del_init(&mv_dev->list);
+               dev_dbg(&mhba->pdev->dev, "release device(0:%d:0) wwid(%llx)\n",
+                       mv_dev->id, mv_dev->wwid);
+               kfree(mv_dev);
+       }
+
+       /* detach virtual device */
+       if (mhba->pdev->device == PCI_DEVICE_ID_MARVELL_MV9580)
+               sdev = scsi_device_lookup(mhba->shost, 0,
+                                               mhba->max_target_id - 1, 0);
+
+       if (sdev) {
+               scsi_remove_device(sdev);
+               scsi_device_put(sdev);
+       }
+
+       mutex_unlock(&mhba->device_lock);
+}
+
+static void mvumi_rescan_devices(struct mvumi_hba *mhba, int id)
+{
+       struct scsi_device *sdev;
+
+       sdev = scsi_device_lookup(mhba->shost, 0, id, 0);
+       if (sdev) {
+               scsi_rescan_device(&sdev->sdev_gendev);
+               scsi_device_put(sdev);
+       }
+}
+
+static int mvumi_match_devices(struct mvumi_hba *mhba, int id, u64 wwid)
+{
+       struct mvumi_device *mv_dev = NULL;
+
+       list_for_each_entry(mv_dev, &mhba->shost_dev_list, list) {
+               if (mv_dev->wwid == wwid) {
+                       if (mv_dev->id != id) {
+                               dev_err(&mhba->pdev->dev,
+                                       "%s has same wwid[%llx] ,"
+                                       " but different id[%d %d]\n",
+                                       __func__, mv_dev->wwid, mv_dev->id, id);
+                               return -1;
+                       } else {
+                               if (mhba->pdev->device ==
+                                               PCI_DEVICE_ID_MARVELL_MV9143)
+                                       mvumi_rescan_devices(mhba, id);
+                               return 1;
+                       }
+               }
+       }
+       return 0;
+}
+
+static void mvumi_remove_devices(struct mvumi_hba *mhba, int id)
+{
+       struct mvumi_device *mv_dev = NULL, *dev_next;
+
+       list_for_each_entry_safe(mv_dev, dev_next,
+                               &mhba->shost_dev_list, list) {
+               if (mv_dev->id == id) {
+                       dev_dbg(&mhba->pdev->dev,
+                               "detach device(0:%d:0) wwid(%llx) from HOST\n",
+                               mv_dev->id, mv_dev->wwid);
+                       mvumi_handle_hotplug(mhba, mv_dev->id, DEVICE_OFFLINE);
+                       list_del_init(&mv_dev->list);
+                       kfree(mv_dev);
+               }
+       }
+}
+
+static int mvumi_probe_devices(struct mvumi_hba *mhba)
+{
+       int id, maxid;
+       u64 wwid = 0;
+       struct mvumi_device *mv_dev = NULL;
+       struct mvumi_cmd *cmd = NULL;
+       int found = 0;
+
+       cmd = mvumi_create_internal_cmd(mhba, 64);
+       if (!cmd)
+               return -1;
+
+       if (mhba->pdev->device == PCI_DEVICE_ID_MARVELL_MV9143)
+               maxid = mhba->max_target_id;
+       else
+               maxid = mhba->max_target_id - 1;
+
+       for (id = 0; id < maxid; id++) {
+               wwid = mvumi_inquiry(mhba, id, cmd);
+               if (!wwid) {
+                       /* device no response, remove it */
+                       mvumi_remove_devices(mhba, id);
+               } else {
+                       /* device response, add it */
+                       found = mvumi_match_devices(mhba, id, wwid);
+                       if (!found) {
+                               mvumi_remove_devices(mhba, id);
+                               mv_dev = kzalloc(sizeof(struct mvumi_device),
+                                                               GFP_KERNEL);
+                               if (!mv_dev) {
+                                       dev_err(&mhba->pdev->dev,
+                                               "%s alloc mv_dev failed\n",
+                                               __func__);
+                                       continue;
+                               }
+                               mv_dev->id = id;
+                               mv_dev->wwid = wwid;
+                               mv_dev->sdev = NULL;
+                               INIT_LIST_HEAD(&mv_dev->list);
+                               list_add_tail(&mv_dev->list,
+                                             &mhba->mhba_dev_list);
+                               dev_dbg(&mhba->pdev->dev,
+                                       "probe a new device(0:%d:0)"
+                                       " wwid(%llx)\n", id, mv_dev->wwid);
+                       } else if (found == -1)
+                               return -1;
+                       else
+                               continue;
+               }
+       }
+
+       if (cmd)
+               mvumi_delete_internal_cmd(mhba, cmd);
+
+       return 0;
+}
+
+static int mvumi_rescan_bus(void *data)
+{
+       int ret = 0;
+       struct mvumi_hba *mhba = (struct mvumi_hba *) data;
+       struct mvumi_device *mv_dev = NULL , *dev_next;
+
+       while (!kthread_should_stop()) {
+
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (!atomic_read(&mhba->pnp_count))
+                       schedule();
+               msleep(1000);
+               atomic_set(&mhba->pnp_count, 0);
+               __set_current_state(TASK_RUNNING);
+
+               mutex_lock(&mhba->device_lock);
+               ret = mvumi_probe_devices(mhba);
+               if (!ret) {
+                       list_for_each_entry_safe(mv_dev, dev_next,
+                                                &mhba->mhba_dev_list, list) {
+                               if (mvumi_handle_hotplug(mhba, mv_dev->id,
+                                                        DEVICE_ONLINE)) {
+                                       dev_err(&mhba->pdev->dev,
+                                               "%s add device(0:%d:0) failed"
+                                               "wwid(%llx) has exist\n",
+                                               __func__,
+                                               mv_dev->id, mv_dev->wwid);
+                                       list_del_init(&mv_dev->list);
+                                       kfree(mv_dev);
+                               } else {
+                                       list_move_tail(&mv_dev->list,
+                                                      &mhba->shost_dev_list);
+                               }
+                       }
+               }
+               mutex_unlock(&mhba->device_lock);
+       }
+       return 0;
+}
+
+static void mvumi_proc_msg(struct mvumi_hba *mhba,
+                                       struct mvumi_hotplug_event *param)
+{
+       u16 size = param->size;
+       const unsigned long *ar_bitmap;
+       const unsigned long *re_bitmap;
+       int index;
+
+       if (mhba->fw_flag & MVUMI_FW_ATTACH) {
+               index = -1;
+               ar_bitmap = (const unsigned long *) param->bitmap;
+               re_bitmap = (const unsigned long *) &param->bitmap[size >> 3];
+
+               mutex_lock(&mhba->sas_discovery_mutex);
+               do {
+                       index = find_next_zero_bit(ar_bitmap, size, index + 1);
+                       if (index >= size)
+                               break;
+                       mvumi_handle_hotplug(mhba, index, DEVICE_ONLINE);
+               } while (1);
+
+               index = -1;
+               do {
+                       index = find_next_zero_bit(re_bitmap, size, index + 1);
+                       if (index >= size)
+                               break;
+                       mvumi_handle_hotplug(mhba, index, DEVICE_OFFLINE);
+               } while (1);
+               mutex_unlock(&mhba->sas_discovery_mutex);
+       }
+}
+
 static void mvumi_notification(struct mvumi_hba *mhba, u8 msg, void *buffer)
 {
        if (msg == APICDB1_EVENT_GETEVENT) {
@@ -1227,6 +1731,8 @@ static void mvumi_notification(struct mvumi_hba *mhba, u8 msg, void *buffer)
                        param = &er->events[i];
                        mvumi_show_event(mhba, param);
                }
+       } else if (msg == APICDB1_HOST_GETEVENT) {
+               mvumi_proc_msg(mhba, buffer);
        }
 }
 
@@ -1271,17 +1777,27 @@ static void mvumi_scan_events(struct work_struct *work)
        kfree(mu_ev);
 }
 
-static void mvumi_launch_events(struct mvumi_hba *mhba, u8 msg)
+static void mvumi_launch_events(struct mvumi_hba *mhba, u32 isr_status)
 {
        struct mvumi_events_wq *mu_ev;
 
-       mu_ev = kzalloc(sizeof(*mu_ev), GFP_ATOMIC);
-       if (mu_ev) {
-               INIT_WORK(&mu_ev->work_q, mvumi_scan_events);
-               mu_ev->mhba = mhba;
-               mu_ev->event = msg;
-               mu_ev->param = NULL;
-               schedule_work(&mu_ev->work_q);
+       while (isr_status & (DRBL_BUS_CHANGE | DRBL_EVENT_NOTIFY)) {
+               if (isr_status & DRBL_BUS_CHANGE) {
+                       atomic_inc(&mhba->pnp_count);
+                       wake_up_process(mhba->dm_thread);
+                       isr_status &= ~(DRBL_BUS_CHANGE);
+                       continue;
+               }
+
+               mu_ev = kzalloc(sizeof(*mu_ev), GFP_ATOMIC);
+               if (mu_ev) {
+                       INIT_WORK(&mu_ev->work_q, mvumi_scan_events);
+                       mu_ev->mhba = mhba;
+                       mu_ev->event = APICDB1_EVENT_GETEVENT;
+                       isr_status &= ~(DRBL_EVENT_NOTIFY);
+                       mu_ev->param = NULL;
+                       schedule_work(&mu_ev->work_q);
+               }
        }
 }
 
@@ -1322,16 +1838,17 @@ static irqreturn_t mvumi_isr_handler(int irq, void *devp)
                return IRQ_NONE;
        }
 
-       if (mhba->global_isr & INT_MAP_DL_CPU2PCIEA) {
+       if (mhba->global_isr & mhba->regs->int_dl_cpu2pciea) {
+               if (mhba->isr_status & (DRBL_BUS_CHANGE | DRBL_EVENT_NOTIFY))
+                       mvumi_launch_events(mhba, mhba->isr_status);
                if (mhba->isr_status & DRBL_HANDSHAKE_ISR) {
                        dev_warn(&mhba->pdev->dev, "enter handshake again!\n");
                        mvumi_handshake(mhba);
                }
-               if (mhba->isr_status & DRBL_EVENT_NOTIFY)
-                       mvumi_launch_events(mhba, APICDB1_EVENT_GETEVENT);
+
        }
 
-       if (mhba->global_isr & INT_MAP_COMAOUT)
+       if (mhba->global_isr & mhba->regs->int_comaout)
                mvumi_receive_ob_list_entry(mhba);
 
        mhba->global_isr = 0;
@@ -1358,8 +1875,7 @@ static enum mvumi_qc_result mvumi_send_command(struct mvumi_hba *mhba,
                dev_dbg(&mhba->pdev->dev, "no free tag.\n");
                return MV_QUEUE_COMMAND_RESULT_NO_RESOURCE;
        }
-       if (mvumi_get_ib_list_entry(mhba, &ib_entry))
-               return MV_QUEUE_COMMAND_RESULT_NO_RESOURCE;
+       mvumi_get_ib_list_entry(mhba, &ib_entry);
 
        cmd->frame->tag = tag_get_one(mhba, &mhba->tag_pool);
        cmd->frame->request_id = mhba->io_seq++;
@@ -1367,21 +1883,35 @@ static enum mvumi_qc_result mvumi_send_command(struct mvumi_hba *mhba,
        mhba->tag_cmd[cmd->frame->tag] = cmd;
        frame_len = sizeof(*ib_frame) - 4 +
                                ib_frame->sg_counts * sizeof(struct mvumi_sgl);
-       memcpy(ib_entry, ib_frame, frame_len);
+       if (mhba->hba_capability & HS_CAPABILITY_SUPPORT_DYN_SRC) {
+               struct mvumi_dyn_list_entry *dle;
+               dle = ib_entry;
+               dle->src_low_addr =
+                       cpu_to_le32(lower_32_bits(cmd->frame_phys));
+               dle->src_high_addr =
+                       cpu_to_le32(upper_32_bits(cmd->frame_phys));
+               dle->if_length = (frame_len >> 2) & 0xFFF;
+       } else {
+               memcpy(ib_entry, ib_frame, frame_len);
+       }
        return MV_QUEUE_COMMAND_RESULT_SENT;
 }
 
 static void mvumi_fire_cmd(struct mvumi_hba *mhba, struct mvumi_cmd *cmd)
 {
        unsigned short num_of_cl_sent = 0;
+       unsigned int count;
        enum mvumi_qc_result result;
 
        if (cmd)
                list_add_tail(&cmd->queue_pointer, &mhba->waiting_req_list);
+       count = mhba->instancet->check_ib_list(mhba);
+       if (list_empty(&mhba->waiting_req_list) || !count)
+               return;
 
-       while (!list_empty(&mhba->waiting_req_list)) {
+       do {
                cmd = list_first_entry(&mhba->waiting_req_list,
-                                        struct mvumi_cmd, queue_pointer);
+                                      struct mvumi_cmd, queue_pointer);
                list_del_init(&cmd->queue_pointer);
                result = mvumi_send_command(mhba, cmd);
                switch (result) {
@@ -1395,65 +1925,77 @@ static void mvumi_fire_cmd(struct mvumi_hba *mhba, struct mvumi_cmd *cmd)
 
                        return;
                }
-       }
+       } while (!list_empty(&mhba->waiting_req_list) && count--);
+
        if (num_of_cl_sent > 0)
                mvumi_send_ib_list_entry(mhba);
 }
 
 /**
  * mvumi_enable_intr - Enables interrupts
- * @regs:                      FW register set
+ * @mhba:              Adapter soft state
  */
-static void mvumi_enable_intr(void *regs)
+static void mvumi_enable_intr(struct mvumi_hba *mhba)
 {
        unsigned int mask;
+       struct mvumi_hw_regs *regs = mhba->regs;
 
-       iowrite32(0x3FFFFFFF, regs + CPU_ARM_TO_PCIEA_MASK_REG);
-       mask = ioread32(regs + CPU_ENPOINTA_MASK_REG);
-       mask |= INT_MAP_DL_CPU2PCIEA | INT_MAP_COMAOUT | INT_MAP_COMAERR;
-       iowrite32(mask, regs + CPU_ENPOINTA_MASK_REG);
+       iowrite32(regs->int_drbl_int_mask, regs->arm_to_pciea_mask_reg);
+       mask = ioread32(regs->enpointa_mask_reg);
+       mask |= regs->int_dl_cpu2pciea | regs->int_comaout | regs->int_comaerr;
+       iowrite32(mask, regs->enpointa_mask_reg);
 }
 
 /**
  * mvumi_disable_intr -Disables interrupt
- * @regs:                      FW register set
+ * @mhba:              Adapter soft state
  */
-static void mvumi_disable_intr(void *regs)
+static void mvumi_disable_intr(struct mvumi_hba *mhba)
 {
        unsigned int mask;
+       struct mvumi_hw_regs *regs = mhba->regs;
 
-       iowrite32(0, regs + CPU_ARM_TO_PCIEA_MASK_REG);
-       mask = ioread32(regs + CPU_ENPOINTA_MASK_REG);
-       mask &= ~(INT_MAP_DL_CPU2PCIEA | INT_MAP_COMAOUT | INT_MAP_COMAERR);
-       iowrite32(mask, regs + CPU_ENPOINTA_MASK_REG);
+       iowrite32(0, regs->arm_to_pciea_mask_reg);
+       mask = ioread32(regs->enpointa_mask_reg);
+       mask &= ~(regs->int_dl_cpu2pciea | regs->int_comaout |
+                                                       regs->int_comaerr);
+       iowrite32(mask, regs->enpointa_mask_reg);
 }
 
 static int mvumi_clear_intr(void *extend)
 {
        struct mvumi_hba *mhba = (struct mvumi_hba *) extend;
        unsigned int status, isr_status = 0, tmp = 0;
-       void *regs = mhba->mmio;
+       struct mvumi_hw_regs *regs = mhba->regs;
 
-       status = ioread32(regs + CPU_MAIN_INT_CAUSE_REG);
-       if (!(status & INT_MAP_MU) || status == 0xFFFFFFFF)
+       status = ioread32(regs->main_int_cause_reg);
+       if (!(status & regs->int_mu) || status == 0xFFFFFFFF)
                return 1;
-       if (unlikely(status & INT_MAP_COMAERR)) {
-               tmp = ioread32(regs + CLA_ISR_CAUSE);
-               if (tmp & (CLIC_IN_ERR_IRQ | CLIC_OUT_ERR_IRQ))
-                       iowrite32(tmp & (CLIC_IN_ERR_IRQ | CLIC_OUT_ERR_IRQ),
-                                       regs + CLA_ISR_CAUSE);
-               status ^= INT_MAP_COMAERR;
+       if (unlikely(status & regs->int_comaerr)) {
+               tmp = ioread32(regs->outb_isr_cause);
+               if (mhba->pdev->device == PCI_DEVICE_ID_MARVELL_MV9580) {
+                       if (tmp & regs->clic_out_err) {
+                               iowrite32(tmp & regs->clic_out_err,
+                                                       regs->outb_isr_cause);
+                       }
+               } else {
+                       if (tmp & (regs->clic_in_err | regs->clic_out_err))
+                               iowrite32(tmp & (regs->clic_in_err |
+                                               regs->clic_out_err),
+                                               regs->outb_isr_cause);
+               }
+               status ^= mhba->regs->int_comaerr;
                /* inbound or outbound parity error, command will timeout */
        }
-       if (status & INT_MAP_COMAOUT) {
-               tmp = ioread32(regs + CLA_ISR_CAUSE);
-               if (tmp & CLIC_OUT_IRQ)
-                       iowrite32(tmp & CLIC_OUT_IRQ, regs + CLA_ISR_CAUSE);
+       if (status & regs->int_comaout) {
+               tmp = ioread32(regs->outb_isr_cause);
+               if (tmp & regs->clic_irq)
+                       iowrite32(tmp & regs->clic_irq, regs->outb_isr_cause);
        }
-       if (status & INT_MAP_DL_CPU2PCIEA) {
-               isr_status = ioread32(regs + CPU_ARM_TO_PCIEA_DRBL_REG);
+       if (status & regs->int_dl_cpu2pciea) {
+               isr_status = ioread32(regs->arm_to_pciea_drbl_reg);
                if (isr_status)
-                       iowrite32(isr_status, regs + CPU_ARM_TO_PCIEA_DRBL_REG);
+                       iowrite32(isr_status, regs->arm_to_pciea_drbl_reg);
        }
 
        mhba->global_isr = status;
@@ -1464,24 +2006,38 @@ static int mvumi_clear_intr(void *extend)
 
 /**
  * mvumi_read_fw_status_reg - returns the current FW status value
- * @regs:                      FW register set
+ * @mhba:              Adapter soft state
  */
-static unsigned int mvumi_read_fw_status_reg(void *regs)
+static unsigned int mvumi_read_fw_status_reg(struct mvumi_hba *mhba)
 {
        unsigned int status;
 
-       status = ioread32(regs + CPU_ARM_TO_PCIEA_DRBL_REG);
+       status = ioread32(mhba->regs->arm_to_pciea_drbl_reg);
        if (status)
-               iowrite32(status, regs + CPU_ARM_TO_PCIEA_DRBL_REG);
+               iowrite32(status, mhba->regs->arm_to_pciea_drbl_reg);
        return status;
 }
 
-static struct mvumi_instance_template mvumi_instance_template = {
+static struct mvumi_instance_template mvumi_instance_9143 = {
        .fire_cmd = mvumi_fire_cmd,
        .enable_intr = mvumi_enable_intr,
        .disable_intr = mvumi_disable_intr,
        .clear_intr = mvumi_clear_intr,
        .read_fw_status_reg = mvumi_read_fw_status_reg,
+       .check_ib_list = mvumi_check_ib_list_9143,
+       .check_ob_list = mvumi_check_ob_list_9143,
+       .reset_host = mvumi_reset_host_9143,
+};
+
+static struct mvumi_instance_template mvumi_instance_9580 = {
+       .fire_cmd = mvumi_fire_cmd,
+       .enable_intr = mvumi_enable_intr,
+       .disable_intr = mvumi_disable_intr,
+       .clear_intr = mvumi_clear_intr,
+       .read_fw_status_reg = mvumi_read_fw_status_reg,
+       .check_ib_list = mvumi_check_ib_list_9580,
+       .check_ob_list = mvumi_check_ob_list_9580,
+       .reset_host = mvumi_reset_host_9580,
 };
 
 static int mvumi_slave_configure(struct scsi_device *sdev)
@@ -1681,6 +2237,124 @@ static struct scsi_transport_template mvumi_transport_template = {
        .eh_timed_out = mvumi_timed_out,
 };
 
+static int mvumi_cfg_hw_reg(struct mvumi_hba *mhba)
+{
+       void *base = NULL;
+       struct mvumi_hw_regs *regs;
+
+       switch (mhba->pdev->device) {
+       case PCI_DEVICE_ID_MARVELL_MV9143:
+               mhba->mmio = mhba->base_addr[0];
+               base = mhba->mmio;
+               if (!mhba->regs) {
+                       mhba->regs = kzalloc(sizeof(*regs), GFP_KERNEL);
+                       if (mhba->regs == NULL)
+                               return -ENOMEM;
+               }
+               regs = mhba->regs;
+
+               /* For Arm */
+               regs->ctrl_sts_reg          = base + 0x20104;
+               regs->rstoutn_mask_reg      = base + 0x20108;
+               regs->sys_soft_rst_reg      = base + 0x2010C;
+               regs->main_int_cause_reg    = base + 0x20200;
+               regs->enpointa_mask_reg     = base + 0x2020C;
+               regs->rstoutn_en_reg        = base + 0xF1400;
+               /* For Doorbell */
+               regs->pciea_to_arm_drbl_reg = base + 0x20400;
+               regs->arm_to_pciea_drbl_reg = base + 0x20408;
+               regs->arm_to_pciea_mask_reg = base + 0x2040C;
+               regs->pciea_to_arm_msg0     = base + 0x20430;
+               regs->pciea_to_arm_msg1     = base + 0x20434;
+               regs->arm_to_pciea_msg0     = base + 0x20438;
+               regs->arm_to_pciea_msg1     = base + 0x2043C;
+
+               /* For Message Unit */
+
+               regs->inb_aval_count_basel  = base + 0x508;
+               regs->inb_aval_count_baseh  = base + 0x50C;
+               regs->inb_write_pointer     = base + 0x518;
+               regs->inb_read_pointer      = base + 0x51C;
+               regs->outb_coal_cfg         = base + 0x568;
+               regs->outb_copy_basel       = base + 0x5B0;
+               regs->outb_copy_baseh       = base + 0x5B4;
+               regs->outb_copy_pointer     = base + 0x544;
+               regs->outb_read_pointer     = base + 0x548;
+               regs->outb_isr_cause        = base + 0x560;
+               regs->outb_coal_cfg         = base + 0x568;
+               /* Bit setting for HW */
+               regs->int_comaout           = 1 << 8;
+               regs->int_comaerr           = 1 << 6;
+               regs->int_dl_cpu2pciea      = 1 << 1;
+               regs->cl_pointer_toggle     = 1 << 12;
+               regs->clic_irq              = 1 << 1;
+               regs->clic_in_err           = 1 << 8;
+               regs->clic_out_err          = 1 << 12;
+               regs->cl_slot_num_mask      = 0xFFF;
+               regs->int_drbl_int_mask     = 0x3FFFFFFF;
+               regs->int_mu = regs->int_dl_cpu2pciea | regs->int_comaout |
+                                                       regs->int_comaerr;
+               break;
+       case PCI_DEVICE_ID_MARVELL_MV9580:
+               mhba->mmio = mhba->base_addr[2];
+               base = mhba->mmio;
+               if (!mhba->regs) {
+                       mhba->regs = kzalloc(sizeof(*regs), GFP_KERNEL);
+                       if (mhba->regs == NULL)
+                               return -ENOMEM;
+               }
+               regs = mhba->regs;
+               /* For Arm */
+               regs->ctrl_sts_reg          = base + 0x20104;
+               regs->rstoutn_mask_reg      = base + 0x1010C;
+               regs->sys_soft_rst_reg      = base + 0x10108;
+               regs->main_int_cause_reg    = base + 0x10200;
+               regs->enpointa_mask_reg     = base + 0x1020C;
+               regs->rstoutn_en_reg        = base + 0xF1400;
+
+               /* For Doorbell */
+               regs->pciea_to_arm_drbl_reg = base + 0x10460;
+               regs->arm_to_pciea_drbl_reg = base + 0x10480;
+               regs->arm_to_pciea_mask_reg = base + 0x10484;
+               regs->pciea_to_arm_msg0     = base + 0x10400;
+               regs->pciea_to_arm_msg1     = base + 0x10404;
+               regs->arm_to_pciea_msg0     = base + 0x10420;
+               regs->arm_to_pciea_msg1     = base + 0x10424;
+
+               /* For reset*/
+               regs->reset_request         = base + 0x10108;
+               regs->reset_enable          = base + 0x1010c;
+
+               /* For Message Unit */
+               regs->inb_aval_count_basel  = base + 0x4008;
+               regs->inb_aval_count_baseh  = base + 0x400C;
+               regs->inb_write_pointer     = base + 0x4018;
+               regs->inb_read_pointer      = base + 0x401C;
+               regs->outb_copy_basel       = base + 0x4058;
+               regs->outb_copy_baseh       = base + 0x405C;
+               regs->outb_copy_pointer     = base + 0x406C;
+               regs->outb_read_pointer     = base + 0x4070;
+               regs->outb_coal_cfg         = base + 0x4080;
+               regs->outb_isr_cause        = base + 0x4088;
+               /* Bit setting for HW */
+               regs->int_comaout           = 1 << 4;
+               regs->int_dl_cpu2pciea      = 1 << 12;
+               regs->int_comaerr           = 1 << 29;
+               regs->cl_pointer_toggle     = 1 << 14;
+               regs->cl_slot_num_mask      = 0x3FFF;
+               regs->clic_irq              = 1 << 0;
+               regs->clic_out_err          = 1 << 1;
+               regs->int_drbl_int_mask     = 0x3FFFFFFF;
+               regs->int_mu = regs->int_dl_cpu2pciea | regs->int_comaout;
+               break;
+       default:
+               return -1;
+               break;
+       }
+
+       return 0;
+}
+
 /**
  * mvumi_init_fw -     Initializes the FW
  * @mhba:              Adapter soft state
@@ -1699,15 +2373,18 @@ static int mvumi_init_fw(struct mvumi_hba *mhba)
        if (ret)
                goto fail_ioremap;
 
-       mhba->mmio = mhba->base_addr[0];
-
        switch (mhba->pdev->device) {
        case PCI_DEVICE_ID_MARVELL_MV9143:
-               mhba->instancet = &mvumi_instance_template;
+               mhba->instancet = &mvumi_instance_9143;
                mhba->io_seq = 0;
                mhba->max_sge = MVUMI_MAX_SG_ENTRY;
                mhba->request_id_enabled = 1;
                break;
+       case PCI_DEVICE_ID_MARVELL_MV9580:
+               mhba->instancet = &mvumi_instance_9580;
+               mhba->io_seq = 0;
+               mhba->max_sge = MVUMI_MAX_SG_ENTRY;
+               break;
        default:
                dev_err(&mhba->pdev->dev, "device 0x%x not supported!\n",
                                                        mhba->pdev->device);
@@ -1717,15 +2394,21 @@ static int mvumi_init_fw(struct mvumi_hba *mhba)
        }
        dev_dbg(&mhba->pdev->dev, "device id : %04X is found.\n",
                                                        mhba->pdev->device);
-
-       mhba->handshake_page = kzalloc(HSP_MAX_SIZE, GFP_KERNEL);
+       ret = mvumi_cfg_hw_reg(mhba);
+       if (ret) {
+               dev_err(&mhba->pdev->dev,
+                       "failed to allocate memory for reg\n");
+               ret = -ENOMEM;
+               goto fail_alloc_mem;
+       }
+       mhba->handshake_page = pci_alloc_consistent(mhba->pdev, HSP_MAX_SIZE,
+                                               &mhba->handshake_page_phys);
        if (!mhba->handshake_page) {
                dev_err(&mhba->pdev->dev,
                        "failed to allocate memory for handshake\n");
                ret = -ENOMEM;
-               goto fail_alloc_mem;
+               goto fail_alloc_page;
        }
-       mhba->handshake_page_phys = virt_to_phys(mhba->handshake_page);
 
        if (mvumi_start(mhba)) {
                ret = -EINVAL;
@@ -1739,7 +2422,10 @@ static int mvumi_init_fw(struct mvumi_hba *mhba)
 
 fail_ready_state:
        mvumi_release_mem_resource(mhba);
-       kfree(mhba->handshake_page);
+       pci_free_consistent(mhba->pdev, HSP_MAX_SIZE,
+               mhba->handshake_page, mhba->handshake_page_phys);
+fail_alloc_page:
+       kfree(mhba->regs);
 fail_alloc_mem:
        mvumi_unmap_pci_addr(mhba->pdev, mhba->base_addr);
 fail_ioremap:
@@ -1755,6 +2441,7 @@ fail_ioremap:
 static int mvumi_io_attach(struct mvumi_hba *mhba)
 {
        struct Scsi_Host *host = mhba->shost;
+       struct scsi_device *sdev = NULL;
        int ret;
        unsigned int max_sg = (mhba->ib_max_size + 4 -
                sizeof(struct mvumi_msg_frame)) / sizeof(struct mvumi_sgl);
@@ -1764,7 +2451,7 @@ static int mvumi_io_attach(struct mvumi_hba *mhba)
        host->can_queue = (mhba->max_io - 1) ? (mhba->max_io - 1) : 1;
        host->sg_tablesize = mhba->max_sge > max_sg ? max_sg : mhba->max_sge;
        host->max_sectors = mhba->max_transfer_size / 512;
-       host->cmd_per_lun =  (mhba->max_io - 1) ? (mhba->max_io - 1) : 1;
+       host->cmd_per_lun = (mhba->max_io - 1) ? (mhba->max_io - 1) : 1;
        host->max_id = mhba->max_target_id;
        host->max_cmd_len = MAX_COMMAND_SIZE;
        host->transportt = &mvumi_transport_template;
@@ -1775,9 +2462,43 @@ static int mvumi_io_attach(struct mvumi_hba *mhba)
                return ret;
        }
        mhba->fw_flag |= MVUMI_FW_ATTACH;
-       scsi_scan_host(host);
 
+       mutex_lock(&mhba->sas_discovery_mutex);
+       if (mhba->pdev->device == PCI_DEVICE_ID_MARVELL_MV9580)
+               ret = scsi_add_device(host, 0, mhba->max_target_id - 1, 0);
+       else
+               ret = 0;
+       if (ret) {
+               dev_err(&mhba->pdev->dev, "add virtual device failed\n");
+               mutex_unlock(&mhba->sas_discovery_mutex);
+               goto fail_add_device;
+       }
+
+       mhba->dm_thread = kthread_create(mvumi_rescan_bus,
+                                               mhba, "mvumi_scanthread");
+       if (IS_ERR(mhba->dm_thread)) {
+               dev_err(&mhba->pdev->dev,
+                       "failed to create device scan thread\n");
+               mutex_unlock(&mhba->sas_discovery_mutex);
+               goto fail_create_thread;
+       }
+       atomic_set(&mhba->pnp_count, 1);
+       wake_up_process(mhba->dm_thread);
+
+       mutex_unlock(&mhba->sas_discovery_mutex);
        return 0;
+
+fail_create_thread:
+       if (mhba->pdev->device == PCI_DEVICE_ID_MARVELL_MV9580)
+               sdev = scsi_device_lookup(mhba->shost, 0,
+                                               mhba->max_target_id - 1, 0);
+       if (sdev) {
+               scsi_remove_device(sdev);
+               scsi_device_put(sdev);
+       }
+fail_add_device:
+       scsi_remove_host(mhba->shost);
+       return ret;
 }
 
 /**
@@ -1828,8 +2549,12 @@ static int __devinit mvumi_probe_one(struct pci_dev *pdev,
        INIT_LIST_HEAD(&mhba->free_ob_list);
        INIT_LIST_HEAD(&mhba->res_list);
        INIT_LIST_HEAD(&mhba->waiting_req_list);
+       mutex_init(&mhba->device_lock);
+       INIT_LIST_HEAD(&mhba->mhba_dev_list);
+       INIT_LIST_HEAD(&mhba->shost_dev_list);
        atomic_set(&mhba->fw_outstanding, 0);
        init_waitqueue_head(&mhba->int_cmd_wait_q);
+       mutex_init(&mhba->sas_discovery_mutex);
 
        mhba->pdev = pdev;
        mhba->shost = host;
@@ -1845,19 +2570,22 @@ static int __devinit mvumi_probe_one(struct pci_dev *pdev,
                dev_err(&pdev->dev, "failed to register IRQ\n");
                goto fail_init_irq;
        }
-       mhba->instancet->enable_intr(mhba->mmio);
+
+       mhba->instancet->enable_intr(mhba);
        pci_set_drvdata(pdev, mhba);
 
        ret = mvumi_io_attach(mhba);
        if (ret)
                goto fail_io_attach;
+
+       mvumi_backup_bar_addr(mhba);
        dev_dbg(&pdev->dev, "probe mvumi driver successfully.\n");
 
        return 0;
 
 fail_io_attach:
        pci_set_drvdata(pdev, NULL);
-       mhba->instancet->disable_intr(mhba->mmio);
+       mhba->instancet->disable_intr(mhba);
        free_irq(mhba->pdev->irq, mhba);
 fail_init_irq:
        mvumi_release_fw(mhba);
@@ -1877,11 +2605,17 @@ static void mvumi_detach_one(struct pci_dev *pdev)
        struct mvumi_hba *mhba;
 
        mhba = pci_get_drvdata(pdev);
+       if (mhba->dm_thread) {
+               kthread_stop(mhba->dm_thread);
+               mhba->dm_thread = NULL;
+       }
+
+       mvumi_detach_devices(mhba);
        host = mhba->shost;
        scsi_remove_host(mhba->shost);
        mvumi_flush_cache(mhba);
 
-       mhba->instancet->disable_intr(mhba->mmio);
+       mhba->instancet->disable_intr(mhba);
        free_irq(mhba->pdev->irq, mhba);
        mvumi_release_fw(mhba);
        scsi_host_put(host);
@@ -1909,7 +2643,7 @@ static int mvumi_suspend(struct pci_dev *pdev, pm_message_t state)
        mvumi_flush_cache(mhba);
 
        pci_set_drvdata(pdev, mhba);
-       mhba->instancet->disable_intr(mhba->mmio);
+       mhba->instancet->disable_intr(mhba);
        free_irq(mhba->pdev->irq, mhba);
        mvumi_unmap_pci_addr(pdev, mhba->base_addr);
        pci_release_regions(pdev);
@@ -1956,8 +2690,13 @@ static int mvumi_resume(struct pci_dev *pdev)
        if (ret)
                goto release_regions;
 
+       if (mvumi_cfg_hw_reg(mhba)) {
+               ret = -EINVAL;
+               goto unmap_pci_addr;
+       }
+
        mhba->mmio = mhba->base_addr[0];
-       mvumi_reset(mhba->mmio);
+       mvumi_reset(mhba);
 
        if (mvumi_start(mhba)) {
                ret = -EINVAL;
@@ -1970,7 +2709,7 @@ static int mvumi_resume(struct pci_dev *pdev)
                dev_err(&pdev->dev, "failed to register IRQ\n");
                goto unmap_pci_addr;
        }
-       mhba->instancet->enable_intr(mhba->mmio);
+       mhba->instancet->enable_intr(mhba);
 
        return 0;
 
index 10b9237566f0c1cbd2805fd27f58c52b7de7c819..e360135fd1bd59a8d851d90da6a6163d017e9d66 100644 (file)
 #define MV_DRIVER_NAME                 "mvumi"
 #define PCI_VENDOR_ID_MARVELL_2                0x1b4b
 #define PCI_DEVICE_ID_MARVELL_MV9143   0x9143
+#define PCI_DEVICE_ID_MARVELL_MV9580   0x9580
 
 #define MVUMI_INTERNAL_CMD_WAIT_TIME   45
+#define MVUMI_INQUIRY_LENGTH           44
+#define MVUMI_INQUIRY_UUID_OFF         36
+#define MVUMI_INQUIRY_UUID_LEN         8
 
 #define IS_DMA64                       (sizeof(dma_addr_t) == 8)
 
 enum mvumi_qc_result {
-       MV_QUEUE_COMMAND_RESULT_SENT    = 0,
+       MV_QUEUE_COMMAND_RESULT_SENT = 0,
        MV_QUEUE_COMMAND_RESULT_NO_RESOURCE,
 };
 
-enum {
-       /*******************************************/
-
-       /* ARM Mbus Registers Map       */
-
-       /*******************************************/
-       CPU_MAIN_INT_CAUSE_REG  = 0x20200,
-       CPU_MAIN_IRQ_MASK_REG   = 0x20204,
-       CPU_MAIN_FIQ_MASK_REG   = 0x20208,
-       CPU_ENPOINTA_MASK_REG   = 0x2020C,
-       CPU_ENPOINTB_MASK_REG   = 0x20210,
-
-       INT_MAP_COMAERR         = 1 << 6,
-       INT_MAP_COMAIN          = 1 << 7,
-       INT_MAP_COMAOUT         = 1 << 8,
-       INT_MAP_COMBERR         = 1 << 9,
-       INT_MAP_COMBIN          = 1 << 10,
-       INT_MAP_COMBOUT         = 1 << 11,
-
-       INT_MAP_COMAINT = (INT_MAP_COMAOUT | INT_MAP_COMAERR),
-       INT_MAP_COMBINT = (INT_MAP_COMBOUT | INT_MAP_COMBIN | INT_MAP_COMBERR),
-
-       INT_MAP_DL_PCIEA2CPU    = 1 << 0,
-       INT_MAP_DL_CPU2PCIEA    = 1 << 1,
-
-       /***************************************/
+struct mvumi_hw_regs {
+       /* For CPU */
+       void *main_int_cause_reg;
+       void *enpointa_mask_reg;
+       void *enpointb_mask_reg;
+       void *rstoutn_en_reg;
+       void *ctrl_sts_reg;
+       void *rstoutn_mask_reg;
+       void *sys_soft_rst_reg;
+
+       /* For Doorbell */
+       void *pciea_to_arm_drbl_reg;
+       void *arm_to_pciea_drbl_reg;
+       void *arm_to_pciea_mask_reg;
+       void *pciea_to_arm_msg0;
+       void *pciea_to_arm_msg1;
+       void *arm_to_pciea_msg0;
+       void *arm_to_pciea_msg1;
+
+       /* reset register */
+       void *reset_request;
+       void *reset_enable;
+
+       /* For Message Unit */
+       void *inb_list_basel;
+       void *inb_list_baseh;
+       void *inb_aval_count_basel;
+       void *inb_aval_count_baseh;
+       void *inb_write_pointer;
+       void *inb_read_pointer;
+       void *outb_list_basel;
+       void *outb_list_baseh;
+       void *outb_copy_basel;
+       void *outb_copy_baseh;
+       void *outb_copy_pointer;
+       void *outb_read_pointer;
+       void *inb_isr_cause;
+       void *outb_isr_cause;
+       void *outb_coal_cfg;
+       void *outb_coal_timeout;
+
+       /* Bit setting for HW */
+       u32 int_comaout;
+       u32 int_comaerr;
+       u32 int_dl_cpu2pciea;
+       u32 int_mu;
+       u32 int_drbl_int_mask;
+       u32 int_main_int_mask;
+       u32 cl_pointer_toggle;
+       u32 cl_slot_num_mask;
+       u32 clic_irq;
+       u32 clic_in_err;
+       u32 clic_out_err;
+};
 
-       /* ARM Doorbell Registers Map           */
+struct mvumi_dyn_list_entry {
+       u32 src_low_addr;
+       u32 src_high_addr;
+       u32 if_length;
+       u32 reserve;
+};
 
-       /***************************************/
-       CPU_PCIEA_TO_ARM_DRBL_REG       = 0x20400,
-       CPU_PCIEA_TO_ARM_MASK_REG       = 0x20404,
-       CPU_ARM_TO_PCIEA_DRBL_REG       = 0x20408,
-       CPU_ARM_TO_PCIEA_MASK_REG       = 0x2040C,
+#define SCSI_CMD_MARVELL_SPECIFIC      0xE1
+#define CDB_CORE_MODULE                        0x1
+#define CDB_CORE_SHUTDOWN              0xB
 
+enum {
        DRBL_HANDSHAKE                  = 1 << 0,
        DRBL_SOFT_RESET                 = 1 << 1,
        DRBL_BUS_CHANGE                 = 1 << 2,
@@ -86,46 +122,6 @@ enum {
        DRBL_MU_RESET                   = 1 << 4,
        DRBL_HANDSHAKE_ISR              = DRBL_HANDSHAKE,
 
-       CPU_PCIEA_TO_ARM_MSG0           = 0x20430,
-       CPU_PCIEA_TO_ARM_MSG1           = 0x20434,
-       CPU_ARM_TO_PCIEA_MSG0           = 0x20438,
-       CPU_ARM_TO_PCIEA_MSG1           = 0x2043C,
-
-       /*******************************************/
-
-       /* ARM Communication List Registers Map    */
-
-       /*******************************************/
-       CLA_INB_LIST_BASEL              = 0x500,
-       CLA_INB_LIST_BASEH              = 0x504,
-       CLA_INB_AVAL_COUNT_BASEL        = 0x508,
-       CLA_INB_AVAL_COUNT_BASEH        = 0x50C,
-       CLA_INB_DESTI_LIST_BASEL        = 0x510,
-       CLA_INB_DESTI_LIST_BASEH        = 0x514,
-       CLA_INB_WRITE_POINTER           = 0x518,
-       CLA_INB_READ_POINTER            = 0x51C,
-
-       CLA_OUTB_LIST_BASEL             = 0x530,
-       CLA_OUTB_LIST_BASEH             = 0x534,
-       CLA_OUTB_SOURCE_LIST_BASEL      = 0x538,
-       CLA_OUTB_SOURCE_LIST_BASEH      = 0x53C,
-       CLA_OUTB_COPY_POINTER           = 0x544,
-       CLA_OUTB_READ_POINTER           = 0x548,
-
-       CLA_ISR_CAUSE                   = 0x560,
-       CLA_ISR_MASK                    = 0x564,
-
-       INT_MAP_MU              = (INT_MAP_DL_CPU2PCIEA | INT_MAP_COMAINT),
-
-       CL_POINTER_TOGGLE               = 1 << 12,
-
-       CLIC_IN_IRQ                     = 1 << 0,
-       CLIC_OUT_IRQ                    = 1 << 1,
-       CLIC_IN_ERR_IRQ                 = 1 << 8,
-       CLIC_OUT_ERR_IRQ                = 1 << 12,
-
-       CL_SLOT_NUM_MASK                = 0xFFF,
-
        /*
        * Command flag is the flag for the CDB command itself
        */
@@ -137,15 +133,23 @@ enum {
        CMD_FLAG_DATA_IN                = 1 << 3,
        /* 1-host write data */
        CMD_FLAG_DATA_OUT               = 1 << 4,
-
-       SCSI_CMD_MARVELL_SPECIFIC       = 0xE1,
-       CDB_CORE_SHUTDOWN               = 0xB,
+       CMD_FLAG_PRDT_IN_HOST           = 1 << 5,
 };
 
 #define APICDB0_EVENT                  0xF4
 #define APICDB1_EVENT_GETEVENT         0
+#define APICDB1_HOST_GETEVENT          1
 #define MAX_EVENTS_RETURNED            6
 
+#define DEVICE_OFFLINE 0
+#define DEVICE_ONLINE  1
+
+struct mvumi_hotplug_event {
+       u16 size;
+       u8 dummy[2];
+       u8 bitmap[0];
+};
+
 struct mvumi_driver_event {
        u32     time_stamp;
        u32     sequence_no;
@@ -172,8 +176,14 @@ struct mvumi_events_wq {
        void *param;
 };
 
+#define HS_CAPABILITY_SUPPORT_COMPACT_SG       (1U << 4)
+#define HS_CAPABILITY_SUPPORT_PRD_HOST         (1U << 5)
+#define HS_CAPABILITY_SUPPORT_DYN_SRC          (1U << 6)
+#define HS_CAPABILITY_NEW_PAGE_IO_DEPTH_DEF    (1U << 14)
+
 #define MVUMI_MAX_SG_ENTRY     32
 #define SGD_EOT                        (1L << 27)
+#define SGD_EOT_CP             (1L << 22)
 
 struct mvumi_sgl {
        u32     baseaddr_l;
@@ -181,6 +191,39 @@ struct mvumi_sgl {
        u32     flags;
        u32     size;
 };
+struct mvumi_compact_sgl {
+       u32     baseaddr_l;
+       u32     baseaddr_h;
+       u32     flags;
+};
+
+#define GET_COMPACT_SGD_SIZE(sgd)      \
+       ((((struct mvumi_compact_sgl *)(sgd))->flags) & 0x3FFFFFL)
+
+#define SET_COMPACT_SGD_SIZE(sgd, sz) do {                     \
+       (((struct mvumi_compact_sgl *)(sgd))->flags) &= ~0x3FFFFFL;     \
+       (((struct mvumi_compact_sgl *)(sgd))->flags) |= (sz);           \
+} while (0)
+#define sgd_getsz(_mhba, sgd, sz) do {                         \
+       if (_mhba->hba_capability & HS_CAPABILITY_SUPPORT_COMPACT_SG)   \
+               (sz) = GET_COMPACT_SGD_SIZE(sgd);       \
+       else \
+               (sz) = (sgd)->size;                     \
+} while (0)
+
+#define sgd_setsz(_mhba, sgd, sz) do {                         \
+       if (_mhba->hba_capability & HS_CAPABILITY_SUPPORT_COMPACT_SG)   \
+               SET_COMPACT_SGD_SIZE(sgd, sz);          \
+       else \
+               (sgd)->size = (sz);                     \
+} while (0)
+
+#define sgd_inc(_mhba, sgd) do {       \
+       if (_mhba->hba_capability & HS_CAPABILITY_SUPPORT_COMPACT_SG)   \
+               sgd = (struct mvumi_sgl *)(((unsigned char *) (sgd)) + 12); \
+       else \
+               sgd = (struct mvumi_sgl *)(((unsigned char *) (sgd)) + 16); \
+} while (0)
 
 struct mvumi_res {
        struct list_head entry;
@@ -197,7 +240,7 @@ enum resource_type {
 };
 
 struct mvumi_sense_data {
-       u8 error_eode:7;
+       u8 error_code:7;
        u8 valid:1;
        u8 segment_number;
        u8 sense_key:4;
@@ -220,6 +263,7 @@ struct mvumi_sense_data {
 struct mvumi_cmd {
        struct list_head queue_pointer;
        struct mvumi_msg_frame *frame;
+       dma_addr_t frame_phys;
        struct scsi_cmnd *scmd;
        atomic_t sync_cmd;
        void *data_buf;
@@ -393,7 +437,8 @@ struct mvumi_hs_page2 {
        u16 frame_length;
 
        u8 host_type;
-       u8 reserved[3];
+       u8 host_cap;
+       u8 reserved[2];
        struct version_info host_ver;
        u32 system_io_bus;
        u32 slot_number;
@@ -435,8 +480,17 @@ struct mvumi_tag {
        unsigned short size;
 };
 
+struct mvumi_device {
+       struct list_head list;
+       struct scsi_device *sdev;
+       u64     wwid;
+       u8      dev_type;
+       int     id;
+};
+
 struct mvumi_hba {
        void *base_addr[MAX_BASE_ADDRESS];
+       u32 pci_base[MAX_BASE_ADDRESS];
        void *mmio;
        struct list_head cmd_pool;
        struct Scsi_Host *shost;
@@ -449,6 +503,9 @@ struct mvumi_hba {
        void *ib_list;
        dma_addr_t ib_list_phys;
 
+       void *ib_frame;
+       dma_addr_t ib_frame_phys;
+
        void *ob_list;
        dma_addr_t ob_list_phys;
 
@@ -477,12 +534,14 @@ struct mvumi_hba {
        unsigned char hba_total_pages;
        unsigned char fw_flag;
        unsigned char request_id_enabled;
+       unsigned char eot_flag;
        unsigned short hba_capability;
        unsigned short io_seq;
 
        unsigned int ib_cur_slot;
        unsigned int ob_cur_slot;
        unsigned int fw_state;
+       struct mutex sas_discovery_mutex;
 
        struct list_head ob_data_list;
        struct list_head free_ob_list;
@@ -491,14 +550,24 @@ struct mvumi_hba {
 
        struct mvumi_tag tag_pool;
        struct mvumi_cmd **tag_cmd;
+       struct mvumi_hw_regs *regs;
+       struct mutex device_lock;
+       struct list_head mhba_dev_list;
+       struct list_head shost_dev_list;
+       struct task_struct *dm_thread;
+       atomic_t pnp_count;
 };
 
 struct mvumi_instance_template {
-       void (*fire_cmd)(struct mvumi_hba *, struct mvumi_cmd *);
-       void (*enable_intr)(void *) ;
-       void (*disable_intr)(void *);
-       int (*clear_intr)(void *);
-       unsigned int (*read_fw_status_reg)(void *);
+       void (*fire_cmd) (struct mvumi_hba *, struct mvumi_cmd *);
+       void (*enable_intr) (struct mvumi_hba *);
+       void (*disable_intr) (struct mvumi_hba *);
+       int (*clear_intr) (void *);
+       unsigned int (*read_fw_status_reg) (struct mvumi_hba *);
+       unsigned int (*check_ib_list) (struct mvumi_hba *);
+       int (*check_ob_list) (struct mvumi_hba *, unsigned int *,
+                             unsigned int *);
+       int (*reset_host) (struct mvumi_hba *);
 };
 
 extern struct timezone sys_tz;
index 799a58bb98599c8900a7d24d391b75883e9a8a16..48fca47384b745894e0a8a853c8fc937daa196df 100644 (file)
@@ -2080,6 +2080,7 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
        uint8_t       domain;
        char            connect_type[22];
        struct qla_hw_data *ha = vha->hw;
+       unsigned long flags;
 
        /* Get host addresses. */
        rval = qla2x00_get_adapter_id(vha,
@@ -2154,9 +2155,9 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
        vha->d_id.b.area = area;
        vha->d_id.b.al_pa = al_pa;
 
-       spin_lock(&ha->vport_slock);
+       spin_lock_irqsave(&ha->vport_slock, flags);
        qlt_update_vp_map(vha, SET_AL_PA);
-       spin_unlock(&ha->vport_slock);
+       spin_unlock_irqrestore(&ha->vport_slock, flags);
 
        if (!vha->flags.init_done)
                ql_log(ql_log_info, vha, 0x2010,
index bddc97c5c8e92fdd1de11b24d9ac338653daca8e..0e09d8f433d1683e61ba61074d7c67b71919d970 100644 (file)
@@ -1403,7 +1403,7 @@ static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha,
        ctio->u.status1.scsi_status =
            __constant_cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID);
        ctio->u.status1.response_len = __constant_cpu_to_le16(8);
-       ((uint32_t *)ctio->u.status1.sense_data)[0] = cpu_to_be32(resp_code);
+       ctio->u.status1.sense_data[0] = resp_code;
 
        qla2x00_start_iocbs(ha, ha->req);
 }
index 4752f65a9272a610a80bb17e25c3ebd736c9894b..2358c16c4c8ea8a0cdb85c33c2c97a5b4e65c400 100644 (file)
@@ -735,17 +735,6 @@ static int tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd)
        return 0;
 }
 
-static u16 tcm_qla2xxx_get_fabric_sense_len(void)
-{
-       return 0;
-}
-
-static u16 tcm_qla2xxx_set_fabric_sense_len(struct se_cmd *se_cmd,
-                                       u32 sense_length)
-{
-       return 0;
-}
-
 /* Local pointer to allocated TCM configfs fabric module */
 struct target_fabric_configfs *tcm_qla2xxx_fabric_configfs;
 struct target_fabric_configfs *tcm_qla2xxx_npiv_fabric_configfs;
@@ -1691,8 +1680,6 @@ static struct target_core_fabric_ops tcm_qla2xxx_ops = {
        .queue_data_in                  = tcm_qla2xxx_queue_data_in,
        .queue_status                   = tcm_qla2xxx_queue_status,
        .queue_tm_rsp                   = tcm_qla2xxx_queue_tm_rsp,
-       .get_fabric_sense_len           = tcm_qla2xxx_get_fabric_sense_len,
-       .set_fabric_sense_len           = tcm_qla2xxx_set_fabric_sense_len,
        /*
         * Setup function pointers for generic logic in
         * target_core_fabric_configfs.c
@@ -1740,8 +1727,6 @@ static struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
        .queue_data_in                  = tcm_qla2xxx_queue_data_in,
        .queue_status                   = tcm_qla2xxx_queue_status,
        .queue_tm_rsp                   = tcm_qla2xxx_queue_tm_rsp,
-       .get_fabric_sense_len           = tcm_qla2xxx_get_fabric_sense_len,
-       .set_fabric_sense_len           = tcm_qla2xxx_set_fabric_sense_len,
        /*
         * Setup function pointers for generic logic in
         * target_core_fabric_configfs.c
index 57fbd5a3d4e2dae3b29ec3337c3493eb4cf815c3..5cda11c07c689a55b7df5080ac580389963d5d78 100644 (file)
@@ -2055,7 +2055,7 @@ static void unmap_region(sector_t lba, unsigned int len)
                block = lba + alignment;
                rem = do_div(block, granularity);
 
-               if (rem == 0 && lba + granularity <= end && block < map_size) {
+               if (rem == 0 && lba + granularity < end && block < map_size) {
                        clear_bit(block, map_storep);
                        if (scsi_debug_lbprz)
                                memset(fake_storep +
index de2337f255a74ff02888f67e1d202766f257930a..c1b05a83d403221912fb845e314d3a30656a89fc 100644 (file)
@@ -789,7 +789,6 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
                             int cmnd_size, int timeout, unsigned sense_bytes)
 {
        struct scsi_device *sdev = scmd->device;
-       struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd);
        struct Scsi_Host *shost = sdev->host;
        DECLARE_COMPLETION_ONSTACK(done);
        unsigned long timeleft;
@@ -845,8 +844,11 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
 
        scsi_eh_restore_cmnd(scmd, &ses);
 
-       if (sdrv && sdrv->eh_action)
-               rtn = sdrv->eh_action(scmd, cmnd, cmnd_size, rtn);
+       if (scmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
+               struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd);
+               if (sdrv->eh_action)
+                       rtn = sdrv->eh_action(scmd, cmnd, cmnd_size, rtn);
+       }
 
        return rtn;
 }
index 528d52beaa1ca67b44079438aa3c87408b24c883..01440782feb2056602a619bbbdb7190d06a7a14a 100644 (file)
@@ -1221,7 +1221,12 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
        /*
         * At this point, all outstanding requests in the adapter
         * should have been flushed out and return to us
+        * There is a potential race here where the host may be in
+        * the process of responding when we return from here.
+        * Just wait for all in-transit packets to be accounted for
+        * before we return from here.
         */
+       storvsc_wait_to_drain(stor_device);
 
        return SUCCESS;
 }
index 3e79a2f0004279d0b2b1175281d003a664d5aeee..595af1ae4421937ba1b157d79b84d081866e8355 100644 (file)
@@ -219,7 +219,7 @@ static int virtscsi_kick_event(struct virtio_scsi *vscsi,
        struct scatterlist sg;
        unsigned long flags;
 
-       sg_set_buf(&sg, &event_node->event, sizeof(struct virtio_scsi_event));
+       sg_init_one(&sg, &event_node->event, sizeof(struct virtio_scsi_event));
 
        spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
 
@@ -279,6 +279,31 @@ static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi,
        }
 }
 
+static void virtscsi_handle_param_change(struct virtio_scsi *vscsi,
+                                        struct virtio_scsi_event *event)
+{
+       struct scsi_device *sdev;
+       struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev);
+       unsigned int target = event->lun[1];
+       unsigned int lun = (event->lun[2] << 8) | event->lun[3];
+       u8 asc = event->reason & 255;
+       u8 ascq = event->reason >> 8;
+
+       sdev = scsi_device_lookup(shost, 0, target, lun);
+       if (!sdev) {
+               pr_err("SCSI device %d 0 %d %d not found\n",
+                       shost->host_no, target, lun);
+               return;
+       }
+
+       /* Handle "Parameters changed", "Mode parameters changed", and
+          "Capacity data has changed".  */
+       if (asc == 0x2a && (ascq == 0x00 || ascq == 0x01 || ascq == 0x09))
+               scsi_rescan_device(&sdev->sdev_gendev);
+
+       scsi_device_put(sdev);
+}
+
 static void virtscsi_handle_event(struct work_struct *work)
 {
        struct virtio_scsi_event_node *event_node =
@@ -297,6 +322,9 @@ static void virtscsi_handle_event(struct work_struct *work)
        case VIRTIO_SCSI_T_TRANSPORT_RESET:
                virtscsi_handle_transport_reset(vscsi, event);
                break;
+       case VIRTIO_SCSI_T_PARAM_CHANGE:
+               virtscsi_handle_param_change(vscsi, event);
+               break;
        default:
                pr_err("Unsupport virtio scsi event %x\n", event->event);
        }
@@ -677,7 +705,11 @@ static int __devinit virtscsi_probe(struct virtio_device *vdev)
        cmd_per_lun = virtscsi_config_get(vdev, cmd_per_lun) ?: 1;
        shost->cmd_per_lun = min_t(u32, cmd_per_lun, shost->can_queue);
        shost->max_sectors = virtscsi_config_get(vdev, max_sectors) ?: 0xFFFF;
-       shost->max_lun = virtscsi_config_get(vdev, max_lun) + 1;
+
+       /* LUNs > 256 are reported with format 1, so they go in the range
+        * 16640-32767.
+        */
+       shost->max_lun = virtscsi_config_get(vdev, max_lun) + 1 + 0x4000;
        shost->max_id = num_targets;
        shost->max_channel = 0;
        shost->max_cmd_len = VIRTIO_SCSI_CDB_SIZE;
@@ -733,7 +765,8 @@ static struct virtio_device_id id_table[] = {
 };
 
 static unsigned int features[] = {
-       VIRTIO_SCSI_F_HOTPLUG
+       VIRTIO_SCSI_F_HOTPLUG,
+       VIRTIO_SCSI_F_CHANGE,
 };
 
 static struct virtio_driver virtio_scsi_driver = {
index 8c2ff2490d991575223878aa9c06a8330d2500b2..1acae359cabea0c3c48b93390220b9909f012e39 100644 (file)
@@ -134,6 +134,7 @@ config SPI_DAVINCI
        tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
        depends on ARCH_DAVINCI
        select SPI_BITBANG
+       select TI_EDMA
        help
          SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
 
index 3afe2f4f5b8eb231bae471d6e4bdd5d48d385dae..147dfa87a64b6260b52f71b62d7880ec6905fdfb 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
+#include <linux/edma.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
 #include <linux/slab.h>
 
 #include <linux/platform_data/spi-davinci.h>
-#include <mach/edma.h>
 
 #define SPI_NO_RESOURCE                ((resource_size_t)-1)
 
 #define SPIDEF         0x4c
 #define SPIFMT0                0x50
 
-/* We have 2 DMA channels per CS, one for RX and one for TX */
-struct davinci_spi_dma {
-       int                     tx_channel;
-       int                     rx_channel;
-       int                     dummy_param_slot;
-       enum dma_event_q        eventq;
-};
-
 /* SPI Controller driver's private data. */
 struct davinci_spi {
        struct spi_bitbang      bitbang;
@@ -134,11 +127,14 @@ struct davinci_spi {
 
        const void              *tx;
        void                    *rx;
-#define SPI_TMP_BUFSZ  (SMP_CACHE_BYTES + 1)
-       u8                      rx_tmp_buf[SPI_TMP_BUFSZ];
        int                     rcount;
        int                     wcount;
-       struct davinci_spi_dma  dma;
+
+       struct dma_chan         *dma_rx;
+       struct dma_chan         *dma_tx;
+       int                     dma_rx_chnum;
+       int                     dma_tx_chnum;
+
        struct davinci_spi_platform_data *pdata;
 
        void                    (*get_rx)(u32 rx_data, struct davinci_spi *);
@@ -496,21 +492,23 @@ out:
        return errors;
 }
 
-static void davinci_spi_dma_callback(unsigned lch, u16 status, void *data)
+static void davinci_spi_dma_rx_callback(void *data)
 {
-       struct davinci_spi *dspi = data;
-       struct davinci_spi_dma *dma = &dspi->dma;
+       struct davinci_spi *dspi = (struct davinci_spi *)data;
 
-       edma_stop(lch);
+       dspi->rcount = 0;
 
-       if (status == DMA_COMPLETE) {
-               if (lch == dma->rx_channel)
-                       dspi->rcount = 0;
-               if (lch == dma->tx_channel)
-                       dspi->wcount = 0;
-       }
+       if (!dspi->wcount && !dspi->rcount)
+               complete(&dspi->done);
+}
 
-       if ((!dspi->wcount && !dspi->rcount) || (status != DMA_COMPLETE))
+static void davinci_spi_dma_tx_callback(void *data)
+{
+       struct davinci_spi *dspi = (struct davinci_spi *)data;
+
+       dspi->wcount = 0;
+
+       if (!dspi->wcount && !dspi->rcount)
                complete(&dspi->done);
 }
 
@@ -526,20 +524,20 @@ static void davinci_spi_dma_callback(unsigned lch, u16 status, void *data)
 static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
 {
        struct davinci_spi *dspi;
-       int data_type, ret;
+       int data_type, ret = -ENOMEM;
        u32 tx_data, spidat1;
        u32 errors = 0;
        struct davinci_spi_config *spicfg;
        struct davinci_spi_platform_data *pdata;
        unsigned uninitialized_var(rx_buf_count);
-       struct device *sdev;
+       void *dummy_buf = NULL;
+       struct scatterlist sg_rx, sg_tx;
 
        dspi = spi_master_get_devdata(spi->master);
        pdata = dspi->pdata;
        spicfg = (struct davinci_spi_config *)spi->controller_data;
        if (!spicfg)
                spicfg = &davinci_spi_default_cfg;
-       sdev = dspi->bitbang.master->dev.parent;
 
        /* convert len to words based on bits_per_word */
        data_type = dspi->bytes_per_word[spi->chip_select];
@@ -567,112 +565,83 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
                spidat1 |= tx_data & 0xFFFF;
                iowrite32(spidat1, dspi->base + SPIDAT1);
        } else {
-               struct davinci_spi_dma *dma;
-               unsigned long tx_reg, rx_reg;
-               struct edmacc_param param;
-               void *rx_buf;
-               int b, c;
-
-               dma = &dspi->dma;
-
-               tx_reg = (unsigned long)dspi->pbase + SPIDAT1;
-               rx_reg = (unsigned long)dspi->pbase + SPIBUF;
-
-               /*
-                * Transmit DMA setup
-                *
-                * If there is transmit data, map the transmit buffer, set it
-                * as the source of data and set the source B index to data
-                * size. If there is no transmit data, set the transmit register
-                * as the source of data, and set the source B index to zero.
-                *
-                * The destination is always the transmit register itself. And
-                * the destination never increments.
-                */
-
-               if (t->tx_buf) {
-                       t->tx_dma = dma_map_single(&spi->dev, (void *)t->tx_buf,
-                                               t->len, DMA_TO_DEVICE);
-                       if (dma_mapping_error(&spi->dev, t->tx_dma)) {
-                               dev_dbg(sdev, "Unable to DMA map %d bytes"
-                                               "TX buffer\n", t->len);
-                               return -ENOMEM;
-                       }
-               }
-
-               /*
-                * If number of words is greater than 65535, then we need
-                * to configure a 3 dimension transfer.  Use the BCNTRLD
-                * feature to allow for transfers that aren't even multiples
-                * of 65535 (or any other possible b size) by first transferring
-                * the remainder amount then grabbing the next N blocks of
-                * 65535 words.
-                */
-
-               c = dspi->wcount / (SZ_64K - 1);        /* N 65535 Blocks */
-               b = dspi->wcount - c * (SZ_64K - 1);    /* Remainder */
-               if (b)
-                       c++;
+               struct dma_slave_config dma_rx_conf = {
+                       .direction = DMA_DEV_TO_MEM,
+                       .src_addr = (unsigned long)dspi->pbase + SPIBUF,
+                       .src_addr_width = data_type,
+                       .src_maxburst = 1,
+               };
+               struct dma_slave_config dma_tx_conf = {
+                       .direction = DMA_MEM_TO_DEV,
+                       .dst_addr = (unsigned long)dspi->pbase + SPIDAT1,
+                       .dst_addr_width = data_type,
+                       .dst_maxburst = 1,
+               };
+               struct dma_async_tx_descriptor *rxdesc;
+               struct dma_async_tx_descriptor *txdesc;
+               void *buf;
+
+               dummy_buf = kzalloc(t->len, GFP_KERNEL);
+               if (!dummy_buf)
+                       goto err_alloc_dummy_buf;
+
+               dmaengine_slave_config(dspi->dma_rx, &dma_rx_conf);
+               dmaengine_slave_config(dspi->dma_tx, &dma_tx_conf);
+
+               sg_init_table(&sg_rx, 1);
+               if (!t->rx_buf)
+                       buf = dummy_buf;
                else
-                       b = SZ_64K - 1;
-
-               param.opt = TCINTEN | EDMA_TCC(dma->tx_channel);
-               param.src = t->tx_buf ? t->tx_dma : tx_reg;
-               param.a_b_cnt = b << 16 | data_type;
-               param.dst = tx_reg;
-               param.src_dst_bidx = t->tx_buf ? data_type : 0;
-               param.link_bcntrld = 0xffffffff;
-               param.src_dst_cidx = t->tx_buf ? data_type : 0;
-               param.ccnt = c;
-               edma_write_slot(dma->tx_channel, &param);
-               edma_link(dma->tx_channel, dma->dummy_param_slot);
-
-               /*
-                * Receive DMA setup
-                *
-                * If there is receive buffer, use it to receive data. If there
-                * is none provided, use a temporary receive buffer. Set the
-                * destination B index to 0 so effectively only one byte is used
-                * in the temporary buffer (address does not increment).
-                *
-                * The source of receive data is the receive data register. The
-                * source address never increments.
-                */
-
-               if (t->rx_buf) {
-                       rx_buf = t->rx_buf;
-                       rx_buf_count = t->len;
-               } else {
-                       rx_buf = dspi->rx_tmp_buf;
-                       rx_buf_count = sizeof(dspi->rx_tmp_buf);
+                       buf = t->rx_buf;
+               t->rx_dma = dma_map_single(&spi->dev, buf,
+                               t->len, DMA_FROM_DEVICE);
+               if (!t->rx_dma) {
+                       ret = -EFAULT;
+                       goto err_rx_map;
                }
+               sg_dma_address(&sg_rx) = t->rx_dma;
+               sg_dma_len(&sg_rx) = t->len;
 
-               t->rx_dma = dma_map_single(&spi->dev, rx_buf, rx_buf_count,
-                                                       DMA_FROM_DEVICE);
-               if (dma_mapping_error(&spi->dev, t->rx_dma)) {
-                       dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n",
-                                                               rx_buf_count);
-                       if (t->tx_buf)
-                               dma_unmap_single(&spi->dev, t->tx_dma, t->len,
-                                                               DMA_TO_DEVICE);
-                       return -ENOMEM;
+               sg_init_table(&sg_tx, 1);
+               if (!t->tx_buf)
+                       buf = dummy_buf;
+               else
+                       buf = (void *)t->tx_buf;
+               t->tx_dma = dma_map_single(&spi->dev, buf,
+                               t->len, DMA_FROM_DEVICE);
+               if (!t->tx_dma) {
+                       ret = -EFAULT;
+                       goto err_tx_map;
                }
-
-               param.opt = TCINTEN | EDMA_TCC(dma->rx_channel);
-               param.src = rx_reg;
-               param.a_b_cnt = b << 16 | data_type;
-               param.dst = t->rx_dma;
-               param.src_dst_bidx = (t->rx_buf ? data_type : 0) << 16;
-               param.link_bcntrld = 0xffffffff;
-               param.src_dst_cidx = (t->rx_buf ? data_type : 0) << 16;
-               param.ccnt = c;
-               edma_write_slot(dma->rx_channel, &param);
+               sg_dma_address(&sg_tx) = t->tx_dma;
+               sg_dma_len(&sg_tx) = t->len;
+
+               rxdesc = dmaengine_prep_slave_sg(dspi->dma_rx,
+                               &sg_rx, 1, DMA_DEV_TO_MEM,
+                               DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               if (!rxdesc)
+                       goto err_desc;
+
+               txdesc = dmaengine_prep_slave_sg(dspi->dma_tx,
+                               &sg_tx, 1, DMA_MEM_TO_DEV,
+                               DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               if (!txdesc)
+                       goto err_desc;
+
+               rxdesc->callback = davinci_spi_dma_rx_callback;
+               rxdesc->callback_param = (void *)dspi;
+               txdesc->callback = davinci_spi_dma_tx_callback;
+               txdesc->callback_param = (void *)dspi;
 
                if (pdata->cshold_bug)
                        iowrite16(spidat1 >> 16, dspi->base + SPIDAT1 + 2);
 
-               edma_start(dma->rx_channel);
-               edma_start(dma->tx_channel);
+               dmaengine_submit(rxdesc);
+               dmaengine_submit(txdesc);
+
+               dma_async_issue_pending(dspi->dma_rx);
+               dma_async_issue_pending(dspi->dma_tx);
+
                set_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN);
        }
 
@@ -690,15 +659,13 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
 
        clear_io_bits(dspi->base + SPIINT, SPIINT_MASKALL);
        if (spicfg->io_type == SPI_IO_TYPE_DMA) {
-
-               if (t->tx_buf)
-                       dma_unmap_single(&spi->dev, t->tx_dma, t->len,
-                                                               DMA_TO_DEVICE);
-
-               dma_unmap_single(&spi->dev, t->rx_dma, rx_buf_count,
-                                                       DMA_FROM_DEVICE);
-
                clear_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN);
+
+               dma_unmap_single(&spi->dev, t->rx_dma,
+                               t->len, DMA_FROM_DEVICE);
+               dma_unmap_single(&spi->dev, t->tx_dma,
+                               t->len, DMA_TO_DEVICE);
+               kfree(dummy_buf);
        }
 
        clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
@@ -716,11 +683,20 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
        }
 
        if (dspi->rcount != 0 || dspi->wcount != 0) {
-               dev_err(sdev, "SPI data transfer error\n");
+               dev_err(&spi->dev, "SPI data transfer error\n");
                return -EIO;
        }
 
        return t->len;
+
+err_desc:
+       dma_unmap_single(&spi->dev, t->tx_dma, t->len, DMA_TO_DEVICE);
+err_tx_map:
+       dma_unmap_single(&spi->dev, t->rx_dma, t->len, DMA_FROM_DEVICE);
+err_rx_map:
+       kfree(dummy_buf);
+err_alloc_dummy_buf:
+       return ret;
 }
 
 /**
@@ -751,39 +727,33 @@ static irqreturn_t davinci_spi_irq(s32 irq, void *data)
 
 static int davinci_spi_request_dma(struct davinci_spi *dspi)
 {
+       dma_cap_mask_t mask;
+       struct device *sdev = dspi->bitbang.master->dev.parent;
        int r;
-       struct davinci_spi_dma *dma = &dspi->dma;
 
-       r = edma_alloc_channel(dma->rx_channel, davinci_spi_dma_callback, dspi,
-                                                               dma->eventq);
-       if (r < 0) {
-               pr_err("Unable to request DMA channel for SPI RX\n");
-               r = -EAGAIN;
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+
+       dspi->dma_rx = dma_request_channel(mask, edma_filter_fn,
+                                          &dspi->dma_rx_chnum);
+       if (!dspi->dma_rx) {
+               dev_err(sdev, "request RX DMA channel failed\n");
+               r = -ENODEV;
                goto rx_dma_failed;
        }
 
-       r = edma_alloc_channel(dma->tx_channel, davinci_spi_dma_callback, dspi,
-                                                               dma->eventq);
-       if (r < 0) {
-               pr_err("Unable to request DMA channel for SPI TX\n");
-               r = -EAGAIN;
+       dspi->dma_tx = dma_request_channel(mask, edma_filter_fn,
+                                          &dspi->dma_tx_chnum);
+       if (!dspi->dma_tx) {
+               dev_err(sdev, "request TX DMA channel failed\n");
+               r = -ENODEV;
                goto tx_dma_failed;
        }
 
-       r = edma_alloc_slot(EDMA_CTLR(dma->tx_channel), EDMA_SLOT_ANY);
-       if (r < 0) {
-               pr_err("Unable to request SPI TX DMA param slot\n");
-               r = -EAGAIN;
-               goto param_failed;
-       }
-       dma->dummy_param_slot = r;
-       edma_link(dma->dummy_param_slot, dma->dummy_param_slot);
-
        return 0;
-param_failed:
-       edma_free_channel(dma->tx_channel);
+
 tx_dma_failed:
-       edma_free_channel(dma->rx_channel);
+       dma_release_channel(dspi->dma_rx);
 rx_dma_failed:
        return r;
 }
@@ -898,9 +868,8 @@ static int __devinit davinci_spi_probe(struct platform_device *pdev)
        dspi->bitbang.txrx_bufs = davinci_spi_bufs;
        if (dma_rx_chan != SPI_NO_RESOURCE &&
            dma_tx_chan != SPI_NO_RESOURCE) {
-               dspi->dma.rx_channel = dma_rx_chan;
-               dspi->dma.tx_channel = dma_tx_chan;
-               dspi->dma.eventq = pdata->dma_event_q;
+               dspi->dma_rx_chnum = dma_rx_chan;
+               dspi->dma_tx_chnum = dma_tx_chan;
 
                ret = davinci_spi_request_dma(dspi);
                if (ret)
@@ -955,9 +924,8 @@ static int __devinit davinci_spi_probe(struct platform_device *pdev)
        return ret;
 
 free_dma:
-       edma_free_channel(dspi->dma.tx_channel);
-       edma_free_channel(dspi->dma.rx_channel);
-       edma_free_slot(dspi->dma.dummy_param_slot);
+       dma_release_channel(dspi->dma_rx);
+       dma_release_channel(dspi->dma_tx);
 free_clk:
        clk_disable(dspi->clk);
        clk_put(dspi->clk);
index 2ec5264dd002a13256e8483747c108593fefb220..ebdb0b676737c27bd8d5d4dc87c41abcc78940ab 100644 (file)
@@ -106,7 +106,8 @@ static void dump_video_chains(void)
        for (i = 0; i < omap_dss_get_num_overlays(); i++) {
                struct omap_overlay *ovl = omap_dss_get_overlay(i);
                struct omap_overlay_manager *mgr = ovl->manager;
-               struct omap_dss_device *dssdev = mgr ? mgr->device : NULL;
+               struct omap_dss_device *dssdev = mgr ?
+                                       mgr->get_device(mgr) : NULL;
                if (dssdev) {
                        DBG("%d: %s -> %s -> %s", i, ovl->name, mgr->name,
                                                dssdev->name);
@@ -185,7 +186,7 @@ static int create_connector(struct drm_device *dev,
        for (j = 0; j < priv->num_encoders; j++) {
                struct omap_overlay_manager *mgr =
                        omap_encoder_get_manager(priv->encoders[j]);
-               if (mgr->device == dssdev) {
+               if (mgr->get_device(mgr) == dssdev) {
                        drm_mode_connector_attach_encoder(connector,
                                        priv->encoders[j]);
                }
index 97c0f78c3c9ca87232fceff82943d293a036d2e1..d6ce2182e67207d41932fec75914b9d2c7f44479 100644 (file)
@@ -427,7 +427,7 @@ int iscsit_reset_np_thread(
        return 0;
 }
 
-int iscsit_del_np_comm(struct iscsi_np *np)
+static int iscsit_del_np_comm(struct iscsi_np *np)
 {
        if (np->np_socket)
                sock_release(np->np_socket);
@@ -785,10 +785,6 @@ static int iscsit_handle_scsi_cmd(
 
        hdr                     = (struct iscsi_scsi_req *) buf;
        payload_length          = ntoh24(hdr->dlength);
-       hdr->itt                = be32_to_cpu(hdr->itt);
-       hdr->data_length        = be32_to_cpu(hdr->data_length);
-       hdr->cmdsn              = be32_to_cpu(hdr->cmdsn);
-       hdr->exp_statsn         = be32_to_cpu(hdr->exp_statsn);
 
        /* FIXME; Add checks for AdditionalHeaderSegment */
 
@@ -852,7 +848,7 @@ done:
                                buf, conn);
        }
 
-       if ((hdr->data_length == payload_length) &&
+       if ((be32_to_cpu(hdr->data_length )== payload_length) &&
            (!(hdr->flags & ISCSI_FLAG_CMD_FINAL))) {
                pr_err("Expected Data Transfer Length and Length of"
                        " Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL"
@@ -861,7 +857,7 @@ done:
                                buf, conn);
        }
 
-       if (payload_length > hdr->data_length) {
+       if (payload_length > be32_to_cpu(hdr->data_length)) {
                pr_err("DataSegmentLength: %u is greater than"
                        " EDTL: %u, protocol error.\n", payload_length,
                                hdr->data_length);
@@ -869,10 +865,10 @@ done:
                                buf, conn);
        }
 
-       if (payload_length > conn->conn_ops->MaxRecvDataSegmentLength) {
+       if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
                pr_err("DataSegmentLength: %u is greater than"
-                       " MaxRecvDataSegmentLength: %u, protocol error.\n",
-                       payload_length, conn->conn_ops->MaxRecvDataSegmentLength);
+                       " MaxXmitDataSegmentLength: %u, protocol error.\n",
+                       payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
                return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
                                buf, conn);
        }
@@ -932,8 +928,8 @@ done:
                spin_unlock_bh(&conn->sess->ttt_lock);
        } else if (hdr->flags & ISCSI_FLAG_CMD_WRITE)
                cmd->targ_xfer_tag = 0xFFFFFFFF;
-       cmd->cmd_sn             = hdr->cmdsn;
-       cmd->exp_stat_sn        = hdr->exp_statsn;
+       cmd->cmd_sn             = be32_to_cpu(hdr->cmdsn);
+       cmd->exp_stat_sn        = be32_to_cpu(hdr->exp_statsn);
        cmd->first_burst_len    = payload_length;
 
        if (cmd->data_direction == DMA_FROM_DEVICE) {
@@ -952,8 +948,9 @@ done:
         * Initialize struct se_cmd descriptor from target_core_mod infrastructure
         */
        transport_init_se_cmd(&cmd->se_cmd, &lio_target_fabric_configfs->tf_ops,
-                       conn->sess->se_sess, hdr->data_length, cmd->data_direction,
-                       sam_task_attr, &cmd->sense_buffer[0]);
+                       conn->sess->se_sess, be32_to_cpu(hdr->data_length),
+                       cmd->data_direction, sam_task_attr,
+                       cmd->sense_buffer + 2);
 
        pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x,"
                " ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt,
@@ -1028,7 +1025,7 @@ attach_cmd:
                                1, 0, buf, cmd);
        }
 
-       iscsit_ack_from_expstatsn(conn, hdr->exp_statsn);
+       iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
 
        /*
         * If no Immediate Data is attached, it's OK to return now.
@@ -1194,11 +1191,6 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
 
        hdr                     = (struct iscsi_data *) buf;
        payload_length          = ntoh24(hdr->dlength);
-       hdr->itt                = be32_to_cpu(hdr->itt);
-       hdr->ttt                = be32_to_cpu(hdr->ttt);
-       hdr->exp_statsn         = be32_to_cpu(hdr->exp_statsn);
-       hdr->datasn             = be32_to_cpu(hdr->datasn);
-       hdr->offset             = be32_to_cpu(hdr->offset);
 
        if (!payload_length) {
                pr_err("DataOUT payload is ZERO, protocol error.\n");
@@ -1216,10 +1208,10 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
        }
        spin_unlock_bh(&conn->sess->session_stats_lock);
 
-       if (payload_length > conn->conn_ops->MaxRecvDataSegmentLength) {
+       if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
                pr_err("DataSegmentLength: %u is greater than"
-                       " MaxRecvDataSegmentLength: %u\n", payload_length,
-                       conn->conn_ops->MaxRecvDataSegmentLength);
+                       " MaxXmitDataSegmentLength: %u\n", payload_length,
+                       conn->conn_ops->MaxXmitDataSegmentLength);
                return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
                                        buf, conn);
        }
@@ -1250,7 +1242,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
        se_cmd = &cmd->se_cmd;
        iscsit_mod_dataout_timer(cmd);
 
-       if ((hdr->offset + payload_length) > cmd->se_cmd.data_length) {
+       if ((be32_to_cpu(hdr->offset) + payload_length) > cmd->se_cmd.data_length) {
                pr_err("DataOut Offset: %u, Length %u greater than"
                        " iSCSI Command EDTL %u, protocol error.\n",
                        hdr->offset, payload_length, cmd->se_cmd.data_length);
@@ -1333,7 +1325,8 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
        rx_size += payload_length;
        iov = &cmd->iov_data[0];
 
-       iov_ret = iscsit_map_iovec(cmd, iov, hdr->offset, payload_length);
+       iov_ret = iscsit_map_iovec(cmd, iov, be32_to_cpu(hdr->offset),
+                                  payload_length);
        if (iov_ret < 0)
                return -1;
 
@@ -1364,7 +1357,8 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
                u32 data_crc;
 
                data_crc = iscsit_do_crypto_hash_sg(&conn->conn_rx_hash, cmd,
-                                                   hdr->offset, payload_length, padding,
+                                                   be32_to_cpu(hdr->offset),
+                                                   payload_length, padding,
                                                    cmd->pad_bytes);
 
                if (checksum != data_crc) {
@@ -1425,30 +1419,26 @@ static int iscsit_handle_nop_out(
 
        hdr                     = (struct iscsi_nopout *) buf;
        payload_length          = ntoh24(hdr->dlength);
-       hdr->itt                = be32_to_cpu(hdr->itt);
-       hdr->ttt                = be32_to_cpu(hdr->ttt);
-       hdr->cmdsn              = be32_to_cpu(hdr->cmdsn);
-       hdr->exp_statsn         = be32_to_cpu(hdr->exp_statsn);
 
-       if ((hdr->itt == 0xFFFFFFFF) && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
+       if (hdr->itt == RESERVED_ITT && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
                pr_err("NOPOUT ITT is reserved, but Immediate Bit is"
                        " not set, protocol error.\n");
                return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
                                        buf, conn);
        }
 
-       if (payload_length > conn->conn_ops->MaxRecvDataSegmentLength) {
+       if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
                pr_err("NOPOUT Ping Data DataSegmentLength: %u is"
-                       " greater than MaxRecvDataSegmentLength: %u, protocol"
+                       " greater than MaxXmitDataSegmentLength: %u, protocol"
                        " error.\n", payload_length,
-                       conn->conn_ops->MaxRecvDataSegmentLength);
+                       conn->conn_ops->MaxXmitDataSegmentLength);
                return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
                                        buf, conn);
        }
 
        pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%09x,"
                " CmdSN: 0x%08x, ExpStatSN: 0x%08x, Length: %u\n",
-               (hdr->itt == 0xFFFFFFFF) ? "Response" : "Request",
+               hdr->itt == RESERVED_ITT ? "Response" : "Request",
                hdr->itt, hdr->ttt, hdr->cmdsn, hdr->exp_statsn,
                payload_length);
        /*
@@ -1458,7 +1448,7 @@ static int iscsit_handle_nop_out(
         * Either way, make sure we allocate an struct iscsi_cmd, as both
         * can contain ping data.
         */
-       if (hdr->ttt == 0xFFFFFFFF) {
+       if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
                cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
                if (!cmd)
                        return iscsit_add_reject(
@@ -1471,12 +1461,12 @@ static int iscsit_handle_nop_out(
                                                1 : 0);
                conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
                cmd->targ_xfer_tag      = 0xFFFFFFFF;
-               cmd->cmd_sn             = hdr->cmdsn;
-               cmd->exp_stat_sn        = hdr->exp_statsn;
+               cmd->cmd_sn             = be32_to_cpu(hdr->cmdsn);
+               cmd->exp_stat_sn        = be32_to_cpu(hdr->exp_statsn);
                cmd->data_direction     = DMA_NONE;
        }
 
-       if (payload_length && (hdr->ttt == 0xFFFFFFFF)) {
+       if (payload_length && hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
                rx_size = payload_length;
                ping_data = kzalloc(payload_length + 1, GFP_KERNEL);
                if (!ping_data) {
@@ -1556,7 +1546,7 @@ static int iscsit_handle_nop_out(
                pr_debug("Ping Data: \"%s\"\n", ping_data);
        }
 
-       if (hdr->itt != 0xFFFFFFFF) {
+       if (hdr->itt != RESERVED_ITT) {
                if (!cmd) {
                        pr_err("Checking CmdSN for NOPOUT,"
                                " but cmd is NULL!\n");
@@ -1569,7 +1559,7 @@ static int iscsit_handle_nop_out(
                list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
                spin_unlock_bh(&conn->cmd_lock);
 
-               iscsit_ack_from_expstatsn(conn, hdr->exp_statsn);
+               iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
 
                if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
                        iscsit_add_cmd_to_response_queue(cmd, conn,
@@ -1590,11 +1580,11 @@ static int iscsit_handle_nop_out(
                return 0;
        }
 
-       if (hdr->ttt != 0xFFFFFFFF) {
+       if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
                /*
                 * This was a response to a unsolicited NOPIN ping.
                 */
-               cmd = iscsit_find_cmd_from_ttt(conn, hdr->ttt);
+               cmd = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt));
                if (!cmd)
                        return -1;
 
@@ -1639,12 +1629,6 @@ static int iscsit_handle_task_mgt_cmd(
        u8 function;
 
        hdr                     = (struct iscsi_tm *) buf;
-       hdr->itt                = be32_to_cpu(hdr->itt);
-       hdr->rtt                = be32_to_cpu(hdr->rtt);
-       hdr->cmdsn              = be32_to_cpu(hdr->cmdsn);
-       hdr->exp_statsn         = be32_to_cpu(hdr->exp_statsn);
-       hdr->refcmdsn           = be32_to_cpu(hdr->refcmdsn);
-       hdr->exp_datasn         = be32_to_cpu(hdr->exp_datasn);
        hdr->flags &= ~ISCSI_FLAG_CMD_FINAL;
        function = hdr->flags;
 
@@ -1655,9 +1639,9 @@ static int iscsit_handle_task_mgt_cmd(
 
        if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
            ((function != ISCSI_TM_FUNC_TASK_REASSIGN) &&
-            (hdr->rtt != ISCSI_RESERVED_TAG))) {
+            hdr->rtt != RESERVED_ITT)) {
                pr_err("RefTaskTag should be set to 0xFFFFFFFF.\n");
-               hdr->rtt = ISCSI_RESERVED_TAG;
+               hdr->rtt = RESERVED_ITT;
        }
 
        if ((function == ISCSI_TM_FUNC_TASK_REASSIGN) &&
@@ -1669,8 +1653,8 @@ static int iscsit_handle_task_mgt_cmd(
                                        buf, conn);
        }
        if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
-           (hdr->refcmdsn != ISCSI_RESERVED_TAG))
-               hdr->refcmdsn = ISCSI_RESERVED_TAG;
+           be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG)
+               hdr->refcmdsn = cpu_to_be32(ISCSI_RESERVED_TAG);
 
        cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
        if (!cmd)
@@ -1700,7 +1684,7 @@ static int iscsit_handle_task_mgt_cmd(
                transport_init_se_cmd(&cmd->se_cmd,
                                      &lio_target_fabric_configfs->tf_ops,
                                      conn->sess->se_sess, 0, DMA_NONE,
-                                     MSG_SIMPLE_TAG, &cmd->sense_buffer[0]);
+                                     MSG_SIMPLE_TAG, cmd->sense_buffer + 2);
 
                switch (function) {
                case ISCSI_TM_FUNC_ABORT_TASK:
@@ -1747,8 +1731,8 @@ static int iscsit_handle_task_mgt_cmd(
        cmd->immediate_cmd      = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
        cmd->init_task_tag      = hdr->itt;
        cmd->targ_xfer_tag      = 0xFFFFFFFF;
-       cmd->cmd_sn             = hdr->cmdsn;
-       cmd->exp_stat_sn        = hdr->exp_statsn;
+       cmd->cmd_sn             = be32_to_cpu(hdr->cmdsn);
+       cmd->exp_stat_sn        = be32_to_cpu(hdr->exp_statsn);
        se_tmr                  = cmd->se_cmd.se_tmr_req;
        tmr_req                 = cmd->tmr_req;
        /*
@@ -1832,7 +1816,7 @@ attach:
                                        ISCSI_REASON_PROTOCOL_ERROR,
                                        1, 0, buf, cmd);
        }
-       iscsit_ack_from_expstatsn(conn, hdr->exp_statsn);
+       iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
 
        if (out_of_order_cmdsn || !(hdr->opcode & ISCSI_OP_IMMEDIATE))
                return 0;
@@ -1869,15 +1853,11 @@ static int iscsit_handle_text_cmd(
 
        hdr                     = (struct iscsi_text *) buf;
        payload_length          = ntoh24(hdr->dlength);
-       hdr->itt                = be32_to_cpu(hdr->itt);
-       hdr->ttt                = be32_to_cpu(hdr->ttt);
-       hdr->cmdsn              = be32_to_cpu(hdr->cmdsn);
-       hdr->exp_statsn         = be32_to_cpu(hdr->exp_statsn);
 
-       if (payload_length > conn->conn_ops->MaxRecvDataSegmentLength) {
+       if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
                pr_err("Unable to accept text parameter length: %u"
-                       "greater than MaxRecvDataSegmentLength %u.\n",
-                      payload_length, conn->conn_ops->MaxRecvDataSegmentLength);
+                       "greater than MaxXmitDataSegmentLength %u.\n",
+                      payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
                return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
                                        buf, conn);
        }
@@ -1989,15 +1969,15 @@ static int iscsit_handle_text_cmd(
        cmd->immediate_cmd      = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
        conn->sess->init_task_tag = cmd->init_task_tag  = hdr->itt;
        cmd->targ_xfer_tag      = 0xFFFFFFFF;
-       cmd->cmd_sn             = hdr->cmdsn;
-       cmd->exp_stat_sn        = hdr->exp_statsn;
+       cmd->cmd_sn             = be32_to_cpu(hdr->cmdsn);
+       cmd->exp_stat_sn        = be32_to_cpu(hdr->exp_statsn);
        cmd->data_direction     = DMA_NONE;
 
        spin_lock_bh(&conn->cmd_lock);
        list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
        spin_unlock_bh(&conn->cmd_lock);
 
-       iscsit_ack_from_expstatsn(conn, hdr->exp_statsn);
+       iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
 
        if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
                cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
@@ -2131,10 +2111,6 @@ static int iscsit_handle_logout_cmd(
 
        hdr                     = (struct iscsi_logout *) buf;
        reason_code             = (hdr->flags & 0x7f);
-       hdr->itt                = be32_to_cpu(hdr->itt);
-       hdr->cid                = be16_to_cpu(hdr->cid);
-       hdr->cmdsn              = be32_to_cpu(hdr->cmdsn);
-       hdr->exp_statsn = be32_to_cpu(hdr->exp_statsn);
 
        if (tiqn) {
                spin_lock(&tiqn->logout_stats.lock);
@@ -2166,9 +2142,9 @@ static int iscsit_handle_logout_cmd(
        cmd->immediate_cmd      = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
        conn->sess->init_task_tag = cmd->init_task_tag  = hdr->itt;
        cmd->targ_xfer_tag      = 0xFFFFFFFF;
-       cmd->cmd_sn             = hdr->cmdsn;
-       cmd->exp_stat_sn        = hdr->exp_statsn;
-       cmd->logout_cid         = hdr->cid;
+       cmd->cmd_sn             = be32_to_cpu(hdr->cmdsn);
+       cmd->exp_stat_sn        = be32_to_cpu(hdr->exp_statsn);
+       cmd->logout_cid         = be16_to_cpu(hdr->cid);
        cmd->logout_reason      = reason_code;
        cmd->data_direction     = DMA_NONE;
 
@@ -2178,7 +2154,7 @@ static int iscsit_handle_logout_cmd(
         */
        if ((reason_code == ISCSI_LOGOUT_REASON_CLOSE_SESSION) ||
           ((reason_code == ISCSI_LOGOUT_REASON_CLOSE_CONNECTION) &&
-           (hdr->cid == conn->cid)))
+           be16_to_cpu(hdr->cid) == conn->cid))
                logout_remove = 1;
 
        spin_lock_bh(&conn->cmd_lock);
@@ -2186,7 +2162,7 @@ static int iscsit_handle_logout_cmd(
        spin_unlock_bh(&conn->cmd_lock);
 
        if (reason_code != ISCSI_LOGOUT_REASON_RECOVERY)
-               iscsit_ack_from_expstatsn(conn, hdr->exp_statsn);
+               iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
 
        /*
         * Immediate commands are executed, well, immediately.
@@ -2219,11 +2195,6 @@ static int iscsit_handle_snack(
 
        hdr                     = (struct iscsi_snack *) buf;
        hdr->flags              &= ~ISCSI_FLAG_CMD_FINAL;
-       hdr->itt                = be32_to_cpu(hdr->itt);
-       hdr->ttt                = be32_to_cpu(hdr->ttt);
-       hdr->exp_statsn         = be32_to_cpu(hdr->exp_statsn);
-       hdr->begrun             = be32_to_cpu(hdr->begrun);
-       hdr->runlength          = be32_to_cpu(hdr->runlength);
 
        pr_debug("Got ISCSI_INIT_SNACK, ITT: 0x%08x, ExpStatSN:"
                " 0x%08x, Type: 0x%02x, BegRun: 0x%08x, RunLength: 0x%08x,"
@@ -2243,13 +2214,18 @@ static int iscsit_handle_snack(
        switch (hdr->flags & ISCSI_FLAG_SNACK_TYPE_MASK) {
        case 0:
                return iscsit_handle_recovery_datain_or_r2t(conn, buf,
-                       hdr->itt, hdr->ttt, hdr->begrun, hdr->runlength);
+                       hdr->itt,
+                       be32_to_cpu(hdr->ttt),
+                       be32_to_cpu(hdr->begrun),
+                       be32_to_cpu(hdr->runlength));
        case ISCSI_FLAG_SNACK_TYPE_STATUS:
-               return iscsit_handle_status_snack(conn, hdr->itt, hdr->ttt,
-                       hdr->begrun, hdr->runlength);
+               return iscsit_handle_status_snack(conn, hdr->itt,
+                       be32_to_cpu(hdr->ttt),
+                       be32_to_cpu(hdr->begrun), be32_to_cpu(hdr->runlength));
        case ISCSI_FLAG_SNACK_TYPE_DATA_ACK:
-               return iscsit_handle_data_ack(conn, hdr->ttt, hdr->begrun,
-                       hdr->runlength);
+               return iscsit_handle_data_ack(conn, be32_to_cpu(hdr->ttt),
+                       be32_to_cpu(hdr->begrun),
+                       be32_to_cpu(hdr->runlength));
        case ISCSI_FLAG_SNACK_TYPE_RDATA:
                /* FIXME: Support R-Data SNACK */
                pr_err("R-Data SNACK Not Supported.\n");
@@ -2414,7 +2390,7 @@ static int iscsit_send_conn_drop_async_message(
        hdr                     = (struct iscsi_async *) cmd->pdu;
        hdr->opcode             = ISCSI_OP_ASYNC_EVENT;
        hdr->flags              = ISCSI_FLAG_CMD_FINAL;
-       cmd->init_task_tag      = 0xFFFFFFFF;
+       cmd->init_task_tag      = RESERVED_ITT;
        cmd->targ_xfer_tag      = 0xFFFFFFFF;
        put_unaligned_be64(0xFFFFFFFFFFFFFFFFULL, &hdr->rsvd4[0]);
        cmd->stat_sn            = conn->stat_sn++;
@@ -2536,12 +2512,17 @@ static int iscsit_send_data_in(
        else
                put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
 
-       hdr->itt                = cpu_to_be32(cmd->init_task_tag);
-       hdr->ttt                = (hdr->flags & ISCSI_FLAG_DATA_ACK) ?
-                                  cpu_to_be32(cmd->targ_xfer_tag) :
-                                  0xFFFFFFFF;
-       hdr->statsn             = (set_statsn) ? cpu_to_be32(cmd->stat_sn) :
-                                               0xFFFFFFFF;
+       hdr->itt                = cmd->init_task_tag;
+
+       if (hdr->flags & ISCSI_FLAG_DATA_ACK)
+               hdr->ttt                = cpu_to_be32(cmd->targ_xfer_tag);
+       else
+               hdr->ttt                = cpu_to_be32(0xFFFFFFFF);
+       if (set_statsn)
+               hdr->statsn             = cpu_to_be32(cmd->stat_sn);
+       else
+               hdr->statsn             = cpu_to_be32(0xFFFFFFFF);
+
        hdr->exp_cmdsn          = cpu_to_be32(conn->sess->exp_cmd_sn);
        hdr->max_cmdsn          = cpu_to_be32(conn->sess->max_cmd_sn);
        hdr->datasn             = cpu_to_be32(datain.data_sn);
@@ -2708,7 +2689,7 @@ static int iscsit_send_logout_response(
        hdr->opcode             = ISCSI_OP_LOGOUT_RSP;
        hdr->flags              |= ISCSI_FLAG_CMD_FINAL;
        hdr->response           = cmd->logout_response;
-       hdr->itt                = cpu_to_be32(cmd->init_task_tag);
+       hdr->itt                = cmd->init_task_tag;
        cmd->stat_sn            = conn->stat_sn++;
        hdr->statsn             = cpu_to_be32(cmd->stat_sn);
 
@@ -2759,7 +2740,7 @@ static int iscsit_send_unsolicited_nopin(
        memset(hdr, 0, ISCSI_HDR_LEN);
        hdr->opcode             = ISCSI_OP_NOOP_IN;
        hdr->flags              |= ISCSI_FLAG_CMD_FINAL;
-       hdr->itt                = cpu_to_be32(cmd->init_task_tag);
+       hdr->itt                = cmd->init_task_tag;
        hdr->ttt                = cpu_to_be32(cmd->targ_xfer_tag);
        cmd->stat_sn            = conn->stat_sn;
        hdr->statsn             = cpu_to_be32(cmd->stat_sn);
@@ -2816,7 +2797,7 @@ static int iscsit_send_nopin_response(
        hdr->flags              |= ISCSI_FLAG_CMD_FINAL;
        hton24(hdr->dlength, cmd->buf_ptr_size);
        put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
-       hdr->itt                = cpu_to_be32(cmd->init_task_tag);
+       hdr->itt                = cmd->init_task_tag;
        hdr->ttt                = cpu_to_be32(cmd->targ_xfer_tag);
        cmd->stat_sn            = conn->stat_sn++;
        hdr->statsn             = cpu_to_be32(cmd->stat_sn);
@@ -2906,7 +2887,7 @@ static int iscsit_send_r2t(
        hdr->flags              |= ISCSI_FLAG_CMD_FINAL;
        int_to_scsilun(cmd->se_cmd.orig_fe_lun,
                        (struct scsi_lun *)&hdr->lun);
-       hdr->itt                = cpu_to_be32(cmd->init_task_tag);
+       hdr->itt                = cmd->init_task_tag;
        spin_lock_bh(&conn->sess->ttt_lock);
        r2t->targ_xfer_tag      = conn->sess->targ_xfer_tag++;
        if (r2t->targ_xfer_tag == 0xFFFFFFFF)
@@ -3074,7 +3055,7 @@ static int iscsit_send_status(
        }
        hdr->response           = cmd->iscsi_response;
        hdr->cmd_status         = cmd->se_cmd.scsi_status;
-       hdr->itt                = cpu_to_be32(cmd->init_task_tag);
+       hdr->itt                = cmd->init_task_tag;
        hdr->statsn             = cpu_to_be32(cmd->stat_sn);
 
        iscsit_increment_maxcmdsn(cmd, conn->sess);
@@ -3092,15 +3073,18 @@ static int iscsit_send_status(
        if (cmd->se_cmd.sense_buffer &&
           ((cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ||
            (cmd->se_cmd.se_cmd_flags & SCF_EMULATED_TASK_SENSE))) {
+               put_unaligned_be16(cmd->se_cmd.scsi_sense_length, cmd->sense_buffer);
+               cmd->se_cmd.scsi_sense_length += sizeof (__be16);
+
                padding         = -(cmd->se_cmd.scsi_sense_length) & 3;
-               hton24(hdr->dlength, cmd->se_cmd.scsi_sense_length);
-               iov[iov_count].iov_base = cmd->se_cmd.sense_buffer;
+               hton24(hdr->dlength, (u32)cmd->se_cmd.scsi_sense_length);
+               iov[iov_count].iov_base = cmd->sense_buffer;
                iov[iov_count++].iov_len =
                                (cmd->se_cmd.scsi_sense_length + padding);
                tx_size += cmd->se_cmd.scsi_sense_length;
 
                if (padding) {
-                       memset(cmd->se_cmd.sense_buffer +
+                       memset(cmd->sense_buffer +
                                cmd->se_cmd.scsi_sense_length, 0, padding);
                        tx_size += padding;
                        pr_debug("Adding %u bytes of padding to"
@@ -3109,7 +3093,7 @@ static int iscsit_send_status(
 
                if (conn->conn_ops->DataDigest) {
                        iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
-                               cmd->se_cmd.sense_buffer,
+                               cmd->sense_buffer,
                                (cmd->se_cmd.scsi_sense_length + padding),
                                0, NULL, (u8 *)&cmd->data_crc);
 
@@ -3184,7 +3168,7 @@ static int iscsit_send_task_mgt_rsp(
        hdr->opcode             = ISCSI_OP_SCSI_TMFUNC_RSP;
        hdr->flags              = ISCSI_FLAG_CMD_FINAL;
        hdr->response           = iscsit_convert_tcm_tmr_rsp(se_tmr);
-       hdr->itt                = cpu_to_be32(cmd->init_task_tag);
+       hdr->itt                = cmd->init_task_tag;
        cmd->stat_sn            = conn->stat_sn++;
        hdr->statsn             = cpu_to_be32(cmd->stat_sn);
 
@@ -3236,7 +3220,7 @@ static bool iscsit_check_inaddr_any(struct iscsi_np *np)
                struct sockaddr_in * sock_in =
                        (struct sockaddr_in *)&np->np_sockaddr;
 
-               if (sock_in->sin_addr.s_addr == INADDR_ANY)
+               if (sock_in->sin_addr.s_addr == htonl(INADDR_ANY))
                        ret = true;
        }
 
@@ -3271,7 +3255,6 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
                len += 1;
 
                if ((len + payload_len) > buffer_len) {
-                       spin_unlock(&tiqn->tiqn_tpg_lock);
                        end_of_buf = 1;
                        goto eob;
                }
@@ -3358,7 +3341,7 @@ static int iscsit_send_text_rsp(
        hdr->opcode             = ISCSI_OP_TEXT_RSP;
        hdr->flags              |= ISCSI_FLAG_CMD_FINAL;
        hton24(hdr->dlength, text_length);
-       hdr->itt                = cpu_to_be32(cmd->init_task_tag);
+       hdr->itt                = cmd->init_task_tag;
        hdr->ttt                = cpu_to_be32(cmd->targ_xfer_tag);
        cmd->stat_sn            = conn->stat_sn++;
        hdr->statsn             = cpu_to_be32(cmd->stat_sn);
@@ -3424,6 +3407,7 @@ static int iscsit_send_reject(
        hdr->opcode             = ISCSI_OP_REJECT;
        hdr->flags              |= ISCSI_FLAG_CMD_FINAL;
        hton24(hdr->dlength, ISCSI_HDR_LEN);
+       hdr->ffffffff           = cpu_to_be32(0xffffffff);
        cmd->stat_sn            = conn->stat_sn++;
        hdr->statsn             = cpu_to_be32(cmd->stat_sn);
        hdr->exp_cmdsn  = cpu_to_be32(conn->sess->exp_cmd_sn);
index 12abb4c9e34ef4df14ea3b72792d15f2b06dba0c..f1e4f3155baca39328eee9c4763dab4431efd508 100644 (file)
@@ -38,4 +38,9 @@ extern struct kmem_cache *lio_cmd_cache;
 extern struct kmem_cache *lio_qr_cache;
 extern struct kmem_cache *lio_r2t_cache;
 
+extern struct idr sess_idr;
+extern struct mutex auth_id_lock;
+extern spinlock_t sess_idr_lock;
+
+
 #endif   /*** ISCSI_TARGET_H ***/
index a7b25e783b58bedf4bceb927015e4642aafc5c63..ff6fd4fb624d44fc4791a62af7e837ba18c10fc1 100644 (file)
@@ -135,7 +135,7 @@ static struct configfs_attribute *lio_target_portal_attrs[] = {
 
 #define MAX_PORTAL_LEN         256
 
-struct se_tpg_np *lio_target_call_addnptotpg(
+static struct se_tpg_np *lio_target_call_addnptotpg(
        struct se_portal_group *se_tpg,
        struct config_group *group,
        const char *name)
@@ -1034,6 +1034,9 @@ TPG_PARAM_ATTR(ImmediateData, S_IRUGO | S_IWUSR);
 DEF_TPG_PARAM(MaxRecvDataSegmentLength);
 TPG_PARAM_ATTR(MaxRecvDataSegmentLength, S_IRUGO | S_IWUSR);
 
+DEF_TPG_PARAM(MaxXmitDataSegmentLength);
+TPG_PARAM_ATTR(MaxXmitDataSegmentLength, S_IRUGO | S_IWUSR);
+
 DEF_TPG_PARAM(MaxBurstLength);
 TPG_PARAM_ATTR(MaxBurstLength, S_IRUGO | S_IWUSR);
 
@@ -1079,6 +1082,7 @@ static struct configfs_attribute *lio_target_tpg_param_attrs[] = {
        &iscsi_tpg_param_InitialR2T.attr,
        &iscsi_tpg_param_ImmediateData.attr,
        &iscsi_tpg_param_MaxRecvDataSegmentLength.attr,
+       &iscsi_tpg_param_MaxXmitDataSegmentLength.attr,
        &iscsi_tpg_param_MaxBurstLength.attr,
        &iscsi_tpg_param_FirstBurstLength.attr,
        &iscsi_tpg_param_DefaultTime2Wait.attr,
@@ -1166,7 +1170,7 @@ static struct configfs_attribute *lio_target_tpg_attrs[] = {
 
 /* Start items for lio_target_tiqn_cit */
 
-struct se_portal_group *lio_target_tiqn_addtpg(
+static struct se_portal_group *lio_target_tiqn_addtpg(
        struct se_wwn *wwn,
        struct config_group *group,
        const char *name)
@@ -1216,7 +1220,7 @@ out:
        return NULL;
 }
 
-void lio_target_tiqn_deltpg(struct se_portal_group *se_tpg)
+static void lio_target_tiqn_deltpg(struct se_portal_group *se_tpg)
 {
        struct iscsi_portal_group *tpg;
        struct iscsi_tiqn *tiqn;
@@ -1248,7 +1252,7 @@ static struct configfs_attribute *lio_target_wwn_attrs[] = {
        NULL,
 };
 
-struct se_wwn *lio_target_call_coreaddtiqn(
+static struct se_wwn *lio_target_call_coreaddtiqn(
        struct target_fabric_configfs *tf,
        struct config_group *group,
        const char *name)
@@ -1296,7 +1300,7 @@ struct se_wwn *lio_target_call_coreaddtiqn(
        return &tiqn->tiqn_wwn;
 }
 
-void lio_target_call_coredeltiqn(
+static void lio_target_call_coredeltiqn(
        struct se_wwn *wwn)
 {
        struct iscsi_tiqn *tiqn = container_of(wwn, struct iscsi_tiqn, tiqn_wwn);
@@ -1471,7 +1475,8 @@ static u32 iscsi_get_task_tag(struct se_cmd *se_cmd)
 {
        struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
 
-       return cmd->init_task_tag;
+       /* only used for printks or comparism with ->ref_task_tag */
+       return (__force u32)cmd->init_task_tag;
 }
 
 static int iscsi_get_cmd_state(struct se_cmd *se_cmd)
@@ -1542,29 +1547,6 @@ static int lio_queue_status(struct se_cmd *se_cmd)
        return 0;
 }
 
-static u16 lio_set_fabric_sense_len(struct se_cmd *se_cmd, u32 sense_length)
-{
-       unsigned char *buffer = se_cmd->sense_buffer;
-       /*
-        * From RFC-3720 10.4.7.  Data Segment - Sense and Response Data Segment
-        * 16-bit SenseLength.
-        */
-       buffer[0] = ((sense_length >> 8) & 0xff);
-       buffer[1] = (sense_length & 0xff);
-       /*
-        * Return two byte offset into allocated sense_buffer.
-        */
-       return 2;
-}
-
-static u16 lio_get_fabric_sense_len(void)
-{
-       /*
-        * Return two byte offset into allocated sense_buffer.
-        */
-       return 2;
-}
-
 static int lio_queue_tm_rsp(struct se_cmd *se_cmd)
 {
        struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
@@ -1748,8 +1730,6 @@ int iscsi_target_register_configfs(void)
        fabric->tf_ops.queue_data_in = &lio_queue_data_in;
        fabric->tf_ops.queue_status = &lio_queue_status;
        fabric->tf_ops.queue_tm_rsp = &lio_queue_tm_rsp;
-       fabric->tf_ops.set_fabric_sense_len = &lio_set_fabric_sense_len;
-       fabric->tf_ops.get_fabric_sense_len = &lio_get_fabric_sense_len;
        /*
         * Setup function pointers for generic logic in target_core_fabric_configfs.c
         */
index 8a908b28d8b2b1455b0cb4c0816131d418912ae8..2ba9f9b9435c8684e59d0c65b6a18a6586ec5490 100644 (file)
 #define NA_DATAOUT_TIMEOUT_RETRIES     5
 #define NA_DATAOUT_TIMEOUT_RETRIES_MAX 15
 #define NA_DATAOUT_TIMEOUT_RETRIES_MIN 1
-#define NA_NOPIN_TIMEOUT               5
+#define NA_NOPIN_TIMEOUT               15
 #define NA_NOPIN_TIMEOUT_MAX           60
 #define NA_NOPIN_TIMEOUT_MIN           3
-#define NA_NOPIN_RESPONSE_TIMEOUT      5
+#define NA_NOPIN_RESPONSE_TIMEOUT      30
 #define NA_NOPIN_RESPONSE_TIMEOUT_MAX  60
 #define NA_NOPIN_RESPONSE_TIMEOUT_MIN  3
 #define NA_RANDOM_DATAIN_PDU_OFFSETS   0
@@ -239,6 +239,7 @@ struct iscsi_conn_ops {
        u8      HeaderDigest;                   /* [0,1] == [None,CRC32C] */
        u8      DataDigest;                     /* [0,1] == [None,CRC32C] */
        u32     MaxRecvDataSegmentLength;       /* [512..2**24-1] */
+       u32     MaxXmitDataSegmentLength;       /* [512..2**24-1] */
        u8      OFMarker;                       /* [0,1] == [No,Yes] */
        u8      IFMarker;                       /* [0,1] == [No,Yes] */
        u32     OFMarkInt;                      /* [1..65535] */
@@ -360,7 +361,7 @@ struct iscsi_cmd {
        /* Command flags */
        enum cmd_flags_table    cmd_flags;
        /* Initiator Task Tag assigned from Initiator */
-       u32                     init_task_tag;
+       itt_t                   init_task_tag;
        /* Target Transfer Tag assigned from Target */
        u32                     targ_xfer_tag;
        /* CmdSN assigned from Initiator */
@@ -478,7 +479,6 @@ struct iscsi_cmd {
 
 struct iscsi_tmr_req {
        bool                    task_reassign:1;
-       u32                     ref_cmd_sn;
        u32                     exp_data_sn;
        struct iscsi_cmd        *ref_cmd;
        struct iscsi_conn_recovery *conn_recovery;
@@ -505,7 +505,7 @@ struct iscsi_conn {
        u32                     auth_id;
        u32                     conn_flags;
        /* Used for iscsi_tx_login_rsp() */
-       u32                     login_itt;
+       itt_t                   login_itt;
        u32                     exp_statsn;
        /* Per connection status sequence number */
        u32                     stat_sn;
@@ -578,6 +578,7 @@ struct iscsi_conn_recovery {
        u16                     cid;
        u32                     cmd_count;
        u32                     maxrecvdatasegmentlength;
+       u32                     maxxmitdatasegmentlength;
        int                     ready_for_reallegiance;
        struct list_head        conn_recovery_cmd_list;
        spinlock_t              conn_recovery_cmd_lock;
@@ -597,7 +598,7 @@ struct iscsi_session {
        /* state session is currently in */
        u32                     session_state;
        /* session wide counter: initiator assigned task tag */
-       u32                     init_task_tag;
+       itt_t                   init_task_tag;
        /* session wide counter: target assigned task tag */
        u32                     targ_xfer_tag;
        u32                     cmdsn_window;
@@ -663,7 +664,7 @@ struct iscsi_login {
        u8 version_max;
        char isid[6];
        u32 cmd_sn;
-       u32 init_task_tag;
+       itt_t init_task_tag;
        u32 initial_exp_statsn;
        u32 rsp_length;
        u16 cid;
index 1a02016ecdab6b478af6a957bf7629c6566acb78..8aacf611b86d43243677845c0a89b8abe825f5a0 100644 (file)
@@ -48,9 +48,9 @@ void iscsit_set_dataout_sequence_values(
        if (cmd->unsolicited_data) {
                cmd->seq_start_offset = cmd->write_data_done;
                cmd->seq_end_offset = (cmd->write_data_done +
-                       (cmd->se_cmd.data_length >
-                        conn->sess->sess_ops->FirstBurstLength) ?
-                       conn->sess->sess_ops->FirstBurstLength : cmd->se_cmd.data_length);
+                       ((cmd->se_cmd.data_length >
+                         conn->sess->sess_ops->FirstBurstLength) ?
+                        conn->sess->sess_ops->FirstBurstLength : cmd->se_cmd.data_length));
                return;
        }
 
@@ -95,14 +95,15 @@ static int iscsit_dataout_within_command_recovery_check(
         */
        if (conn->sess->sess_ops->DataSequenceInOrder) {
                if ((cmd->cmd_flags & ICF_WITHIN_COMMAND_RECOVERY) &&
-                   (cmd->write_data_done != hdr->offset))
+                   cmd->write_data_done != be32_to_cpu(hdr->offset))
                        goto dump;
 
                cmd->cmd_flags &= ~ICF_WITHIN_COMMAND_RECOVERY;
        } else {
                struct iscsi_seq *seq;
 
-               seq = iscsit_get_seq_holder(cmd, hdr->offset, payload_length);
+               seq = iscsit_get_seq_holder(cmd, be32_to_cpu(hdr->offset),
+                                           payload_length);
                if (!seq)
                        return DATAOUT_CANNOT_RECOVER;
                /*
@@ -111,15 +112,15 @@ static int iscsit_dataout_within_command_recovery_check(
                cmd->seq_ptr = seq;
 
                if (conn->sess->sess_ops->DataPDUInOrder) {
-                       if ((seq->status ==
-                            DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY) &&
-                          ((seq->offset != hdr->offset) ||
-                           (seq->data_sn != hdr->datasn)))
+                       if (seq->status ==
+                           DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY &&
+                          (seq->offset != be32_to_cpu(hdr->offset) ||
+                           seq->data_sn != be32_to_cpu(hdr->datasn)))
                                goto dump;
                } else {
-                       if ((seq->status ==
-                            DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY) &&
-                           (seq->data_sn != hdr->datasn))
+                       if (seq->status ==
+                            DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY &&
+                           seq->data_sn != be32_to_cpu(hdr->datasn))
                                goto dump;
                }
 
@@ -148,12 +149,12 @@ static int iscsit_dataout_check_unsolicited_sequence(
        u32 payload_length = ntoh24(hdr->dlength);
 
 
-       if ((hdr->offset < cmd->seq_start_offset) ||
-          ((hdr->offset + payload_length) > cmd->seq_end_offset)) {
+       if ((be32_to_cpu(hdr->offset) < cmd->seq_start_offset) ||
+          ((be32_to_cpu(hdr->offset) + payload_length) > cmd->seq_end_offset)) {
                pr_err("Command ITT: 0x%08x with Offset: %u,"
                " Length: %u outside of Unsolicited Sequence %u:%u while"
                " DataSequenceInOrder=Yes.\n", cmd->init_task_tag,
-               hdr->offset, payload_length, cmd->seq_start_offset,
+               be32_to_cpu(hdr->offset), payload_length, cmd->seq_start_offset,
                        cmd->seq_end_offset);
                return DATAOUT_CANNOT_RECOVER;
        }
@@ -236,12 +237,12 @@ static int iscsit_dataout_check_sequence(
                 * fullfilling an Recovery R2T, it's best to just dump the
                 * payload here, instead of erroring out.
                 */
-               if ((hdr->offset < cmd->seq_start_offset) ||
-                  ((hdr->offset + payload_length) > cmd->seq_end_offset)) {
+               if ((be32_to_cpu(hdr->offset) < cmd->seq_start_offset) ||
+                  ((be32_to_cpu(hdr->offset) + payload_length) > cmd->seq_end_offset)) {
                        pr_err("Command ITT: 0x%08x with Offset: %u,"
                        " Length: %u outside of Sequence %u:%u while"
                        " DataSequenceInOrder=Yes.\n", cmd->init_task_tag,
-                       hdr->offset, payload_length, cmd->seq_start_offset,
+                       be32_to_cpu(hdr->offset), payload_length, cmd->seq_start_offset,
                                cmd->seq_end_offset);
 
                        if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
@@ -251,7 +252,8 @@ static int iscsit_dataout_check_sequence(
 
                next_burst_len = (cmd->next_burst_len + payload_length);
        } else {
-               seq = iscsit_get_seq_holder(cmd, hdr->offset, payload_length);
+               seq = iscsit_get_seq_holder(cmd, be32_to_cpu(hdr->offset),
+                                           payload_length);
                if (!seq)
                        return DATAOUT_CANNOT_RECOVER;
                /*
@@ -366,16 +368,16 @@ static int iscsit_dataout_check_datasn(
                data_sn = seq->data_sn;
        }
 
-       if (hdr->datasn > data_sn) {
+       if (be32_to_cpu(hdr->datasn) > data_sn) {
                pr_err("Command ITT: 0x%08x, received DataSN: 0x%08x"
                        " higher than expected 0x%08x.\n", cmd->init_task_tag,
-                               hdr->datasn, data_sn);
+                               be32_to_cpu(hdr->datasn), data_sn);
                recovery = 1;
                goto recover;
-       } else if (hdr->datasn < data_sn) {
+       } else if (be32_to_cpu(hdr->datasn) < data_sn) {
                pr_err("Command ITT: 0x%08x, received DataSN: 0x%08x"
                        " lower than expected 0x%08x, discarding payload.\n",
-                       cmd->init_task_tag, hdr->datasn, data_sn);
+                       cmd->init_task_tag, be32_to_cpu(hdr->datasn), data_sn);
                dump = 1;
                goto dump;
        }
@@ -415,26 +417,27 @@ static int iscsit_dataout_pre_datapduinorder_yes(
         * error has occured and fail the connection.
         */
        if (conn->sess->sess_ops->DataSequenceInOrder) {
-               if (hdr->offset != cmd->write_data_done) {
+               if (be32_to_cpu(hdr->offset) != cmd->write_data_done) {
                        pr_err("Command ITT: 0x%08x, received offset"
                        " %u different than expected %u.\n", cmd->init_task_tag,
-                               hdr->offset, cmd->write_data_done);
+                               be32_to_cpu(hdr->offset), cmd->write_data_done);
                        recovery = 1;
                        goto recover;
                }
        } else {
                struct iscsi_seq *seq = cmd->seq_ptr;
 
-               if (hdr->offset > seq->offset) {
+               if (be32_to_cpu(hdr->offset) > seq->offset) {
                        pr_err("Command ITT: 0x%08x, received offset"
                        " %u greater than expected %u.\n", cmd->init_task_tag,
-                               hdr->offset, seq->offset);
+                               be32_to_cpu(hdr->offset), seq->offset);
                        recovery = 1;
                        goto recover;
-               } else if (hdr->offset < seq->offset) {
+               } else if (be32_to_cpu(hdr->offset) < seq->offset) {
                        pr_err("Command ITT: 0x%08x, received offset"
                        " %u less than expected %u, discarding payload.\n",
-                               cmd->init_task_tag, hdr->offset, seq->offset);
+                               cmd->init_task_tag, be32_to_cpu(hdr->offset),
+                               seq->offset);
                        dump = 1;
                        goto dump;
                }
@@ -453,7 +456,7 @@ dump:
                return DATAOUT_CANNOT_RECOVER;
 
        return (recovery) ? iscsit_recover_dataout_sequence(cmd,
-               hdr->offset, payload_length) :
+               be32_to_cpu(hdr->offset), payload_length) :
               (dump) ? DATAOUT_WITHIN_COMMAND_RECOVERY : DATAOUT_NORMAL;
 }
 
@@ -465,7 +468,8 @@ static int iscsit_dataout_pre_datapduinorder_no(
        struct iscsi_data *hdr = (struct iscsi_data *) buf;
        u32 payload_length = ntoh24(hdr->dlength);
 
-       pdu = iscsit_get_pdu_holder(cmd, hdr->offset, payload_length);
+       pdu = iscsit_get_pdu_holder(cmd, be32_to_cpu(hdr->offset),
+                                   payload_length);
        if (!pdu)
                return DATAOUT_CANNOT_RECOVER;
 
@@ -479,7 +483,7 @@ static int iscsit_dataout_pre_datapduinorder_no(
        case ISCSI_PDU_RECEIVED_OK:
                pr_err("Command ITT: 0x%08x received already gotten"
                        " Offset: %u, Length: %u\n", cmd->init_task_tag,
-                               hdr->offset, payload_length);
+                               be32_to_cpu(hdr->offset), payload_length);
                return iscsit_dump_data_payload(cmd->conn, payload_length, 1);
        default:
                return DATAOUT_CANNOT_RECOVER;
@@ -553,7 +557,7 @@ static int iscsit_dataout_post_crc_passed(
        if (cmd->unsolicited_data) {
                if ((cmd->first_burst_len + payload_length) ==
                     conn->sess->sess_ops->FirstBurstLength) {
-                       if (iscsit_dataout_update_r2t(cmd, hdr->offset,
+                       if (iscsit_dataout_update_r2t(cmd, be32_to_cpu(hdr->offset),
                                        payload_length) < 0)
                                return DATAOUT_CANNOT_RECOVER;
                        send_r2t = 1;
@@ -561,7 +565,8 @@ static int iscsit_dataout_post_crc_passed(
 
                if (!conn->sess->sess_ops->DataPDUInOrder) {
                        ret = iscsit_dataout_update_datapduinorder_no(cmd,
-                               hdr->datasn, (hdr->flags & ISCSI_FLAG_CMD_FINAL));
+                               be32_to_cpu(hdr->datasn),
+                               (hdr->flags & ISCSI_FLAG_CMD_FINAL));
                        if (ret == DATAOUT_CANNOT_RECOVER)
                                return ret;
                }
@@ -586,7 +591,8 @@ static int iscsit_dataout_post_crc_passed(
                if (conn->sess->sess_ops->DataSequenceInOrder) {
                        if ((cmd->next_burst_len + payload_length) ==
                             conn->sess->sess_ops->MaxBurstLength) {
-                               if (iscsit_dataout_update_r2t(cmd, hdr->offset,
+                               if (iscsit_dataout_update_r2t(cmd,
+                                               be32_to_cpu(hdr->offset),
                                                payload_length) < 0)
                                        return DATAOUT_CANNOT_RECOVER;
                                send_r2t = 1;
@@ -594,7 +600,7 @@ static int iscsit_dataout_post_crc_passed(
 
                        if (!conn->sess->sess_ops->DataPDUInOrder) {
                                ret = iscsit_dataout_update_datapduinorder_no(
-                                               cmd, hdr->datasn,
+                                               cmd, be32_to_cpu(hdr->datasn),
                                                (hdr->flags & ISCSI_FLAG_CMD_FINAL));
                                if (ret == DATAOUT_CANNOT_RECOVER)
                                        return ret;
@@ -610,7 +616,8 @@ static int iscsit_dataout_post_crc_passed(
 
                        if ((seq->next_burst_len + payload_length) ==
                             seq->xfer_len) {
-                               if (iscsit_dataout_update_r2t(cmd, hdr->offset,
+                               if (iscsit_dataout_update_r2t(cmd,
+                                               be32_to_cpu(hdr->offset),
                                                payload_length) < 0)
                                        return DATAOUT_CANNOT_RECOVER;
                                send_r2t = 1;
@@ -618,7 +625,7 @@ static int iscsit_dataout_post_crc_passed(
 
                        if (!conn->sess->sess_ops->DataPDUInOrder) {
                                ret = iscsit_dataout_update_datapduinorder_no(
-                                               cmd, hdr->datasn,
+                                               cmd, be32_to_cpu(hdr->datasn),
                                                (hdr->flags & ISCSI_FLAG_CMD_FINAL));
                                if (ret == DATAOUT_CANNOT_RECOVER)
                                        return ret;
@@ -678,14 +685,15 @@ static int iscsit_dataout_post_crc_failed(
        }
 
 recover:
-       return iscsit_recover_dataout_sequence(cmd, hdr->offset, payload_length);
+       return iscsit_recover_dataout_sequence(cmd, be32_to_cpu(hdr->offset),
+                                               payload_length);
 }
 
 /*
  *     Called from iscsit_handle_data_out() before DataOUT Payload is received
  *     and CRC computed.
  */
-extern int iscsit_check_pre_dataout(
+int iscsit_check_pre_dataout(
        struct iscsi_cmd *cmd,
        unsigned char *buf)
 {
@@ -789,7 +797,7 @@ static void iscsit_handle_time2retain_timeout(unsigned long data)
        target_put_session(sess->se_sess);
 }
 
-extern void iscsit_start_time2retain_handler(struct iscsi_session *sess)
+void iscsit_start_time2retain_handler(struct iscsi_session *sess)
 {
        int tpg_active;
        /*
@@ -822,7 +830,7 @@ extern void iscsit_start_time2retain_handler(struct iscsi_session *sess)
 /*
  *     Called with spin_lock_bh(&struct se_portal_group->session_lock) held
  */
-extern int iscsit_stop_time2retain_timer(struct iscsi_session *sess)
+int iscsit_stop_time2retain_timer(struct iscsi_session *sess)
 {
        struct iscsi_portal_group *tpg = ISCSI_TPG_S(sess);
        struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
@@ -926,7 +934,7 @@ static void iscsit_handle_connection_cleanup(struct iscsi_conn *conn)
        }
 }
 
-extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
+void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
 {
        spin_lock_bh(&conn->state_lock);
        if (atomic_read(&conn->connection_exit)) {
index 3df8a2cef86faab090bcf24dfbc377cc00b32e04..21f29d91a8cb7a604bedf30bd32119b5b7990fbc 100644 (file)
@@ -466,7 +466,7 @@ static int iscsit_handle_recovery_datain(
 int iscsit_handle_recovery_datain_or_r2t(
        struct iscsi_conn *conn,
        unsigned char *buf,
-       u32 init_task_tag,
+       itt_t init_task_tag,
        u32 targ_xfer_tag,
        u32 begrun,
        u32 runlength)
@@ -498,7 +498,7 @@ int iscsit_handle_recovery_datain_or_r2t(
 /* #warning FIXME: Status SNACK needs to be dependent on OPCODE!!! */
 int iscsit_handle_status_snack(
        struct iscsi_conn *conn,
-       u32 init_task_tag,
+       itt_t init_task_tag,
        u32 targ_xfer_tag,
        u32 begrun,
        u32 runlength)
index 85e67e29de6be94b09b1be6038b34ccc017333ab..2a3ebf118a342fb33200810237afef1694c78536 100644 (file)
@@ -7,8 +7,8 @@ extern int iscsit_create_recovery_datain_values_datasequenceinorder_yes(
 extern int iscsit_create_recovery_datain_values_datasequenceinorder_no(
                        struct iscsi_cmd *, struct iscsi_datain_req *);
 extern int iscsit_handle_recovery_datain_or_r2t(struct iscsi_conn *, unsigned char *,
-                       u32, u32, u32, u32);
-extern int iscsit_handle_status_snack(struct iscsi_conn *, u32, u32,
+                       itt_t, u32, u32, u32);
+extern int iscsit_handle_status_snack(struct iscsi_conn *, itt_t, u32,
                        u32, u32);
 extern int iscsit_handle_data_ack(struct iscsi_conn *, u32, u32, u32);
 extern int iscsit_dataout_datapduinorder_no_fbit(struct iscsi_cmd *, struct iscsi_pdu *);
index 65aac14fd8312d12bd57bdc8ad9b59bff8a9a452..17d8c20094fd13e5cd276afbc86ab47a6ca634d3 100644 (file)
@@ -36,7 +36,7 @@
  */
 void iscsit_create_conn_recovery_datain_values(
        struct iscsi_cmd *cmd,
-       u32 exp_data_sn)
+       __be32 exp_data_sn)
 {
        u32 data_sn = 0;
        struct iscsi_conn *conn = cmd->conn;
@@ -44,7 +44,7 @@ void iscsit_create_conn_recovery_datain_values(
        cmd->next_burst_len = 0;
        cmd->read_data_done = 0;
 
-       while (exp_data_sn > data_sn) {
+       while (be32_to_cpu(exp_data_sn) > data_sn) {
                if ((cmd->next_burst_len +
                     conn->conn_ops->MaxRecvDataSegmentLength) <
                     conn->sess->sess_ops->MaxBurstLength) {
@@ -193,15 +193,13 @@ int iscsit_remove_active_connection_recovery_entry(
        return 0;
 }
 
-int iscsit_remove_inactive_connection_recovery_entry(
+static void iscsit_remove_inactive_connection_recovery_entry(
        struct iscsi_conn_recovery *cr,
        struct iscsi_session *sess)
 {
        spin_lock(&sess->cr_i_lock);
        list_del(&cr->cr_list);
        spin_unlock(&sess->cr_i_lock);
-
-       return 0;
 }
 
 /*
@@ -421,6 +419,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
        cr->cid = conn->cid;
        cr->cmd_count = cmd_count;
        cr->maxrecvdatasegmentlength = conn->conn_ops->MaxRecvDataSegmentLength;
+       cr->maxxmitdatasegmentlength = conn->conn_ops->MaxXmitDataSegmentLength;
        cr->sess = conn->sess;
 
        iscsit_attach_inactive_connection_recovery_entry(conn->sess, cr);
index 22f8d24780a606fa12ac473bbc757c39b08b61dc..63f2501f3fe08344ea000d3ae83e414fe4e361de 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef ISCSI_TARGET_ERL2_H
 #define ISCSI_TARGET_ERL2_H
 
-extern void iscsit_create_conn_recovery_datain_values(struct iscsi_cmd *, u32);
+extern void iscsit_create_conn_recovery_datain_values(struct iscsi_cmd *, __be32);
 extern void iscsit_create_conn_recovery_dataout_values(struct iscsi_cmd *);
 extern struct iscsi_conn_recovery *iscsit_get_inactive_connection_recovery_entry(
                        struct iscsi_session *, u16);
index 6aba4395e8d8ffd5aa950c4dfc745791c3f65fc2..cdc8a10939c3d8d00912a6d9b5d735930d4e60ab 100644 (file)
 #include "iscsi_target.h"
 #include "iscsi_target_parameters.h"
 
-extern struct idr sess_idr;
-extern struct mutex auth_id_lock;
-extern spinlock_t sess_idr_lock;
-
 static int iscsi_login_init_conn(struct iscsi_conn *conn)
 {
        INIT_LIST_HEAD(&conn->conn_list);
@@ -196,10 +192,10 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
 static void iscsi_login_set_conn_values(
        struct iscsi_session *sess,
        struct iscsi_conn *conn,
-       u16 cid)
+       __be16 cid)
 {
        conn->sess              = sess;
-       conn->cid               = cid;
+       conn->cid               = be16_to_cpu(cid);
        /*
         * Generate a random Status sequence number (statsn) for the new
         * iSCSI connection.
@@ -234,7 +230,7 @@ static int iscsi_login_zero_tsih_s1(
        iscsi_login_set_conn_values(sess, conn, pdu->cid);
        sess->init_task_tag     = pdu->itt;
        memcpy(&sess->isid, pdu->isid, 6);
-       sess->exp_cmd_sn        = pdu->cmdsn;
+       sess->exp_cmd_sn        = be32_to_cpu(pdu->cmdsn);
        INIT_LIST_HEAD(&sess->sess_conn_list);
        INIT_LIST_HEAD(&sess->sess_ooo_cmdsn_list);
        INIT_LIST_HEAD(&sess->cr_active_list);
@@ -275,7 +271,7 @@ static int iscsi_login_zero_tsih_s1(
         * The FFP CmdSN window values will be allocated from the TPG's
         * Initiator Node's ACL once the login has been successfully completed.
         */
-       sess->max_cmd_sn        = pdu->cmdsn;
+       sess->max_cmd_sn        = be32_to_cpu(pdu->cmdsn);
 
        sess->sess_ops = kzalloc(sizeof(struct iscsi_sess_ops), GFP_KERNEL);
        if (!sess->sess_ops) {
@@ -453,7 +449,7 @@ static int iscsi_login_non_zero_tsih_s2(
                   (sess_p->time2retain_timer_flags & ISCSI_TF_EXPIRED))
                        continue;
                if (!memcmp(sess_p->isid, pdu->isid, 6) &&
-                    (sess_p->tsih == pdu->tsih)) {
+                    (sess_p->tsih == be16_to_cpu(pdu->tsih))) {
                        iscsit_inc_session_usage_count(sess_p);
                        iscsit_stop_time2retain_timer(sess_p);
                        sess = sess_p;
@@ -955,11 +951,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
        }
 
        pdu                     = (struct iscsi_login_req *) buffer;
-       pdu->cid                = be16_to_cpu(pdu->cid);
-       pdu->tsih               = be16_to_cpu(pdu->tsih);
-       pdu->itt                = be32_to_cpu(pdu->itt);
-       pdu->cmdsn              = be32_to_cpu(pdu->cmdsn);
-       pdu->exp_statsn         = be32_to_cpu(pdu->exp_statsn);
+
        /*
         * Used by iscsit_tx_login_rsp() for Login Resonses PDUs
         * when Status-Class != 0.
index 2dba448cac193daf452c16a0eb847a03a2de1d04..e9053a04f24c3b181a2fd1b88f880eedccedb7a2 100644 (file)
@@ -44,7 +44,7 @@ void convert_null_to_semi(char *buf, int len)
                        buf[i] = ';';
 }
 
-int strlen_semi(char *buf)
+static int strlen_semi(char *buf)
 {
        int i = 0;
 
@@ -339,14 +339,14 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log
        hton24(login_rsp->dlength, login->rsp_length);
        memcpy(login_rsp->isid, login->isid, 6);
        login_rsp->tsih                 = cpu_to_be16(login->tsih);
-       login_rsp->itt                  = cpu_to_be32(login->init_task_tag);
+       login_rsp->itt                  = login->init_task_tag;
        login_rsp->statsn               = cpu_to_be32(conn->stat_sn++);
        login_rsp->exp_cmdsn            = cpu_to_be32(conn->sess->exp_cmd_sn);
        login_rsp->max_cmdsn            = cpu_to_be32(conn->sess->max_cmd_sn);
 
        pr_debug("Sending Login Response, Flags: 0x%02x, ITT: 0x%08x,"
                " ExpCmdSN; 0x%08x, MaxCmdSN: 0x%08x, StatSN: 0x%08x, Length:"
-               " %u\n", login_rsp->flags, ntohl(login_rsp->itt),
+               " %u\n", login_rsp->flags, (__force u32)login_rsp->itt,
                ntohl(login_rsp->exp_cmdsn), ntohl(login_rsp->max_cmdsn),
                ntohl(login_rsp->statsn), login->rsp_length);
 
@@ -360,12 +360,9 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log
                return -1;
 
        login->rsp_length               = 0;
-       login_rsp->tsih                 = be16_to_cpu(login_rsp->tsih);
-       login_rsp->itt                  = be32_to_cpu(login_rsp->itt);
-       login_rsp->statsn               = be32_to_cpu(login_rsp->statsn);
        mutex_lock(&sess->cmdsn_mutex);
-       login_rsp->exp_cmdsn            = be32_to_cpu(sess->exp_cmd_sn);
-       login_rsp->max_cmdsn            = be32_to_cpu(sess->max_cmd_sn);
+       login_rsp->exp_cmdsn            = cpu_to_be32(sess->exp_cmd_sn);
+       login_rsp->max_cmdsn            = cpu_to_be32(sess->max_cmd_sn);
        mutex_unlock(&sess->cmdsn_mutex);
 
        return 0;
@@ -381,11 +378,6 @@ static int iscsi_target_do_rx_login_io(struct iscsi_conn *conn, struct iscsi_log
 
        login_req = (struct iscsi_login_req *) login->req;
        payload_length                  = ntoh24(login_req->dlength);
-       login_req->tsih                 = be16_to_cpu(login_req->tsih);
-       login_req->itt                  = be32_to_cpu(login_req->itt);
-       login_req->cid                  = be16_to_cpu(login_req->cid);
-       login_req->cmdsn                = be32_to_cpu(login_req->cmdsn);
-       login_req->exp_statsn           = be32_to_cpu(login_req->exp_statsn);
 
        pr_debug("Got Login Command, Flags 0x%02x, ITT: 0x%08x,"
                " CmdSN: 0x%08x, ExpStatSN: 0x%08x, CID: %hu, Length: %u\n",
@@ -550,7 +542,7 @@ static int iscsi_target_handle_csg_zero(
                        SENDER_INITIATOR|SENDER_RECEIVER,
                        login->req_buf,
                        payload_length,
-                       conn->param_list);
+                       conn);
        if (ret < 0)
                return -1;
 
@@ -627,7 +619,7 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log
                        SENDER_INITIATOR|SENDER_RECEIVER,
                        login->req_buf,
                        payload_length,
-                       conn->param_list);
+                       conn);
        if (ret < 0)
                return -1;
 
@@ -762,11 +754,11 @@ static int iscsi_target_locate_portal(
        login->version_min      = login_req->min_version;
        login->version_max      = login_req->max_version;
        memcpy(login->isid, login_req->isid, 6);
-       login->cmd_sn           = login_req->cmdsn;
+       login->cmd_sn           = be32_to_cpu(login_req->cmdsn);
        login->init_task_tag    = login_req->itt;
-       login->initial_exp_statsn = login_req->exp_statsn;
-       login->cid              = login_req->cid;
-       login->tsih             = login_req->tsih;
+       login->initial_exp_statsn = be32_to_cpu(login_req->exp_statsn);
+       login->cid              = be16_to_cpu(login_req->cid);
+       login->tsih             = be16_to_cpu(login_req->tsih);
 
        if (iscsi_target_get_initial_payload(conn, login) < 0)
                return -1;
@@ -1000,7 +992,6 @@ struct iscsi_login *iscsi_target_init_negotiation(
         *      Locates Target Portal from NP -> Target IQN
         */
        if (iscsi_target_locate_portal(np, conn, login) < 0) {
-               pr_err("iSCSI Login negotiation failed.\n");
                goto out;
        }
 
index 240f7aa76ed1cfd962c6a16fd7eed27701023ee5..90b740048f26ee7151eda956b092e12fad74e70c 100644 (file)
@@ -334,6 +334,13 @@ int iscsi_create_default_params(struct iscsi_param_list **param_list_ptr)
        if (!param)
                goto out;
 
+       param = iscsi_set_default_param(pl, MAXXMITDATASEGMENTLENGTH,
+                       INITIAL_MAXXMITDATASEGMENTLENGTH,
+                       PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
+                       TYPERANGE_512_TO_16777215, USE_ALL);
+       if (!param)
+               goto out;
+
        param = iscsi_set_default_param(pl, MAXRECVDATASEGMENTLENGTH,
                        INITIAL_MAXRECVDATASEGMENTLENGTH,
                        PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
@@ -467,6 +474,8 @@ int iscsi_set_keys_to_negotiate(
                        SET_PSTATE_NEGOTIATE(param);
                } else if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) {
                        SET_PSTATE_NEGOTIATE(param);
+               } else if (!strcmp(param->name, MAXXMITDATASEGMENTLENGTH)) {
+                       continue;
                } else if (!strcmp(param->name, MAXBURSTLENGTH)) {
                        SET_PSTATE_NEGOTIATE(param);
                } else if (!strcmp(param->name, FIRSTBURSTLENGTH)) {
@@ -1056,7 +1065,8 @@ out:
        return proposer_values;
 }
 
-static int iscsi_check_acceptor_state(struct iscsi_param *param, char *value)
+static int iscsi_check_acceptor_state(struct iscsi_param *param, char *value,
+                               struct iscsi_conn *conn)
 {
        u8 acceptor_boolean_value = 0, proposer_boolean_value = 0;
        char *negoitated_value = NULL;
@@ -1131,8 +1141,35 @@ static int iscsi_check_acceptor_state(struct iscsi_param *param, char *value)
                                return -1;
                }
 
-               if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH))
-                       SET_PSTATE_REPLY_OPTIONAL(param);
+               if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) {
+                       struct iscsi_param *param_mxdsl;
+                       unsigned long long tmp;
+                       int rc;
+
+                       rc = strict_strtoull(param->value, 0, &tmp);
+                       if (rc < 0)
+                               return -1;
+
+                       conn->conn_ops->MaxRecvDataSegmentLength = tmp;
+                       pr_debug("Saving op->MaxRecvDataSegmentLength from"
+                               " original initiator received value: %u\n",
+                               conn->conn_ops->MaxRecvDataSegmentLength);
+
+                       param_mxdsl = iscsi_find_param_from_key(
+                                               MAXXMITDATASEGMENTLENGTH,
+                                               conn->param_list);
+                       if (!param_mxdsl)
+                               return -1;
+
+                       rc = iscsi_update_param_value(param,
+                                               param_mxdsl->value);
+                       if (rc < 0)
+                               return -1;
+
+                       pr_debug("Updated %s to target MXDSL value: %s\n",
+                                       param->name, param->value);
+               }
+
        } else if (IS_TYPE_NUMBER_RANGE(param)) {
                negoitated_value = iscsi_get_value_from_number_range(
                                        param, value);
@@ -1526,8 +1563,9 @@ int iscsi_decode_text_input(
        u8 sender,
        char *textbuf,
        u32 length,
-       struct iscsi_param_list *param_list)
+       struct iscsi_conn *conn)
 {
+       struct iscsi_param_list *param_list = conn->param_list;
        char *tmpbuf, *start = NULL, *end = NULL;
 
        tmpbuf = kzalloc(length + 1, GFP_KERNEL);
@@ -1585,7 +1623,7 @@ int iscsi_decode_text_input(
                        }
                        SET_PSTATE_RESPONSE_GOT(param);
                } else {
-                       if (iscsi_check_acceptor_state(param, value) < 0) {
+                       if (iscsi_check_acceptor_state(param, value, conn) < 0) {
                                kfree(tmpbuf);
                                return -1;
                        }
@@ -1720,6 +1758,18 @@ void iscsi_set_connection_parameters(
        pr_debug("---------------------------------------------------"
                        "---------------\n");
        list_for_each_entry(param, &param_list->param_list, p_list) {
+               /*
+                * Special case to set MAXXMITDATASEGMENTLENGTH from the
+                * target requested MaxRecvDataSegmentLength, even though
+                * this key is not sent over the wire.
+                */
+               if (!strcmp(param->name, MAXXMITDATASEGMENTLENGTH)) {
+                       ops->MaxXmitDataSegmentLength =
+                               simple_strtoul(param->value, &tmpptr, 0);
+                       pr_debug("MaxXmitDataSegmentLength:     %s\n",
+                               param->value);
+               }
+
                if (!IS_PSTATE_ACCEPTOR(param) && !IS_PSTATE_PROPOSER(param))
                        continue;
                if (!strcmp(param->name, AUTHMETHOD)) {
@@ -1734,10 +1784,13 @@ void iscsi_set_connection_parameters(
                        pr_debug("DataDigest:                   %s\n",
                                param->value);
                } else if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) {
-                       ops->MaxRecvDataSegmentLength =
-                               simple_strtoul(param->value, &tmpptr, 0);
-                       pr_debug("MaxRecvDataSegmentLength:     %s\n",
-                               param->value);
+                       /*
+                        * At this point iscsi_check_acceptor_state() will have
+                        * set ops->MaxRecvDataSegmentLength from the original
+                        * initiator provided value.
+                        */
+                       pr_debug("MaxRecvDataSegmentLength:     %u\n",
+                               ops->MaxRecvDataSegmentLength);
                } else if (!strcmp(param->name, OFMARKER)) {
                        ops->OFMarker = !strcmp(param->value, YES);
                        pr_debug("OFMarker:                     %s\n",
index 6a37fd6f128500d774c4b3b9bd3979e189a8d9c8..1e1b7504a76b97a2bb5fa862c04f25383d9c9801 100644 (file)
@@ -36,7 +36,7 @@ extern void iscsi_release_param_list(struct iscsi_param_list *);
 extern struct iscsi_param *iscsi_find_param_from_key(char *, struct iscsi_param_list *);
 extern int iscsi_extract_key_value(char *, char **, char **);
 extern int iscsi_update_param_value(struct iscsi_param *, char *);
-extern int iscsi_decode_text_input(u8, u8, char *, u32, struct iscsi_param_list *);
+extern int iscsi_decode_text_input(u8, u8, char *, u32, struct iscsi_conn *);
 extern int iscsi_encode_text_output(u8, u8, char *, u32 *,
                        struct iscsi_param_list *);
 extern int iscsi_check_negotiated_keys(struct iscsi_param_list *);
@@ -70,6 +70,7 @@ extern void iscsi_set_session_parameters(struct iscsi_sess_ops *,
 #define INITIALR2T                     "InitialR2T"
 #define IMMEDIATEDATA                  "ImmediateData"
 #define MAXRECVDATASEGMENTLENGTH       "MaxRecvDataSegmentLength"
+#define MAXXMITDATASEGMENTLENGTH       "MaxXmitDataSegmentLength"
 #define MAXBURSTLENGTH                 "MaxBurstLength"
 #define FIRSTBURSTLENGTH               "FirstBurstLength"
 #define DEFAULTTIME2WAIT               "DefaultTime2Wait"
@@ -113,6 +114,10 @@ extern void iscsi_set_session_parameters(struct iscsi_sess_ops *,
 #define INITIAL_INITIALR2T                     YES
 #define INITIAL_IMMEDIATEDATA                  YES
 #define INITIAL_MAXRECVDATASEGMENTLENGTH       "8192"
+/*
+ * Match outgoing MXDSL default to incoming Open-iSCSI default
+ */
+#define INITIAL_MAXXMITDATASEGMENTLENGTH       "262144"
 #define INITIAL_MAXBURSTLENGTH                 "262144"
 #define INITIAL_FIRSTBURSTLENGTH               "65536"
 #define INITIAL_DEFAULTTIME2WAIT               "2"
index 85a306e067ba81dd693523683e93d0e5534fb49c..edb592a368ef521f9dc77f8abca20054b1a78577 100644 (file)
@@ -219,8 +219,14 @@ static void iscsit_determine_counts_for_list(
        int check_immediate = 0;
        u32 burstlength = 0, offset = 0;
        u32 unsolicited_data_length = 0;
+       u32 mdsl;
        struct iscsi_conn *conn = cmd->conn;
 
+       if (cmd->se_cmd.data_direction == DMA_TO_DEVICE)
+               mdsl = cmd->conn->conn_ops->MaxXmitDataSegmentLength;
+       else
+               mdsl = cmd->conn->conn_ops->MaxRecvDataSegmentLength;
+
        if ((bl->type == PDULIST_IMMEDIATE) ||
            (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
                check_immediate = 1;
@@ -243,14 +249,13 @@ static void iscsit_determine_counts_for_list(
                        continue;
                }
                if (unsolicited_data_length > 0) {
-                       if ((offset + conn->conn_ops->MaxRecvDataSegmentLength)
-                                       >= cmd->se_cmd.data_length) {
+                       if ((offset + mdsl) >= cmd->se_cmd.data_length) {
                                unsolicited_data_length -=
                                        (cmd->se_cmd.data_length - offset);
                                offset += (cmd->se_cmd.data_length - offset);
                                continue;
                        }
-                       if ((offset + conn->conn_ops->MaxRecvDataSegmentLength)
+                       if ((offset + mdsl)
                                        >= conn->sess->sess_ops->FirstBurstLength) {
                                unsolicited_data_length -=
                                        (conn->sess->sess_ops->FirstBurstLength -
@@ -262,17 +267,15 @@ static void iscsit_determine_counts_for_list(
                                continue;
                        }
 
-                       offset += conn->conn_ops->MaxRecvDataSegmentLength;
-                       unsolicited_data_length -=
-                               conn->conn_ops->MaxRecvDataSegmentLength;
+                       offset += mdsl;
+                       unsolicited_data_length -= mdsl;
                        continue;
                }
-               if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
-                    cmd->se_cmd.data_length) {
+               if ((offset + mdsl) >= cmd->se_cmd.data_length) {
                        offset += (cmd->se_cmd.data_length - offset);
                        continue;
                }
-               if ((burstlength + conn->conn_ops->MaxRecvDataSegmentLength) >=
+               if ((burstlength + mdsl) >=
                     conn->sess->sess_ops->MaxBurstLength) {
                        offset += (conn->sess->sess_ops->MaxBurstLength -
                                        burstlength);
@@ -281,8 +284,8 @@ static void iscsit_determine_counts_for_list(
                        continue;
                }
 
-               burstlength += conn->conn_ops->MaxRecvDataSegmentLength;
-               offset += conn->conn_ops->MaxRecvDataSegmentLength;
+               burstlength += mdsl;
+               offset += mdsl;
        }
 }
 
@@ -296,12 +299,17 @@ static int iscsit_do_build_pdu_and_seq_lists(
        struct iscsi_build_list *bl)
 {
        int check_immediate = 0, datapduinorder, datasequenceinorder;
-       u32 burstlength = 0, offset = 0, i = 0;
+       u32 burstlength = 0, offset = 0, i = 0, mdsl;
        u32 pdu_count = 0, seq_no = 0, unsolicited_data_length = 0;
        struct iscsi_conn *conn = cmd->conn;
        struct iscsi_pdu *pdu = cmd->pdu_list;
        struct iscsi_seq *seq = cmd->seq_list;
 
+       if (cmd->se_cmd.data_direction == DMA_TO_DEVICE)
+               mdsl = cmd->conn->conn_ops->MaxXmitDataSegmentLength;
+       else
+               mdsl = cmd->conn->conn_ops->MaxRecvDataSegmentLength;
+
        datapduinorder = conn->sess->sess_ops->DataPDUInOrder;
        datasequenceinorder = conn->sess->sess_ops->DataSequenceInOrder;
 
@@ -348,9 +356,7 @@ static int iscsit_do_build_pdu_and_seq_lists(
                        continue;
                }
                if (unsolicited_data_length > 0) {
-                       if ((offset +
-                            conn->conn_ops->MaxRecvDataSegmentLength) >=
-                            cmd->se_cmd.data_length) {
+                       if ((offset + mdsl) >= cmd->se_cmd.data_length) {
                                if (!datapduinorder) {
                                        pdu[i].type = PDUTYPE_UNSOLICITED;
                                        pdu[i].length =
@@ -367,8 +373,7 @@ static int iscsit_do_build_pdu_and_seq_lists(
                                offset += (cmd->se_cmd.data_length - offset);
                                continue;
                        }
-                       if ((offset +
-                            conn->conn_ops->MaxRecvDataSegmentLength) >=
+                       if ((offset + mdsl) >=
                                        conn->sess->sess_ops->FirstBurstLength) {
                                if (!datapduinorder) {
                                        pdu[i].type = PDUTYPE_UNSOLICITED;
@@ -396,17 +401,14 @@ static int iscsit_do_build_pdu_and_seq_lists(
 
                        if (!datapduinorder) {
                                pdu[i].type = PDUTYPE_UNSOLICITED;
-                               pdu[i++].length =
-                                    conn->conn_ops->MaxRecvDataSegmentLength;
+                               pdu[i++].length = mdsl;
                        }
-                       burstlength += conn->conn_ops->MaxRecvDataSegmentLength;
-                       offset += conn->conn_ops->MaxRecvDataSegmentLength;
-                       unsolicited_data_length -=
-                               conn->conn_ops->MaxRecvDataSegmentLength;
+                       burstlength += mdsl;
+                       offset += mdsl;
+                       unsolicited_data_length -= mdsl;
                        continue;
                }
-               if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
-                    cmd->se_cmd.data_length) {
+               if ((offset + mdsl) >= cmd->se_cmd.data_length) {
                        if (!datapduinorder) {
                                pdu[i].type = PDUTYPE_NORMAL;
                                pdu[i].length = (cmd->se_cmd.data_length - offset);
@@ -420,7 +422,7 @@ static int iscsit_do_build_pdu_and_seq_lists(
                        offset += (cmd->se_cmd.data_length - offset);
                        continue;
                }
-               if ((burstlength + conn->conn_ops->MaxRecvDataSegmentLength) >=
+               if ((burstlength + mdsl) >=
                     conn->sess->sess_ops->MaxBurstLength) {
                        if (!datapduinorder) {
                                pdu[i].type = PDUTYPE_NORMAL;
@@ -445,11 +447,10 @@ static int iscsit_do_build_pdu_and_seq_lists(
 
                if (!datapduinorder) {
                        pdu[i].type = PDUTYPE_NORMAL;
-                       pdu[i++].length =
-                               conn->conn_ops->MaxRecvDataSegmentLength;
+                       pdu[i++].length = mdsl;
                }
-               burstlength += conn->conn_ops->MaxRecvDataSegmentLength;
-               offset += conn->conn_ops->MaxRecvDataSegmentLength;
+               burstlength += mdsl;
+               offset += mdsl;
        }
 
        if (!datasequenceinorder) {
index f62fe123d902cd78f0bdbee14337564559ec8ec9..4a99820d063be4d07c9d14e0239486793779c837 100644 (file)
@@ -50,21 +50,20 @@ u8 iscsit_tmr_abort_task(
        if (!ref_cmd) {
                pr_err("Unable to locate RefTaskTag: 0x%08x on CID:"
                        " %hu.\n", hdr->rtt, conn->cid);
-               return ((hdr->refcmdsn >= conn->sess->exp_cmd_sn) &&
-                       (hdr->refcmdsn <= conn->sess->max_cmd_sn)) ?
+               return (be32_to_cpu(hdr->refcmdsn) >= conn->sess->exp_cmd_sn &&
+                       be32_to_cpu(hdr->refcmdsn) <= conn->sess->max_cmd_sn) ?
                        ISCSI_TMF_RSP_COMPLETE : ISCSI_TMF_RSP_NO_TASK;
        }
-       if (ref_cmd->cmd_sn != hdr->refcmdsn) {
+       if (ref_cmd->cmd_sn != be32_to_cpu(hdr->refcmdsn)) {
                pr_err("RefCmdSN 0x%08x does not equal"
                        " task's CmdSN 0x%08x. Rejecting ABORT_TASK.\n",
                        hdr->refcmdsn, ref_cmd->cmd_sn);
                return ISCSI_TMF_RSP_REJECTED;
        }
 
-       se_tmr->ref_task_tag            = hdr->rtt;
+       se_tmr->ref_task_tag            = (__force u32)hdr->rtt;
        tmr_req->ref_cmd                = ref_cmd;
-       tmr_req->ref_cmd_sn             = hdr->refcmdsn;
-       tmr_req->exp_data_sn            = hdr->exp_datasn;
+       tmr_req->exp_data_sn            = be32_to_cpu(hdr->exp_datasn);
 
        return ISCSI_TMF_RSP_COMPLETE;
 }
@@ -146,7 +145,7 @@ u8 iscsit_tmr_task_reassign(
        }
        /*
         * Temporary check to prevent connection recovery for
-        * connections with a differing MaxRecvDataSegmentLength.
+        * connections with a differing Max*DataSegmentLength.
         */
        if (cr->maxrecvdatasegmentlength !=
            conn->conn_ops->MaxRecvDataSegmentLength) {
@@ -155,6 +154,13 @@ u8 iscsit_tmr_task_reassign(
                        " TMR TASK_REASSIGN.\n");
                return ISCSI_TMF_RSP_REJECTED;
        }
+       if (cr->maxxmitdatasegmentlength !=
+           conn->conn_ops->MaxXmitDataSegmentLength) {
+               pr_err("Unable to perform connection recovery for"
+                       " differing MaxXmitDataSegmentLength, rejecting"
+                       " TMR TASK_REASSIGN.\n");
+               return ISCSI_TMF_RSP_REJECTED;
+       }
 
        ref_lun = scsilun_to_int(&hdr->lun);
        if (ref_lun != ref_cmd->se_cmd.orig_fe_lun) {
@@ -164,10 +170,9 @@ u8 iscsit_tmr_task_reassign(
                return ISCSI_TMF_RSP_REJECTED;
        }
 
-       se_tmr->ref_task_tag            = hdr->rtt;
+       se_tmr->ref_task_tag            = (__force u32)hdr->rtt;
        tmr_req->ref_cmd                = ref_cmd;
-       tmr_req->ref_cmd_sn             = hdr->refcmdsn;
-       tmr_req->exp_data_sn            = hdr->exp_datasn;
+       tmr_req->exp_data_sn            = be32_to_cpu(hdr->exp_datasn);
        tmr_req->conn_recovery          = cr;
        tmr_req->task_reassign          = 1;
        /*
@@ -455,7 +460,7 @@ static int iscsit_task_reassign_complete(
  *     Right now the only one that its really needed for is
  *     connection recovery releated TASK_REASSIGN.
  */
-extern int iscsit_tmr_post_handler(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
+int iscsit_tmr_post_handler(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
 {
        struct iscsi_tmr_req *tmr_req = cmd->tmr_req;
        struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
@@ -470,7 +475,7 @@ extern int iscsit_tmr_post_handler(struct iscsi_cmd *cmd, struct iscsi_conn *con
 /*
  *     Nothing to do here, but leave it for good measure. :-)
  */
-int iscsit_task_reassign_prepare_read(
+static int iscsit_task_reassign_prepare_read(
        struct iscsi_tmr_req *tmr_req,
        struct iscsi_conn *conn)
 {
@@ -545,7 +550,7 @@ static void iscsit_task_reassign_prepare_unsolicited_dataout(
        }
 }
 
-int iscsit_task_reassign_prepare_write(
+static int iscsit_task_reassign_prepare_write(
        struct iscsi_tmr_req *tmr_req,
        struct iscsi_conn *conn)
 {
index a38a3f8ab0d9236598b3bb7f176443c19334e7de..de9ea32b61046287eedacbc4c97c5368d5964217 100644 (file)
@@ -677,6 +677,12 @@ int iscsit_ta_generate_node_acls(
        pr_debug("iSCSI_TPG[%hu] - Generate Initiator Portal Group ACLs: %s\n",
                tpg->tpgt, (a->generate_node_acls) ? "Enabled" : "Disabled");
 
+       if (flag == 1 && a->cache_dynamic_acls == 0) {
+               pr_debug("Explicitly setting cache_dynamic_acls=1 when "
+                       "generate_node_acls=1\n");
+               a->cache_dynamic_acls = 1;
+       }
+
        return 0;
 }
 
@@ -716,6 +722,12 @@ int iscsit_ta_cache_dynamic_acls(
                return -EINVAL;
        }
 
+       if (a->generate_node_acls == 1 && flag == 0) {
+               pr_debug("Skipping cache_dynamic_acls=0 when"
+                       " generate_node_acls=1\n");
+               return 0;
+       }
+
        a->cache_dynamic_acls = flag;
        pr_debug("iSCSI_TPG[%hu] - Cache Dynamic Initiator Portal Group"
                " ACLs %s\n", tpg->tpgt, (a->cache_dynamic_acls) ?
index 977e1cf90e83e9b98eee725d82efc4032d903e04..9d881a000e42bbf3f973b8c574bcab3e259d9a69 100644 (file)
@@ -40,7 +40,7 @@ static void iscsi_add_ts_to_active_list(struct iscsi_thread_set *ts)
        spin_unlock(&active_ts_lock);
 }
 
-extern void iscsi_add_ts_to_inactive_list(struct iscsi_thread_set *ts)
+static void iscsi_add_ts_to_inactive_list(struct iscsi_thread_set *ts)
 {
        spin_lock(&inactive_ts_lock);
        list_add_tail(&ts->ts_list, &inactive_ts_list);
@@ -76,7 +76,7 @@ static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void)
        return ts;
 }
 
-extern int iscsi_allocate_thread_sets(u32 thread_pair_count)
+int iscsi_allocate_thread_sets(u32 thread_pair_count)
 {
        int allocated_thread_pair_count = 0, i, thread_id;
        struct iscsi_thread_set *ts = NULL;
@@ -140,7 +140,7 @@ extern int iscsi_allocate_thread_sets(u32 thread_pair_count)
        return allocated_thread_pair_count;
 }
 
-extern void iscsi_deallocate_thread_sets(void)
+void iscsi_deallocate_thread_sets(void)
 {
        u32 released_count = 0;
        struct iscsi_thread_set *ts = NULL;
index 26e6a95ec20315786a9046443c05fca639a31573..547d118312820d2a39ba960b11844298810190ce 100644 (file)
@@ -5,7 +5,6 @@
  * Defines for thread sets.
  */
 extern int iscsi_thread_set_force_reinstatement(struct iscsi_conn *);
-extern void iscsi_add_ts_to_inactive_list(struct iscsi_thread_set *);
 extern int iscsi_allocate_thread_sets(u32);
 extern void iscsi_deallocate_thread_sets(void);
 extern void iscsi_activate_thread_set(struct iscsi_conn *, struct iscsi_thread_set *);
index b42cdeb153df6e1075a8dcac83079d9caeec8a48..afd98ccd40ae564f8013155bf6a4d99f857f339a 100644 (file)
@@ -274,14 +274,14 @@ static inline int iscsit_check_received_cmdsn(struct iscsi_session *sess, u32 cm
 int iscsit_sequence_cmd(
        struct iscsi_conn *conn,
        struct iscsi_cmd *cmd,
-       u32 cmdsn)
+       __be32 cmdsn)
 {
        int ret;
        int cmdsn_ret;
 
        mutex_lock(&conn->sess->cmdsn_mutex);
 
-       cmdsn_ret = iscsit_check_received_cmdsn(conn->sess, cmdsn);
+       cmdsn_ret = iscsit_check_received_cmdsn(conn->sess, be32_to_cpu(cmdsn));
        switch (cmdsn_ret) {
        case CMDSN_NORMAL_OPERATION:
                ret = iscsit_execute_cmd(cmd, 0);
@@ -289,7 +289,7 @@ int iscsit_sequence_cmd(
                        iscsit_execute_ooo_cmdsns(conn->sess);
                break;
        case CMDSN_HIGHER_THAN_EXP:
-               ret = iscsit_handle_ooo_cmdsn(conn->sess, cmd, cmdsn);
+               ret = iscsit_handle_ooo_cmdsn(conn->sess, cmd, be32_to_cpu(cmdsn));
                break;
        case CMDSN_LOWER_THAN_EXP:
                cmd->i_state = ISTATE_REMOVE;
@@ -351,7 +351,7 @@ int iscsit_check_unsolicited_dataout(struct iscsi_cmd *cmd, unsigned char *buf)
 
 struct iscsi_cmd *iscsit_find_cmd_from_itt(
        struct iscsi_conn *conn,
-       u32 init_task_tag)
+       itt_t init_task_tag)
 {
        struct iscsi_cmd *cmd;
 
@@ -371,7 +371,7 @@ struct iscsi_cmd *iscsit_find_cmd_from_itt(
 
 struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(
        struct iscsi_conn *conn,
-       u32 init_task_tag,
+       itt_t init_task_tag,
        u32 length)
 {
        struct iscsi_cmd *cmd;
@@ -417,7 +417,7 @@ int iscsit_find_cmd_for_recovery(
        struct iscsi_session *sess,
        struct iscsi_cmd **cmd_ptr,
        struct iscsi_conn_recovery **cr_ptr,
-       u32 init_task_tag)
+       itt_t init_task_tag)
 {
        struct iscsi_cmd *cmd = NULL;
        struct iscsi_conn_recovery *cr;
@@ -855,7 +855,7 @@ static int iscsit_add_nopin(struct iscsi_conn *conn, int want_response)
        cmd->iscsi_opcode = ISCSI_OP_NOOP_IN;
        state = (want_response) ? ISTATE_SEND_NOPIN_WANT_RESPONSE :
                                ISTATE_SEND_NOPIN_NO_RESPONSE;
-       cmd->init_task_tag = 0xFFFFFFFF;
+       cmd->init_task_tag = RESERVED_ITT;
        spin_lock_bh(&conn->sess->ttt_lock);
        cmd->targ_xfer_tag = (want_response) ? conn->sess->targ_xfer_tag++ :
                        0xFFFFFFFF;
@@ -1222,7 +1222,7 @@ int iscsit_tx_login_rsp(struct iscsi_conn *conn, u8 status_class, u8 status_deta
        hdr->opcode             = ISCSI_OP_LOGIN_RSP;
        hdr->status_class       = status_class;
        hdr->status_detail      = status_detail;
-       hdr->itt                = cpu_to_be32(conn->login_itt);
+       hdr->itt                = conn->login_itt;
 
        iov.iov_base            = &iscsi_hdr;
        iov.iov_len             = ISCSI_HDR_LEN;
index e1c729b8a1c5bc330242272e016b56087aaea6e7..44054bd35437af3b21fbdc5422171d7d8032f76c 100644 (file)
@@ -12,14 +12,14 @@ extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t);
 extern struct iscsi_seq *iscsit_get_seq_holder_for_datain(struct iscsi_cmd *, u32);
 extern struct iscsi_seq *iscsit_get_seq_holder_for_r2t(struct iscsi_cmd *);
 extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32);
-int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, u32 cmdsn);
+int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, __be32 cmdsn);
 extern int iscsit_check_unsolicited_dataout(struct iscsi_cmd *, unsigned char *);
-extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, u32);
+extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, itt_t);
 extern struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(struct iscsi_conn *,
-                       u32, u32);
+                       itt_t, u32);
 extern struct iscsi_cmd *iscsit_find_cmd_from_ttt(struct iscsi_conn *, u32);
 extern int iscsit_find_cmd_for_recovery(struct iscsi_session *, struct iscsi_cmd **,
-                       struct iscsi_conn_recovery **, u32);
+                       struct iscsi_conn_recovery **, itt_t);
 extern void iscsit_add_cmd_to_immediate_queue(struct iscsi_cmd *, struct iscsi_conn *, u8);
 extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *);
 extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8);
index 5491c632a15ed9073fb1b02efdf6b3ac095c57f8..2d444b1ccd33231a57a6bd8f8eb57456ed8f61da 100644 (file)
@@ -166,7 +166,7 @@ static void tcm_loop_submission_work(struct work_struct *work)
        struct tcm_loop_tpg *tl_tpg;
        struct scatterlist *sgl_bidi = NULL;
        u32 sgl_bidi_count = 0;
-       int ret;
+       int rc;
 
        tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
        tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
@@ -187,12 +187,6 @@ static void tcm_loop_submission_work(struct work_struct *work)
                set_host_byte(sc, DID_ERROR);
                goto out_done;
        }
-
-       transport_init_se_cmd(se_cmd, tl_tpg->tl_se_tpg.se_tpg_tfo,
-                       tl_nexus->se_sess,
-                       scsi_bufflen(sc), sc->sc_data_direction,
-                       tcm_loop_sam_attr(sc), &tl_cmd->tl_sense_buf[0]);
-
        if (scsi_bidi_cmnd(sc)) {
                struct scsi_data_buffer *sdb = scsi_in(sc);
 
@@ -201,56 +195,16 @@ static void tcm_loop_submission_work(struct work_struct *work)
                se_cmd->se_cmd_flags |= SCF_BIDI;
 
        }
-
-       if (transport_lookup_cmd_lun(se_cmd, tl_cmd->sc->device->lun) < 0) {
-               kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
+       rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus->se_sess, sc->cmnd,
+                       &tl_cmd->tl_sense_buf[0], tl_cmd->sc->device->lun,
+                       scsi_bufflen(sc), tcm_loop_sam_attr(sc),
+                       sc->sc_data_direction, 0,
+                       scsi_sglist(sc), scsi_sg_count(sc),
+                       sgl_bidi, sgl_bidi_count);
+       if (rc < 0) {
                set_host_byte(sc, DID_NO_CONNECT);
                goto out_done;
        }
-
-       /*
-        * Because some userspace code via scsi-generic do not memset their
-        * associated read buffers, go ahead and do that here for type
-        * non-data CDBs.  Also note that this is currently guaranteed to be a
-        * single SGL for this case by target core in
-        * target_setup_cmd_from_cdb() -> transport_generic_cmd_sequencer().
-        */
-       if (!(se_cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) &&
-           se_cmd->data_direction == DMA_FROM_DEVICE) {
-               struct scatterlist *sg = scsi_sglist(sc);
-               unsigned char *buf = kmap(sg_page(sg)) + sg->offset;
-
-               if (buf != NULL) {
-                       memset(buf, 0, sg->length);
-                       kunmap(sg_page(sg));
-               }
-       }
-
-       ret = target_setup_cmd_from_cdb(se_cmd, sc->cmnd);
-       if (ret == -ENOMEM) {
-               transport_send_check_condition_and_sense(se_cmd,
-                               TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
-               transport_generic_free_cmd(se_cmd, 0);
-               return;
-       } else if (ret < 0) {
-               if (se_cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)
-                       tcm_loop_queue_status(se_cmd);
-               else
-                       transport_send_check_condition_and_sense(se_cmd,
-                                       se_cmd->scsi_sense_reason, 0);
-               transport_generic_free_cmd(se_cmd, 0);
-               return;
-       }
-
-       ret = transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc),
-                       scsi_sg_count(sc), sgl_bidi, sgl_bidi_count);
-       if (ret) {
-               transport_send_check_condition_and_sense(se_cmd,
-                                       se_cmd->scsi_sense_reason, 0);
-               transport_generic_free_cmd(se_cmd, 0);
-               return;
-       }
-       transport_handle_cdb_direct(se_cmd);
        return;
 
 out_done:
@@ -846,16 +800,6 @@ static int tcm_loop_queue_tm_rsp(struct se_cmd *se_cmd)
        return 0;
 }
 
-static u16 tcm_loop_set_fabric_sense_len(struct se_cmd *se_cmd, u32 sense_length)
-{
-       return 0;
-}
-
-static u16 tcm_loop_get_fabric_sense_len(void)
-{
-       return 0;
-}
-
 static char *tcm_loop_dump_proto_id(struct tcm_loop_hba *tl_hba)
 {
        switch (tl_hba->tl_proto_id) {
@@ -1373,8 +1317,6 @@ static int tcm_loop_register_configfs(void)
        fabric->tf_ops.queue_data_in = &tcm_loop_queue_data_in;
        fabric->tf_ops.queue_status = &tcm_loop_queue_status;
        fabric->tf_ops.queue_tm_rsp = &tcm_loop_queue_tm_rsp;
-       fabric->tf_ops.set_fabric_sense_len = &tcm_loop_set_fabric_sense_len;
-       fabric->tf_ops.get_fabric_sense_len = &tcm_loop_get_fabric_sense_len;
 
        /*
         * Setup function pointers for generic logic in target_core_fabric_configfs.c
index 39ddba584b30e9d08950bd3143c257da20c80b55..0d6d7c1f025ea11a465fff1a04c8568055214272 100644 (file)
@@ -660,8 +660,7 @@ static void session_reconnect_expired(struct sbp_session *sess)
        spin_lock_bh(&sess->lock);
        list_for_each_entry_safe(login, temp, &sess->login_list, link) {
                login->sess = NULL;
-               list_del(&login->link);
-               list_add_tail(&login->link, &login_list);
+               list_move_tail(&login->link, &login_list);
        }
        spin_unlock_bh(&sess->lock);
 
@@ -1847,16 +1846,6 @@ static int sbp_queue_tm_rsp(struct se_cmd *se_cmd)
        return 0;
 }
 
-static u16 sbp_set_fabric_sense_len(struct se_cmd *se_cmd, u32 sense_length)
-{
-       return 0;
-}
-
-static u16 sbp_get_fabric_sense_len(void)
-{
-       return 0;
-}
-
 static int sbp_check_stop_free(struct se_cmd *se_cmd)
 {
        struct sbp_target_request *req = container_of(se_cmd,
@@ -2068,7 +2057,7 @@ static int sbp_update_unit_directory(struct sbp_tport *tport)
        return ret;
 }
 
-static ssize_t sbp_parse_wwn(const char *name, u64 *wwn, int strict)
+static ssize_t sbp_parse_wwn(const char *name, u64 *wwn)
 {
        const char *cp;
        char c, nibble;
@@ -2088,7 +2077,7 @@ static ssize_t sbp_parse_wwn(const char *name, u64 *wwn, int strict)
                err = 3;
                if (isdigit(c))
                        nibble = c - '0';
-               else if (isxdigit(c) && (islower(c) || !strict))
+               else if (isxdigit(c))
                        nibble = tolower(c) - 'a' + 10;
                else
                        goto fail;
@@ -2117,7 +2106,7 @@ static struct se_node_acl *sbp_make_nodeacl(
        u64 guid = 0;
        u32 nexus_depth = 1;
 
-       if (sbp_parse_wwn(name, &guid, 1) < 0)
+       if (sbp_parse_wwn(name, &guid) < 0)
                return ERR_PTR(-EINVAL);
 
        se_nacl_new = sbp_alloc_fabric_acl(se_tpg);
@@ -2253,7 +2242,7 @@ static struct se_wwn *sbp_make_tport(
        struct sbp_tport *tport;
        u64 guid = 0;
 
-       if (sbp_parse_wwn(name, &guid, 1) < 0)
+       if (sbp_parse_wwn(name, &guid) < 0)
                return ERR_PTR(-EINVAL);
 
        tport = kzalloc(sizeof(*tport), GFP_KERNEL);
@@ -2534,8 +2523,6 @@ static struct target_core_fabric_ops sbp_ops = {
        .queue_data_in                  = sbp_queue_data_in,
        .queue_status                   = sbp_queue_status,
        .queue_tm_rsp                   = sbp_queue_tm_rsp,
-       .get_fabric_sense_len           = sbp_get_fabric_sense_len,
-       .set_fabric_sense_len           = sbp_set_fabric_sense_len,
        .check_stop_free                = sbp_check_stop_free,
 
        .fabric_make_wwn                = sbp_make_tport,
@@ -2556,9 +2543,9 @@ static int sbp_register_configfs(void)
        int ret;
 
        fabric = target_fabric_configfs_init(THIS_MODULE, "sbp");
-       if (!fabric) {
+       if (IS_ERR(fabric)) {
                pr_err("target_fabric_configfs_init() failed\n");
-               return -ENOMEM;
+               return PTR_ERR(fabric);
        }
 
        fabric->tf_ops = sbp_ops;
index 41641ba548286e9dbf33f45a02ece5b20eec0d14..9a5f9a7aecd2b9a5d7d4b6f99c6bd5023359d778 100644 (file)
@@ -344,7 +344,7 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)
                         */
                        rtpi = get_unaligned_be16(ptr + 2);
                        /*
-                        * Locate the matching relative target port identifer
+                        * Locate the matching relative target port identifier
                         * for the struct se_device storage object.
                         */
                        spin_lock(&dev->se_port_lock);
index 801efa8920464620ca8cdbc318d5c4865181c5c3..015f5be27bf6f00dab299b20b295ef71df4af3e2 100644 (file)
@@ -457,14 +457,6 @@ static int target_fabric_tf_ops_check(
                pr_err("Missing tfo->queue_tm_rsp()\n");
                return -EINVAL;
        }
-       if (!tfo->set_fabric_sense_len) {
-               pr_err("Missing tfo->set_fabric_sense_len()\n");
-               return -EINVAL;
-       }
-       if (!tfo->get_fabric_sense_len) {
-               pr_err("Missing tfo->get_fabric_sense_len()\n");
-               return -EINVAL;
-       }
        /*
         * We at least require tfo->fabric_make_wwn(), tfo->fabric_drop_wwn()
         * tfo->fabric_make_tpg() and tfo->fabric_drop_tpg() in
@@ -1208,7 +1200,7 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
                " Target Node Endpoint: %s\n", tfo->get_fabric_name(),
                tfo->tpg_get_wwn(se_tpg));
        len += sprintf(page+len, "SPC-3 Reservation: Relative Port"
-               " Identifer Tag: %hu %s Portal Group Tag: %hu"
+               " Identifier Tag: %hu %s Portal Group Tag: %hu"
                " %s Logical Unit: %u\n", lun->lun_sep->sep_rtpi,
                tfo->get_fabric_name(), tfo->tpg_get_tag(se_tpg),
                tfo->get_fabric_name(), lun->unpacked_lun);
@@ -3132,6 +3124,7 @@ static int __init target_core_init_configfs(void)
                                GFP_KERNEL);
        if (!target_cg->default_groups) {
                pr_err("Unable to allocate target_cg->default_groups\n");
+               ret = -ENOMEM;
                goto out_global;
        }
 
@@ -3147,6 +3140,7 @@ static int __init target_core_init_configfs(void)
                                GFP_KERNEL);
        if (!hba_cg->default_groups) {
                pr_err("Unable to allocate hba_cg->default_groups\n");
+               ret = -ENOMEM;
                goto out_global;
        }
        config_group_init_type_name(&alua_group,
@@ -3162,6 +3156,7 @@ static int __init target_core_init_configfs(void)
                        GFP_KERNEL);
        if (!alua_cg->default_groups) {
                pr_err("Unable to allocate alua_cg->default_groups\n");
+               ret = -ENOMEM;
                goto out_global;
        }
 
@@ -3173,14 +3168,17 @@ static int __init target_core_init_configfs(void)
         * Add core/alua/lu_gps/default_lu_gp
         */
        lu_gp = core_alua_allocate_lu_gp("default_lu_gp", 1);
-       if (IS_ERR(lu_gp))
+       if (IS_ERR(lu_gp)) {
+               ret = -ENOMEM;
                goto out_global;
+       }
 
        lu_gp_cg = &alua_lu_gps_group;
        lu_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
                        GFP_KERNEL);
        if (!lu_gp_cg->default_groups) {
                pr_err("Unable to allocate lu_gp_cg->default_groups\n");
+               ret = -ENOMEM;
                goto out_global;
        }
 
index 9fc9a6006ca082076a6d235dfad676e1e1a11ea9..8d774da16320707cb81f525f511188ff202c57ae 100644 (file)
@@ -531,7 +531,7 @@ static struct se_port *core_alloc_port(struct se_device *dev)
        }
 again:
        /*
-        * Allocate the next RELATIVE TARGET PORT IDENTIFER for this struct se_device
+        * Allocate the next RELATIVE TARGET PORT IDENTIFIER for this struct se_device
         * Here is the table from spc4r17 section 7.7.3.8.
         *
         *    Table 473 -- RELATIVE TARGET PORT IDENTIFIER field
@@ -548,7 +548,7 @@ again:
 
        list_for_each_entry(port_tmp, &dev->dev_sep_list, sep_list) {
                /*
-                * Make sure RELATIVE TARGET PORT IDENTIFER is unique
+                * Make sure RELATIVE TARGET PORT IDENTIFIER is unique
                 * for 16-bit wrap..
                 */
                if (port->sep_rtpi == port_tmp->sep_rtpi)
@@ -595,7 +595,7 @@ static void core_export_port(
        }
 
        dev->dev_port_count++;
-       port->sep_index = port->sep_rtpi; /* RELATIVE TARGET PORT IDENTIFER */
+       port->sep_index = port->sep_rtpi; /* RELATIVE TARGET PORT IDENTIFIER */
 }
 
 /*
@@ -988,8 +988,9 @@ int se_dev_set_emulate_fua_write(struct se_device *dev, int flag)
                return -EINVAL;
        }
 
-       if (flag && dev->transport->fua_write_emulated == 0) {
-               pr_err("fua_write_emulated not supported\n");
+       if (flag &&
+           dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
+               pr_err("emulate_fua_write not supported for pSCSI\n");
                return -EINVAL;
        }
        dev->se_sub_dev->se_dev_attrib.emulate_fua_write = flag;
@@ -1019,8 +1020,9 @@ int se_dev_set_emulate_write_cache(struct se_device *dev, int flag)
                pr_err("Illegal value %d\n", flag);
                return -EINVAL;
        }
-       if (flag && dev->transport->write_cache_emulated == 0) {
-               pr_err("write_cache_emulated not supported\n");
+       if (flag &&
+           dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
+               pr_err("emulate_write_cache not supported for pSCSI\n");
                return -EINVAL;
        }
        dev->se_sub_dev->se_dev_attrib.emulate_write_cache = flag;
index ea479e54f5fdf3f613cfd2056dc8994b9934c4c0..bca737bb813ddc1682fe6d0f9cd8ab27c618471b 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <generated/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/init.h>
 #include <linux/fs.h>
index 283a36e464e65ee5e55e9dded0037262a8203a9a..e460d6233a0a3364a66bc55c72bb7c3cd801b6d9 100644 (file)
@@ -338,7 +338,7 @@ u32 iscsi_get_pr_transport_id_len(
         * 00b: iSCSI Initiator device TransportID format
         */
        if (pr_reg->isid_present_at_reg) {
-               len += 5; /* For ",i,0x" ASCII seperator */
+               len += 5; /* For ",i,0x" ASCII separator */
                len += 7; /* For iSCSI Initiator Session ID + Null terminator */
                *format_code = 1;
        } else
@@ -415,20 +415,20 @@ char *iscsi_parse_pr_out_transport_id(
                        *out_tid_len = (add_len + 4);
        }
        /*
-        * Check for ',i,0x' seperator between iSCSI Name and iSCSI Initiator
+        * Check for ',i,0x' separator between iSCSI Name and iSCSI Initiator
         * Session ID as defined in Table 390 - iSCSI initiator port TransportID
         * format.
         */
        if (format_code == 0x40) {
                p = strstr(&buf[4], ",i,0x");
                if (!p) {
-                       pr_err("Unable to locate \",i,0x\" seperator"
+                       pr_err("Unable to locate \",i,0x\" separator"
                                " for Initiator port identifier: %s\n",
                                &buf[4]);
                        return NULL;
                }
                *p = '\0'; /* Terminate iSCSI Name */
-               p += 5; /* Skip over ",i,0x" seperator */
+               p += 5; /* Skip over ",i,0x" separator */
 
                *port_nexus_ptr = p;
                /*
index cbb5aaf3e567f5d52f552cc940f3e9556ac8ee40..0360383dfb94c54ae56744d6a1b91172031bd8eb 100644 (file)
@@ -125,6 +125,19 @@ static struct se_device *fd_create_virtdevice(
         * of pure timestamp updates.
         */
        flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC;
+       /*
+        * Optionally allow fd_buffered_io=1 to be enabled for people
+        * who want use the fs buffer cache as an WriteCache mechanism.
+        *
+        * This means that in event of a hard failure, there is a risk
+        * of silent data-loss if the SCSI client has *not* performed a
+        * forced unit access (FUA) write, or issued SYNCHRONIZE_CACHE
+        * to write-out the entire device cache.
+        */
+       if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) {
+               pr_debug("FILEIO: Disabling O_DSYNC, using buffered FILEIO\n");
+               flags &= ~O_DSYNC;
+       }
 
        file = filp_open(fd_dev->fd_dev_name, flags, 0600);
        if (IS_ERR(file)) {
@@ -188,6 +201,12 @@ static struct se_device *fd_create_virtdevice(
        if (!dev)
                goto fail;
 
+       if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) {
+               pr_debug("FILEIO: Forcing setting of emulate_write_cache=1"
+                       " with FDBD_HAS_BUFFERED_IO_WCE\n");
+               dev->se_sub_dev->se_dev_attrib.emulate_write_cache = 1;
+       }
+
        fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++;
        fd_dev->fd_queue_depth = dev->queue_depth;
 
@@ -407,6 +426,7 @@ enum {
 static match_table_t tokens = {
        {Opt_fd_dev_name, "fd_dev_name=%s"},
        {Opt_fd_dev_size, "fd_dev_size=%s"},
+       {Opt_fd_buffered_io, "fd_buffered_io=%d"},
        {Opt_err, NULL}
 };
 
@@ -418,7 +438,7 @@ static ssize_t fd_set_configfs_dev_params(
        struct fd_dev *fd_dev = se_dev->se_dev_su_ptr;
        char *orig, *ptr, *arg_p, *opts;
        substring_t args[MAX_OPT_ARGS];
-       int ret = 0, token;
+       int ret = 0, arg, token;
 
        opts = kstrdup(page, GFP_KERNEL);
        if (!opts)
@@ -459,6 +479,19 @@ static ssize_t fd_set_configfs_dev_params(
                                        " bytes\n", fd_dev->fd_dev_size);
                        fd_dev->fbd_flags |= FBDF_HAS_SIZE;
                        break;
+               case Opt_fd_buffered_io:
+                       match_int(args, &arg);
+                       if (arg != 1) {
+                               pr_err("bogus fd_buffered_io=%d value\n", arg);
+                               ret = -EINVAL;
+                               goto out;
+                       }
+
+                       pr_debug("FILEIO: Using buffered I/O"
+                               " operations for struct fd_dev\n");
+
+                       fd_dev->fbd_flags |= FDBD_HAS_BUFFERED_IO_WCE;
+                       break;
                default:
                        break;
                }
@@ -490,8 +523,10 @@ static ssize_t fd_show_configfs_dev_params(
        ssize_t bl = 0;
 
        bl = sprintf(b + bl, "TCM FILEIO ID: %u", fd_dev->fd_dev_id);
-       bl += sprintf(b + bl, "        File: %s  Size: %llu  Mode: O_DSYNC\n",
-               fd_dev->fd_dev_name, fd_dev->fd_dev_size);
+       bl += sprintf(b + bl, "        File: %s  Size: %llu  Mode: %s\n",
+               fd_dev->fd_dev_name, fd_dev->fd_dev_size,
+               (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) ?
+               "Buffered-WCE" : "O_DSYNC");
        return bl;
 }
 
@@ -546,8 +581,6 @@ static struct se_subsystem_api fileio_template = {
        .name                   = "fileio",
        .owner                  = THIS_MODULE,
        .transport_type         = TRANSPORT_PLUGIN_VHBA_PDEV,
-       .write_cache_emulated   = 1,
-       .fua_write_emulated     = 1,
        .attach_hba             = fd_attach_hba,
        .detach_hba             = fd_detach_hba,
        .allocate_virtdevice    = fd_allocate_virtdevice,
index 70ce7fd7111dd81da3cd1b4d89f5eff822889c8a..876ae53ef5b8bcd42824e976ca91a8881ee9696e 100644 (file)
@@ -14,6 +14,7 @@
 
 #define FBDF_HAS_PATH          0x01
 #define FBDF_HAS_SIZE          0x02
+#define FDBD_HAS_BUFFERED_IO_WCE 0x04
 
 struct fd_dev {
        u32             fbd_flags;
index 9ba495477fd24f80bf6643cfae3707525b7c165e..57d7674c50133c67430019efb98966b6013fa9e3 100644 (file)
@@ -454,14 +454,11 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba,
                                ret = -EEXIST;
                                goto out;
                        }
-                       arg_p = match_strdup(&args[0]);
-                       if (!arg_p) {
-                               ret = -ENOMEM;
+                       if (match_strlcpy(ib_dev->ibd_udev_path, &args[0],
+                               SE_UDEV_PATH_LEN) == 0) {
+                               ret = -EINVAL;
                                break;
                        }
-                       snprintf(ib_dev->ibd_udev_path, SE_UDEV_PATH_LEN,
-                                       "%s", arg_p);
-                       kfree(arg_p);
                        pr_debug("IBLOCK: Referencing UDEV path: %s\n",
                                        ib_dev->ibd_udev_path);
                        ib_dev->ibd_flags |= IBDF_HAS_UDEV_PATH;
@@ -556,14 +553,6 @@ static void iblock_complete_cmd(struct se_cmd *cmd)
        kfree(ibr);
 }
 
-static void iblock_bio_destructor(struct bio *bio)
-{
-       struct se_cmd *cmd = bio->bi_private;
-       struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr;
-
-       bio_free(bio, ib_dev->ibd_bio_set);
-}
-
 static struct bio *
 iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num)
 {
@@ -585,7 +574,6 @@ iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num)
 
        bio->bi_bdev = ib_dev->ibd_bd;
        bio->bi_private = cmd;
-       bio->bi_destructor = iblock_bio_destructor;
        bio->bi_end_io = &iblock_bio_done;
        bio->bi_sector = lba;
        return bio;
@@ -657,6 +645,12 @@ static int iblock_execute_rw(struct se_cmd *cmd)
                goto fail;
        cmd->priv = ibr;
 
+       if (!sgl_nents) {
+               atomic_set(&ibr->pending, 1);
+               iblock_complete_cmd(cmd);
+               return 0;
+       }
+
        bio = iblock_get_bio(cmd, block_lba, sgl_nents);
        if (!bio)
                goto fail_free_ibr;
@@ -769,8 +763,6 @@ static struct se_subsystem_api iblock_template = {
        .name                   = "iblock",
        .owner                  = THIS_MODULE,
        .transport_type         = TRANSPORT_PLUGIN_VHBA_PDEV,
-       .write_cache_emulated   = 1,
-       .fua_write_emulated     = 1,
        .attach_hba             = iblock_attach_hba,
        .detach_hba             = iblock_detach_hba,
        .allocate_virtdevice    = iblock_allocate_virtdevice,
index 956c84c6b666498caabf7b60b7404413698c0b14..8c323a98c4a02bbf7773384f87b885b737d1124a 100644 (file)
@@ -197,10 +197,10 @@ int target_scsi2_reservation_release(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
        struct se_session *sess = cmd->se_sess;
-       struct se_portal_group *tpg = sess->se_tpg;
+       struct se_portal_group *tpg;
        int ret = 0, rc;
 
-       if (!sess || !tpg)
+       if (!sess || !sess->se_tpg)
                goto out;
        rc = target_check_scsi2_reservation_conflict(cmd);
        if (rc == 1)
@@ -228,6 +228,7 @@ int target_scsi2_reservation_release(struct se_cmd *cmd)
                dev->dev_res_bin_isid = 0;
                dev->dev_flags &= ~DF_SPC2_RESERVATIONS_WITH_ISID;
        }
+       tpg = sess->se_tpg;
        pr_debug("SCSI-2 Released reservation for %s LUN: %u ->"
                " MAPPED LUN: %u for %s\n", tpg->se_tpg_tfo->get_fabric_name(),
                cmd->se_lun->unpacked_lun, cmd->se_deve->mapped_lun,
@@ -245,7 +246,7 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
        struct se_session *sess = cmd->se_sess;
-       struct se_portal_group *tpg = sess->se_tpg;
+       struct se_portal_group *tpg;
        int ret = 0, rc;
 
        if ((cmd->t_task_cdb[1] & 0x01) &&
@@ -260,7 +261,7 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd)
         * This is currently the case for target_core_mod passthrough struct se_cmd
         * ops
         */
-       if (!sess || !tpg)
+       if (!sess || !sess->se_tpg)
                goto out;
        rc = target_check_scsi2_reservation_conflict(cmd);
        if (rc == 1)
@@ -272,6 +273,7 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd)
        }
 
        ret = 0;
+       tpg = sess->se_tpg;
        spin_lock(&dev->dev_reservation_lock);
        if (dev->dev_reserved_node_acl &&
           (dev->dev_reserved_node_acl != sess->se_node_acl)) {
@@ -1620,7 +1622,7 @@ static int core_scsi3_decode_spec_i_port(
                                goto out;
                        }
                        /*
-                        * Locate the desination initiator ACL to be registered
+                        * Locate the destination initiator ACL to be registered
                         * from the decoded fabric module specific TransportID
                         * at *i_str.
                         */
@@ -4257,7 +4259,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
                        buf[off++] = ((port->sep_rtpi >> 8) & 0xff);
                        buf[off++] = (port->sep_rtpi & 0xff);
                } else
-                       off += 2; /* Skip over RELATIVE TARGET PORT IDENTIFER */
+                       off += 2; /* Skip over RELATIVE TARGET PORT IDENTIFIER */
 
                /*
                 * Now, have the $FABRIC_MOD fill in the protocol identifier
index 9d7ce3daa26275a7c08b831ae9b955382e0e9103..617c086a8a023c84cbaa9e815602bc4123215f04 100644 (file)
@@ -264,7 +264,7 @@ pscsi_get_inquiry_vpd_device_ident(struct scsi_device *sdev,
                                        " length zero!\n");
                        break;
                }
-               pr_debug("T10 VPD Identifer Length: %d\n", ident_len);
+               pr_debug("T10 VPD Identifier Length: %d\n", ident_len);
 
                vpd = kzalloc(sizeof(struct t10_vpd), GFP_KERNEL);
                if (!vpd) {
index a9dd9469e3bd4ef9af3b3fa334e54f513d60a316..868f8aa04f13d318b1c752d08887703f7a72de21 100644 (file)
@@ -40,8 +40,9 @@
 static int sbc_emulate_readcapacity(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
-       unsigned char *buf;
        unsigned long long blocks_long = dev->transport->get_blocks(dev);
+       unsigned char *rbuf;
+       unsigned char buf[8];
        u32 blocks;
 
        if (blocks_long >= 0x00000000ffffffff)
@@ -49,8 +50,6 @@ static int sbc_emulate_readcapacity(struct se_cmd *cmd)
        else
                blocks = (u32)blocks_long;
 
-       buf = transport_kmap_data_sg(cmd);
-
        buf[0] = (blocks >> 24) & 0xff;
        buf[1] = (blocks >> 16) & 0xff;
        buf[2] = (blocks >> 8) & 0xff;
@@ -60,7 +59,11 @@ static int sbc_emulate_readcapacity(struct se_cmd *cmd)
        buf[6] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff;
        buf[7] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff;
 
-       transport_kunmap_data_sg(cmd);
+       rbuf = transport_kmap_data_sg(cmd);
+       if (rbuf) {
+               memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+               transport_kunmap_data_sg(cmd);
+       }
 
        target_complete_cmd(cmd, GOOD);
        return 0;
@@ -69,11 +72,11 @@ static int sbc_emulate_readcapacity(struct se_cmd *cmd)
 static int sbc_emulate_readcapacity_16(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
-       unsigned char *buf;
+       unsigned char *rbuf;
+       unsigned char buf[32];
        unsigned long long blocks = dev->transport->get_blocks(dev);
 
-       buf = transport_kmap_data_sg(cmd);
-
+       memset(buf, 0, sizeof(buf));
        buf[0] = (blocks >> 56) & 0xff;
        buf[1] = (blocks >> 48) & 0xff;
        buf[2] = (blocks >> 40) & 0xff;
@@ -93,7 +96,11 @@ static int sbc_emulate_readcapacity_16(struct se_cmd *cmd)
        if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
                buf[14] = 0x80;
 
-       transport_kunmap_data_sg(cmd);
+       rbuf = transport_kmap_data_sg(cmd);
+       if (rbuf) {
+               memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+               transport_kunmap_data_sg(cmd);
+       }
 
        target_complete_cmd(cmd, GOOD);
        return 0;
index 388a922c8f6de8f4f2a18f7bea85f5b3590b41a9..9229bd9ad61b3db7cd4d182ab3d5315f24785a5f 100644 (file)
@@ -600,30 +600,11 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
        struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg;
-       unsigned char *buf, *map_buf;
+       unsigned char *rbuf;
        unsigned char *cdb = cmd->t_task_cdb;
+       unsigned char buf[SE_INQUIRY_BUF];
        int p, ret;
 
-       map_buf = transport_kmap_data_sg(cmd);
-       /*
-        * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we
-        * know we actually allocated a full page.  Otherwise, if the
-        * data buffer is too small, allocate a temporary buffer so we
-        * don't have to worry about overruns in all our INQUIRY
-        * emulation handling.
-        */
-       if (cmd->data_length < SE_INQUIRY_BUF &&
-           (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) {
-               buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL);
-               if (!buf) {
-                       transport_kunmap_data_sg(cmd);
-                       cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-                       return -ENOMEM;
-               }
-       } else {
-               buf = map_buf;
-       }
-
        if (dev == tpg->tpg_virt_lun0.lun_se_dev)
                buf[0] = 0x3f; /* Not connected */
        else
@@ -655,11 +636,11 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)
        ret = -EINVAL;
 
 out:
-       if (buf != map_buf) {
-               memcpy(map_buf, buf, cmd->data_length);
-               kfree(buf);
+       rbuf = transport_kmap_data_sg(cmd);
+       if (rbuf) {
+               memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+               transport_kunmap_data_sg(cmd);
        }
-       transport_kunmap_data_sg(cmd);
 
        if (!ret)
                target_complete_cmd(cmd, GOOD);
@@ -803,7 +784,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
        unsigned char *rbuf;
        int type = dev->transport->get_device_type(dev);
        int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10);
-       int offset = ten ? 8 : 4;
+       u32 offset = ten ? 8 : 4;
        int length = 0;
        unsigned char buf[SE_MODE_PAGE_BUF];
 
@@ -836,6 +817,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
                offset -= 2;
                buf[0] = (offset >> 8) & 0xff;
                buf[1] = offset & 0xff;
+               offset += 2;
 
                if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
                    (cmd->se_deve &&
@@ -845,13 +827,10 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
                if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
                    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
                        spc_modesense_dpofua(&buf[3], type);
-
-               if ((offset + 2) > cmd->data_length)
-                       offset = cmd->data_length;
-
        } else {
                offset -= 1;
                buf[0] = offset & 0xff;
+               offset += 1;
 
                if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
                    (cmd->se_deve &&
@@ -861,14 +840,13 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
                if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
                    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
                        spc_modesense_dpofua(&buf[2], type);
-
-               if ((offset + 1) > cmd->data_length)
-                       offset = cmd->data_length;
        }
 
        rbuf = transport_kmap_data_sg(cmd);
-       memcpy(rbuf, buf, offset);
-       transport_kunmap_data_sg(cmd);
+       if (rbuf) {
+               memcpy(rbuf, buf, min(offset, cmd->data_length));
+               transport_kunmap_data_sg(cmd);
+       }
 
        target_complete_cmd(cmd, GOOD);
        return 0;
index 3d44beb0cf1f84d712562ea6cc7d46aedbf80972..cb6b0036ae953ad16891115a04b7ceeb63392c87 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/delay.h>
 #include <linux/timer.h>
 #include <linux/string.h>
-#include <generated/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
index b8628a5014b9ecb45151e52496845a33be06bfc2..a531fe282b1e4868b2286e3c7d842061636c9be8 100644 (file)
@@ -303,7 +303,7 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
        }
        /*
         * Here we only create demo-mode MappedLUNs from the active
-        * TPG LUNs if the fabric is not explictly asking for
+        * TPG LUNs if the fabric is not explicitly asking for
         * tpg_check_demo_mode_login_only() == 1.
         */
        if ((tpg->se_tpg_tfo->tpg_check_demo_mode_login_only == NULL) ||
index 269f54488397bd2193bb80869bf9de8ac4c73bf2..c33baff86aa699deacd04bd873e3c31fa5569cf5 100644 (file)
@@ -55,8 +55,6 @@
 #include "target_core_pr.h"
 #include "target_core_ua.h"
 
-static int sub_api_initialized;
-
 static struct workqueue_struct *target_completion_wq;
 static struct kmem_cache *se_sess_cache;
 struct kmem_cache *se_ua_cache;
@@ -195,6 +193,7 @@ u32 scsi_get_new_index(scsi_index_t type)
 void transport_subsystem_check_init(void)
 {
        int ret;
+       static int sub_api_initialized;
 
        if (sub_api_initialized)
                return;
@@ -211,12 +210,7 @@ void transport_subsystem_check_init(void)
        if (ret != 0)
                pr_err("Unable to load target_core_pscsi\n");
 
-       ret = request_module("target_core_stgt");
-       if (ret != 0)
-               pr_err("Unable to load target_core_stgt\n");
-
        sub_api_initialized = 1;
-       return;
 }
 
 struct se_session *transport_init_session(void)
@@ -573,9 +567,7 @@ static void target_complete_failure_work(struct work_struct *work)
  */
 static unsigned char *transport_get_sense_buffer(struct se_cmd *cmd)
 {
-       unsigned char *buffer = cmd->sense_buffer;
        struct se_device *dev = cmd->se_dev;
-       u32 offset = 0;
 
        WARN_ON(!cmd->se_lun);
 
@@ -585,14 +577,11 @@ static unsigned char *transport_get_sense_buffer(struct se_cmd *cmd)
        if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION)
                return NULL;
 
-       offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER);
-
-       /* Automatically padded */
-       cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset;
+       cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER;
 
        pr_debug("HBA_[%u]_PLUG[%s]: Requesting sense for SAM STATUS: 0x%02x\n",
                dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status);
-       return &buffer[offset];
+       return cmd->sense_buffer;
 }
 
 void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
@@ -969,7 +958,7 @@ int
 transport_set_vpd_ident(struct t10_vpd *vpd, unsigned char *page_83)
 {
        static const char hex_str[] = "0123456789abcdef";
-       int j = 0, i = 4; /* offset to start of the identifer */
+       int j = 0, i = 4; /* offset to start of the identifier */
 
        /*
         * The VPD Code Set (encoding)
@@ -1466,8 +1455,9 @@ int transport_handle_cdb_direct(
 }
 EXPORT_SYMBOL(transport_handle_cdb_direct);
 
-/**
- * target_submit_cmd - lookup unpacked lun and submit uninitialized se_cmd
+/*
+ * target_submit_cmd_map_sgls - lookup unpacked lun and submit uninitialized
+ *                      se_cmd + use pre-allocated SGL memory.
  *
  * @se_cmd: command descriptor to submit
  * @se_sess: associated se_sess for endpoint
@@ -1478,6 +1468,10 @@ EXPORT_SYMBOL(transport_handle_cdb_direct);
  * @task_addr: SAM task attribute
  * @data_dir: DMA data direction
  * @flags: flags for command submission from target_sc_flags_tables
+ * @sgl: struct scatterlist memory for unidirectional mapping
+ * @sgl_count: scatterlist count for unidirectional mapping
+ * @sgl_bidi: struct scatterlist memory for bidirectional READ mapping
+ * @sgl_bidi_count: scatterlist count for bidirectional READ mapping
  *
  * Returns non zero to signal active I/O shutdown failure.  All other
  * setup exceptions will be returned as a SCSI CHECK_CONDITION response,
@@ -1485,10 +1479,12 @@ EXPORT_SYMBOL(transport_handle_cdb_direct);
  *
  * This may only be called from process context, and also currently
  * assumes internal allocation of fabric payload buffer by target-core.
- **/
-int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
+ */
+int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess,
                unsigned char *cdb, unsigned char *sense, u32 unpacked_lun,
-               u32 data_length, int task_attr, int data_dir, int flags)
+               u32 data_length, int task_attr, int data_dir, int flags,
+               struct scatterlist *sgl, u32 sgl_count,
+               struct scatterlist *sgl_bidi, u32 sgl_bidi_count)
 {
        struct se_portal_group *se_tpg;
        int rc;
@@ -1535,7 +1531,42 @@ int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
                transport_generic_request_failure(se_cmd);
                return 0;
        }
+       /*
+        * When a non zero sgl_count has been passed perform SGL passthrough
+        * mapping for pre-allocated fabric memory instead of having target
+        * core perform an internal SGL allocation..
+        */
+       if (sgl_count != 0) {
+               BUG_ON(!sgl);
+
+               /*
+                * A work-around for tcm_loop as some userspace code via
+                * scsi-generic do not memset their associated read buffers,
+                * so go ahead and do that here for type non-data CDBs.  Also
+                * note that this is currently guaranteed to be a single SGL
+                * for this case by target core in target_setup_cmd_from_cdb()
+                * -> transport_generic_cmd_sequencer().
+                */
+               if (!(se_cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) &&
+                    se_cmd->data_direction == DMA_FROM_DEVICE) {
+                       unsigned char *buf = NULL;
+
+                       if (sgl)
+                               buf = kmap(sg_page(sgl)) + sgl->offset;
+
+                       if (buf) {
+                               memset(buf, 0, sgl->length);
+                               kunmap(sg_page(sgl));
+                       }
+               }
 
+               rc = transport_generic_map_mem_to_cmd(se_cmd, sgl, sgl_count,
+                               sgl_bidi, sgl_bidi_count);
+               if (rc != 0) {
+                       transport_generic_request_failure(se_cmd);
+                       return 0;
+               }
+       }
        /*
         * Check if we need to delay processing because of ALUA
         * Active/NonOptimized primary access state..
@@ -1545,6 +1576,38 @@ int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
        transport_handle_cdb_direct(se_cmd);
        return 0;
 }
+EXPORT_SYMBOL(target_submit_cmd_map_sgls);
+
+/*
+ * target_submit_cmd - lookup unpacked lun and submit uninitialized se_cmd
+ *
+ * @se_cmd: command descriptor to submit
+ * @se_sess: associated se_sess for endpoint
+ * @cdb: pointer to SCSI CDB
+ * @sense: pointer to SCSI sense buffer
+ * @unpacked_lun: unpacked LUN to reference for struct se_lun
+ * @data_length: fabric expected data transfer length
+ * @task_addr: SAM task attribute
+ * @data_dir: DMA data direction
+ * @flags: flags for command submission from target_sc_flags_tables
+ *
+ * Returns non zero to signal active I/O shutdown failure.  All other
+ * setup exceptions will be returned as a SCSI CHECK_CONDITION response,
+ * but still return zero here.
+ *
+ * This may only be called from process context, and also currently
+ * assumes internal allocation of fabric payload buffer by target-core.
+ *
+ * It also assumes interal target core SGL memory allocation.
+ */
+int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
+               unsigned char *cdb, unsigned char *sense, u32 unpacked_lun,
+               u32 data_length, int task_attr, int data_dir, int flags)
+{
+       return target_submit_cmd_map_sgls(se_cmd, se_sess, cdb, sense,
+                       unpacked_lun, data_length, task_attr, data_dir,
+                       flags, NULL, 0, NULL, 0);
+}
 EXPORT_SYMBOL(target_submit_cmd);
 
 static void target_complete_tmr_failure(struct work_struct *work)
@@ -2300,23 +2363,6 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
                if (ret < 0)
                        goto out_fail;
        }
-       /*
-        * If this command doesn't have any payload and we don't have to call
-        * into the fabric for data transfers, go ahead and complete it right
-        * away.
-        */
-       if (!cmd->data_length &&
-           cmd->t_task_cdb[0] != REQUEST_SENSE &&
-           cmd->se_dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) {
-               spin_lock_irq(&cmd->t_state_lock);
-               cmd->t_state = TRANSPORT_COMPLETE;
-               cmd->transport_state |= CMD_T_ACTIVE;
-               spin_unlock_irq(&cmd->t_state_lock);
-
-               INIT_WORK(&cmd->work, target_complete_ok_work);
-               queue_work(target_completion_wq, &cmd->work);
-               return 0;
-       }
 
        atomic_inc(&cmd->t_fe_count);
 
@@ -2771,7 +2817,7 @@ bool transport_wait_for_tasks(struct se_cmd *cmd)
        spin_lock_irqsave(&cmd->t_state_lock, flags);
        cmd->transport_state &= ~(CMD_T_ACTIVE | CMD_T_STOP);
 
-       pr_debug("wait_for_tasks: Stopped wait_for_compltion("
+       pr_debug("wait_for_tasks: Stopped wait_for_completion("
                "&cmd->t_transport_stop_comp) for ITT: 0x%08x\n",
                cmd->se_tfo->get_task_tag(cmd));
 
@@ -2810,7 +2856,6 @@ int transport_send_check_condition_and_sense(
 {
        unsigned char *buffer = cmd->sense_buffer;
        unsigned long flags;
-       int offset;
        u8 asc = 0, ascq = 0;
 
        spin_lock_irqsave(&cmd->t_state_lock, flags);
@@ -2826,14 +2871,7 @@ int transport_send_check_condition_and_sense(
 
        if (!from_transport)
                cmd->se_cmd_flags |= SCF_EMULATED_TASK_SENSE;
-       /*
-        * Data Segment and SenseLength of the fabric response PDU.
-        *
-        * TRANSPORT_SENSE_BUFFER is now set to SCSI_SENSE_BUFFERSIZE
-        * from include/scsi/scsi_cmnd.h
-        */
-       offset = cmd->se_tfo->set_fabric_sense_len(cmd,
-                               TRANSPORT_SENSE_BUFFER);
+
        /*
         * Actual SENSE DATA, see SPC-3 7.23.2  SPC_SENSE_KEY_OFFSET uses
         * SENSE KEY values from include/scsi/scsi.h
@@ -2841,151 +2879,151 @@ int transport_send_check_condition_and_sense(
        switch (reason) {
        case TCM_NON_EXISTENT_LUN:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* LOGICAL UNIT NOT SUPPORTED */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x25;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x25;
                break;
        case TCM_UNSUPPORTED_SCSI_OPCODE:
        case TCM_SECTOR_COUNT_TOO_MANY:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* INVALID COMMAND OPERATION CODE */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x20;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x20;
                break;
        case TCM_UNKNOWN_MODE_PAGE:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* INVALID FIELD IN CDB */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x24;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x24;
                break;
        case TCM_CHECK_CONDITION_ABORT_CMD:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ABORTED COMMAND */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+               buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
                /* BUS DEVICE RESET FUNCTION OCCURRED */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x29;
-               buffer[offset+SPC_ASCQ_KEY_OFFSET] = 0x03;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x29;
+               buffer[SPC_ASCQ_KEY_OFFSET] = 0x03;
                break;
        case TCM_INCORRECT_AMOUNT_OF_DATA:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ABORTED COMMAND */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+               buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
                /* WRITE ERROR */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x0c;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x0c;
                /* NOT ENOUGH UNSOLICITED DATA */
-               buffer[offset+SPC_ASCQ_KEY_OFFSET] = 0x0d;
+               buffer[SPC_ASCQ_KEY_OFFSET] = 0x0d;
                break;
        case TCM_INVALID_CDB_FIELD:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* INVALID FIELD IN CDB */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x24;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x24;
                break;
        case TCM_INVALID_PARAMETER_LIST:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* INVALID FIELD IN PARAMETER LIST */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x26;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x26;
                break;
        case TCM_UNEXPECTED_UNSOLICITED_DATA:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ABORTED COMMAND */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+               buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
                /* WRITE ERROR */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x0c;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x0c;
                /* UNEXPECTED_UNSOLICITED_DATA */
-               buffer[offset+SPC_ASCQ_KEY_OFFSET] = 0x0c;
+               buffer[SPC_ASCQ_KEY_OFFSET] = 0x0c;
                break;
        case TCM_SERVICE_CRC_ERROR:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ABORTED COMMAND */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+               buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
                /* PROTOCOL SERVICE CRC ERROR */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x47;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x47;
                /* N/A */
-               buffer[offset+SPC_ASCQ_KEY_OFFSET] = 0x05;
+               buffer[SPC_ASCQ_KEY_OFFSET] = 0x05;
                break;
        case TCM_SNACK_REJECTED:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ABORTED COMMAND */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+               buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
                /* READ ERROR */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x11;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x11;
                /* FAILED RETRANSMISSION REQUEST */
-               buffer[offset+SPC_ASCQ_KEY_OFFSET] = 0x13;
+               buffer[SPC_ASCQ_KEY_OFFSET] = 0x13;
                break;
        case TCM_WRITE_PROTECTED:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* DATA PROTECT */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = DATA_PROTECT;
+               buffer[SPC_SENSE_KEY_OFFSET] = DATA_PROTECT;
                /* WRITE PROTECTED */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x27;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x27;
                break;
        case TCM_ADDRESS_OUT_OF_RANGE:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* LOGICAL BLOCK ADDRESS OUT OF RANGE */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x21;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x21;
                break;
        case TCM_CHECK_CONDITION_UNIT_ATTENTION:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* UNIT ATTENTION */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
+               buffer[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
                core_scsi3_ua_for_check_condition(cmd, &asc, &ascq);
-               buffer[offset+SPC_ASC_KEY_OFFSET] = asc;
-               buffer[offset+SPC_ASCQ_KEY_OFFSET] = ascq;
+               buffer[SPC_ASC_KEY_OFFSET] = asc;
+               buffer[SPC_ASCQ_KEY_OFFSET] = ascq;
                break;
        case TCM_CHECK_CONDITION_NOT_READY:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* Not Ready */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = NOT_READY;
+               buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY;
                transport_get_sense_codes(cmd, &asc, &ascq);
-               buffer[offset+SPC_ASC_KEY_OFFSET] = asc;
-               buffer[offset+SPC_ASCQ_KEY_OFFSET] = ascq;
+               buffer[SPC_ASC_KEY_OFFSET] = asc;
+               buffer[SPC_ASCQ_KEY_OFFSET] = ascq;
                break;
        case TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE:
        default:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* LOGICAL UNIT COMMUNICATION FAILURE */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x80;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x80;
                break;
        }
        /*
@@ -2996,7 +3034,7 @@ int transport_send_check_condition_and_sense(
         * Automatically padded, this value is encoded in the fabric's
         * data_length response PDU containing the SCSI defined sense data.
         */
-       cmd->scsi_sense_length  = TRANSPORT_SENSE_BUFFER + offset;
+       cmd->scsi_sense_length  = TRANSPORT_SENSE_BUFFER;
 
 after_reason:
        return cmd->se_tfo->queue_status(cmd);
index 823e6922249d07e3122973ebdb370cd4994704a0..b406f178ff390663951ff4915824b67acdfe31b2 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <generated/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/init.h>
 #include <linux/slab.h>
index 9501844fae2d01fd55a7870bb8443ec13fd701ed..b74feb0d5133bee4a41a0a5c2d32fe5d36d08416 100644 (file)
@@ -495,16 +495,6 @@ static void ft_set_default_node_attr(struct se_node_acl *se_nacl)
 {
 }
 
-static u16 ft_get_fabric_sense_len(void)
-{
-       return 0;
-}
-
-static u16 ft_set_fabric_sense_len(struct se_cmd *se_cmd, u32 sense_len)
-{
-       return 0;
-}
-
 static u32 ft_tpg_get_inst_index(struct se_portal_group *se_tpg)
 {
        struct ft_tpg *tpg = se_tpg->se_tpg_fabric_ptr;
@@ -542,8 +532,6 @@ static struct target_core_fabric_ops ft_fabric_ops = {
        .queue_data_in =                ft_queue_data_in,
        .queue_status =                 ft_queue_status,
        .queue_tm_rsp =                 ft_queue_tm_resp,
-       .get_fabric_sense_len =         ft_get_fabric_sense_len,
-       .set_fabric_sense_len =         ft_set_fabric_sense_len,
        /*
         * Setup function pointers for generic logic in
         * target_core_fabric_configfs.c
index ad36ede1a1eab12b907964ca8c446262d2918528..b6fd4cf428401a17f32c193f8c5633e216d7a669 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <generated/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -328,11 +327,12 @@ drop:
  */
 void ft_invl_hw_context(struct ft_cmd *cmd)
 {
-       struct fc_seq *seq = cmd->seq;
+       struct fc_seq *seq;
        struct fc_exch *ep = NULL;
        struct fc_lport *lport = NULL;
 
        BUG_ON(!cmd);
+       seq = cmd->seq;
 
        /* Cleanup the DDP context in HW if DDP was setup */
        if (cmd->was_ddp_setup && seq) {
index 3c9e5b57caabea23567192e2d2f85843ca6bc70f..9585010964ecad04727a4561d925ac55a9412c6b 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <generated/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/init.h>
 #include <linux/slab.h>
index 2944ff88fdc0b2ea9705850e080a755aca440a8d..f4abfe238f98cb6bb6a4c53607bd4adf2a447ebc 100644 (file)
@@ -478,7 +478,6 @@ static void xencons_backend_changed(struct xenbus_device *dev,
        case XenbusStateInitialising:
        case XenbusStateInitialised:
        case XenbusStateUnknown:
-       case XenbusStateClosed:
                break;
 
        case XenbusStateInitWait:
@@ -488,6 +487,10 @@ static void xencons_backend_changed(struct xenbus_device *dev,
                xenbus_switch_state(dev, XenbusStateConnected);
                break;
 
+       case XenbusStateClosed:
+               if (dev->state == XenbusStateClosed)
+                       break;
+               /* Missed the backend's CLOSING state -- fallthrough */
        case XenbusStateClosing:
                xenbus_frontend_closed(dev);
                break;
index c0b334327d9313e71b099b2ff0667671be417c50..10020547c60b5735d4cbf667956c911aa06a1030 100644 (file)
@@ -97,7 +97,8 @@ static void kgdboc_restore_input(void)
 
 static int kgdboc_register_kbd(char **cptr)
 {
-       if (strncmp(*cptr, "kbd", 3) == 0) {
+       if (strncmp(*cptr, "kbd", 3) == 0 ||
+               strncmp(*cptr, "kdb", 3) == 0) {
                if (kdb_poll_idx < KDB_POLL_FUNC_MAX) {
                        kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char;
                        kdb_poll_idx++;
index 999ca63afdeffc2c03a0d5a057d57653f3b85490..f87d7e8964bf0849c1ab3e3da327e3a14c9b35a2 100644 (file)
@@ -3442,6 +3442,19 @@ int con_debug_enter(struct vc_data *vc)
                        kdb_set(2, setargs);
                }
        }
+       if (vc->vc_cols < 999) {
+               int colcount;
+               char cols[4];
+               const char *setargs[3] = {
+                       "set",
+                       "COLUMNS",
+                       cols,
+               };
+               if (kdbgetintenv(setargs[0], &colcount)) {
+                       snprintf(cols, 4, "%i", vc->vc_cols);
+                       kdb_set(2, setargs);
+               }
+       }
 #endif /* CONFIG_KGDB_KDB */
        return ret;
 }
index 36f2be4def2f29ffd0df8fe9bbdd8a3a8695fd18..981f2132d1283c44234f4fa79466c4d11241c94e 100644 (file)
@@ -1551,6 +1551,9 @@ static const struct usb_device_id acm_ids[] = {
                                           Maybe we should define a new
                                           quirk for this. */
        },
+       { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */
+       .driver_info = NO_UNION_NORMAL,
+       },
        { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */
        .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
        },
index eaa1005377fc58ff9304ced98db1169823d8d81d..97e68b38cfdf5ebab332f1ae0f670ed7b7edc56b 100644 (file)
@@ -1472,16 +1472,6 @@ static int usbg_queue_tm_rsp(struct se_cmd *se_cmd)
        return 0;
 }
 
-static u16 usbg_set_fabric_sense_len(struct se_cmd *se_cmd, u32 sense_length)
-{
-       return 0;
-}
-
-static u16 usbg_get_fabric_sense_len(void)
-{
-       return 0;
-}
-
 static const char *usbg_check_wwn(const char *name)
 {
        const char *n;
@@ -1822,7 +1812,7 @@ static ssize_t tcm_usbg_tpg_store_nexus(
                ret = tcm_usbg_drop_nexus(tpg);
                return (!ret) ? count : ret;
        }
-       if (strlen(page) > USBG_NAMELEN) {
+       if (strlen(page) >= USBG_NAMELEN) {
                pr_err("Emulated NAA Sas Address: %s, exceeds"
                                " max: %d\n", page, USBG_NAMELEN);
                return -EINVAL;
@@ -1907,8 +1897,6 @@ static struct target_core_fabric_ops usbg_ops = {
        .queue_data_in                  = usbg_send_read_response,
        .queue_status                   = usbg_send_status_response,
        .queue_tm_rsp                   = usbg_queue_tm_rsp,
-       .get_fabric_sense_len           = usbg_get_fabric_sense_len,
-       .set_fabric_sense_len           = usbg_set_fabric_sense_len,
        .check_stop_free                = usbg_check_stop_free,
 
        .fabric_make_wwn                = usbg_make_tport,
@@ -1968,7 +1956,6 @@ static void usbg_deregister_configfs(void)
 static struct usb_interface_descriptor bot_intf_desc = {
        .bLength =              sizeof(bot_intf_desc),
        .bDescriptorType =      USB_DT_INTERFACE,
-       .bAlternateSetting =    0,
        .bNumEndpoints =        2,
        .bAlternateSetting =    USB_G_ALT_INT_BBB,
        .bInterfaceClass =      USB_CLASS_MASS_STORAGE,
index 6d369fe9d30bef6abb0dae1db22e55ec181d9e92..6c119944bbb6e8c03f7e15424494b17d4fbdd5db 100644 (file)
@@ -408,7 +408,7 @@ static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma)
        struct vfio_pci_device *vdev = device_data;
        struct pci_dev *pdev = vdev->pdev;
        unsigned int index;
-       u64 phys_len, req_len, pgoff, req_start, phys;
+       u64 phys_len, req_len, pgoff, req_start;
        int ret;
 
        index = vma->vm_pgoff >> (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT);
@@ -463,10 +463,9 @@ static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma)
        vma->vm_private_data = vdev;
        vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+       vma->vm_pgoff = (pci_resource_start(pdev, index) >> PAGE_SHIFT) + pgoff;
 
-       phys = (pci_resource_start(pdev, index) >> PAGE_SHIFT) + pgoff;
-
-       return remap_pfn_range(vma, vma->vm_start, phys,
+       return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
                               req_len, vma->vm_page_prot);
 }
 
index d8dedc7d3910c7bdc362dac6e099326642f0f1fb..3639371fa697e63e9bf6d3e5ccc49453e5ecff76 100644 (file)
@@ -366,6 +366,17 @@ static int vfio_intx_enable(struct vfio_pci_device *vdev)
                return -ENOMEM;
 
        vdev->num_ctx = 1;
+
+       /*
+        * If the virtual interrupt is masked, restore it.  Devices
+        * supporting DisINTx can be masked at the hardware level
+        * here, non-PCI-2.3 devices will have to wait until the
+        * interrupt is enabled.
+        */
+       vdev->ctx[0].masked = vdev->virq_disabled;
+       if (vdev->pci_2_3)
+               pci_intx(vdev->pdev, !vdev->ctx[0].masked);
+
        vdev->irq_type = VFIO_PCI_INTX_IRQ_INDEX;
 
        return 0;
@@ -400,25 +411,26 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd)
                return PTR_ERR(trigger);
        }
 
+       vdev->ctx[0].trigger = trigger;
+
        if (!vdev->pci_2_3)
                irqflags = 0;
 
        ret = request_irq(pdev->irq, vfio_intx_handler,
                          irqflags, vdev->ctx[0].name, vdev);
        if (ret) {
+               vdev->ctx[0].trigger = NULL;
                kfree(vdev->ctx[0].name);
                eventfd_ctx_put(trigger);
                return ret;
        }
 
-       vdev->ctx[0].trigger = trigger;
-
        /*
         * INTx disable will stick across the new irq setup,
         * disable_irq won't.
         */
        spin_lock_irqsave(&vdev->irqlock, flags);
-       if (!vdev->pci_2_3 && (vdev->ctx[0].masked || vdev->virq_disabled))
+       if (!vdev->pci_2_3 && vdev->ctx[0].masked)
                disable_irq_nosync(pdev->irq);
        spin_unlock_irqrestore(&vdev->irqlock, flags);
 
index ed8e2e6c8df28715455c7ac09423ef447115e976..aa31692064ddd08b6aa91718ed1ece369da74631 100644 (file)
@@ -330,17 +330,6 @@ static int tcm_vhost_queue_tm_rsp(struct se_cmd *se_cmd)
        return 0;
 }
 
-static u16 tcm_vhost_set_fabric_sense_len(struct se_cmd *se_cmd,
-       u32 sense_length)
-{
-       return 0;
-}
-
-static u16 tcm_vhost_get_fabric_sense_len(void)
-{
-       return 0;
-}
-
 static void vhost_scsi_free_cmd(struct tcm_vhost_cmd *tv_cmd)
 {
        struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd;
@@ -426,10 +415,7 @@ static struct tcm_vhost_cmd *vhost_scsi_allocate_cmd(
 {
        struct tcm_vhost_cmd *tv_cmd;
        struct tcm_vhost_nexus *tv_nexus;
-       struct se_portal_group *se_tpg = &tv_tpg->se_tpg;
        struct se_session *se_sess;
-       struct se_cmd *se_cmd;
-       int sam_task_attr;
 
        tv_nexus = tv_tpg->tpg_nexus;
        if (!tv_nexus) {
@@ -445,23 +431,11 @@ static struct tcm_vhost_cmd *vhost_scsi_allocate_cmd(
        }
        INIT_LIST_HEAD(&tv_cmd->tvc_completion_list);
        tv_cmd->tvc_tag = v_req->tag;
+       tv_cmd->tvc_task_attr = v_req->task_attr;
+       tv_cmd->tvc_exp_data_len = exp_data_len;
+       tv_cmd->tvc_data_direction = data_direction;
+       tv_cmd->tvc_nexus = tv_nexus;
 
-       se_cmd = &tv_cmd->tvc_se_cmd;
-       /*
-        * Locate the SAM Task Attr from virtio_scsi_cmd_req
-        */
-       sam_task_attr = v_req->task_attr;
-       /*
-        * Initialize struct se_cmd descriptor from TCM infrastructure
-        */
-       transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, exp_data_len,
-                               data_direction, sam_task_attr,
-                               &tv_cmd->tvc_sense_buf[0]);
-
-#if 0  /* FIXME: vhost_scsi_allocate_cmd() BIDI operation */
-       if (bidi)
-               se_cmd->se_cmd_flags |= SCF_BIDI;
-#endif
        return tv_cmd;
 }
 
@@ -560,37 +534,10 @@ static void tcm_vhost_submission_work(struct work_struct *work)
 {
        struct tcm_vhost_cmd *tv_cmd =
                container_of(work, struct tcm_vhost_cmd, work);
+       struct tcm_vhost_nexus *tv_nexus;
        struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd;
        struct scatterlist *sg_ptr, *sg_bidi_ptr = NULL;
        int rc, sg_no_bidi = 0;
-       /*
-        * Locate the struct se_lun pointer based on v_req->lun, and
-        * attach it to struct se_cmd
-        */
-       rc = transport_lookup_cmd_lun(&tv_cmd->tvc_se_cmd, tv_cmd->tvc_lun);
-       if (rc < 0) {
-               pr_err("Failed to look up lun: %d\n", tv_cmd->tvc_lun);
-               transport_send_check_condition_and_sense(&tv_cmd->tvc_se_cmd,
-                       tv_cmd->tvc_se_cmd.scsi_sense_reason, 0);
-               transport_generic_free_cmd(se_cmd, 0);
-               return;
-       }
-
-       rc = target_setup_cmd_from_cdb(se_cmd, tv_cmd->tvc_cdb);
-       if (rc == -ENOMEM) {
-               transport_send_check_condition_and_sense(se_cmd,
-                               TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
-               transport_generic_free_cmd(se_cmd, 0);
-               return;
-       } else if (rc < 0) {
-               if (se_cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)
-                       tcm_vhost_queue_status(se_cmd);
-               else
-                       transport_send_check_condition_and_sense(se_cmd,
-                                       se_cmd->scsi_sense_reason, 0);
-               transport_generic_free_cmd(se_cmd, 0);
-               return;
-       }
 
        if (tv_cmd->tvc_sgl_count) {
                sg_ptr = tv_cmd->tvc_sgl;
@@ -608,17 +555,19 @@ static void tcm_vhost_submission_work(struct work_struct *work)
        } else {
                sg_ptr = NULL;
        }
-
-       rc = transport_generic_map_mem_to_cmd(se_cmd, sg_ptr,
-                               tv_cmd->tvc_sgl_count, sg_bidi_ptr,
-                               sg_no_bidi);
+       tv_nexus = tv_cmd->tvc_nexus;
+
+       rc = target_submit_cmd_map_sgls(se_cmd, tv_nexus->tvn_se_sess,
+                       tv_cmd->tvc_cdb, &tv_cmd->tvc_sense_buf[0],
+                       tv_cmd->tvc_lun, tv_cmd->tvc_exp_data_len,
+                       tv_cmd->tvc_task_attr, tv_cmd->tvc_data_direction,
+                       0, sg_ptr, tv_cmd->tvc_sgl_count,
+                       sg_bidi_ptr, sg_no_bidi);
        if (rc < 0) {
                transport_send_check_condition_and_sense(se_cmd,
-                               se_cmd->scsi_sense_reason, 0);
+                               TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
                transport_generic_free_cmd(se_cmd, 0);
-               return;
        }
-       transport_handle_cdb_direct(se_cmd);
 }
 
 static void vhost_scsi_handle_vq(struct vhost_scsi *vs)
@@ -1531,8 +1480,6 @@ static struct target_core_fabric_ops tcm_vhost_ops = {
        .queue_data_in                  = tcm_vhost_queue_data_in,
        .queue_status                   = tcm_vhost_queue_status,
        .queue_tm_rsp                   = tcm_vhost_queue_tm_rsp,
-       .get_fabric_sense_len           = tcm_vhost_get_fabric_sense_len,
-       .set_fabric_sense_len           = tcm_vhost_set_fabric_sense_len,
        /*
         * Setup callers for generic logic in target_core_fabric_configfs.c
         */
index d9e93557d669d09b3ab08d1030aa47791184db00..7e87c63ecbcd84aa38b89d0568b8007cfa6cdd83 100644 (file)
@@ -5,6 +5,12 @@
 struct tcm_vhost_cmd {
        /* Descriptor from vhost_get_vq_desc() for virt_queue segment */
        int tvc_vq_desc;
+       /* virtio-scsi initiator task attribute */
+       int tvc_task_attr;
+       /* virtio-scsi initiator data direction */
+       enum dma_data_direction tvc_data_direction;
+       /* Expected data transfer length from virtio-scsi header */
+       u32 tvc_exp_data_len;
        /* The Tag from include/linux/virtio_scsi.h:struct virtio_scsi_cmd_req */
        u64 tvc_tag;
        /* The number of scatterlists associated with this cmd */
@@ -17,6 +23,8 @@ struct tcm_vhost_cmd {
        struct virtio_scsi_cmd_resp __user *tvc_resp;
        /* Pointer to vhost_scsi for our device */
        struct vhost_scsi *tvc_vhost;
+       /* Pointer to vhost nexus memory */
+       struct tcm_vhost_nexus *tvc_nexus;
        /* The TCM I/O descriptor that is accessed via container_of() */
        struct se_cmd tvc_se_cmd;
        /* work item used for cmwq dispatch to tcm_vhost_submission_work() */
index 20c33c42600a1d1b7e12e770059a5a18d5a9daae..d08d7998a4aae7835c607791b2308d6ed008a797 100644 (file)
@@ -2139,21 +2139,6 @@ config FB_UDL
          mplayer -vo fbdev. Supports all USB 2.0 era DisplayLink devices.
          To compile as a module, choose M here: the module name is udlfb.
 
-config FB_PNX4008_DUM
-       tristate "Display Update Module support on Philips PNX4008 board"
-       depends on FB && ARCH_PNX4008
-       ---help---
-         Say Y here to enable support for PNX4008 Display Update Module (DUM)
-
-config FB_PNX4008_DUM_RGB
-       tristate "RGB Framebuffer support on Philips PNX4008 board"
-       depends on FB_PNX4008_DUM
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       ---help---
-         Say Y here to enable support for PNX4008 RGB Framebuffer
-
 config FB_IBM_GXT4500
        tristate "Framebuffer support for IBM GXT4500P adaptor"
        depends on FB && PPC
index 194035986af2a11562f46bbd0af8584f7d7ed737..23e948ebfab8931b790617cf9341a081b1f9edae 100644 (file)
@@ -127,8 +127,6 @@ obj-$(CONFIG_FB_S3C)                  += s3c-fb.o
 obj-$(CONFIG_FB_S3C2410)         += s3c2410fb.o
 obj-$(CONFIG_FB_FSL_DIU)         += fsl-diu-fb.o
 obj-$(CONFIG_FB_COBALT)           += cobalt_lcdfb.o
-obj-$(CONFIG_FB_PNX4008_DUM)     += pnx4008/
-obj-$(CONFIG_FB_PNX4008_DUM_RGB)  += pnx4008/
 obj-$(CONFIG_FB_IBM_GXT4500)     += gxt4500.o
 obj-$(CONFIG_FB_PS3)             += ps3fb.o
 obj-$(CONFIG_FB_SM501)            += sm501fb.o
index 887df9d8142222fb17cfb508525f2d4b2bbbabcf..7fa1bf823729205450d0347a017ef62f9b19cd20 100644 (file)
@@ -949,7 +949,6 @@ static int round_down_bpp = 1;      /* for mode probing */
 
 
 static int amifb_ilbm = 0;     /* interleaved or normal bitplanes */
-static int amifb_inverse = 0;
 
 static u32 amifb_hfmin __initdata;     /* monitor hfreq lower limit (Hz) */
 static u32 amifb_hfmax __initdata;     /* monitor hfreq upper limit (Hz) */
@@ -2355,7 +2354,6 @@ static int __init amifb_setup(char *options)
                if (!*this_opt)
                        continue;
                if (!strcmp(this_opt, "inverse")) {
-                       amifb_inverse = 1;
                        fb_invert_cmaps();
                } else if (!strcmp(this_opt, "ilbm"))
                        amifb_ilbm = 1;
index a1d58e9d3073e1ff57bead6eb1cefbe4d98e6f84..4659d5da6ff88d2a59270b9b2db69aec0c14908d 100644 (file)
@@ -552,6 +552,7 @@ static int __devinit arcfb_probe(struct platform_device *dev)
                                "arcfb", info)) {
                        printk(KERN_INFO
                                "arcfb: Failed req IRQ %d\n", par->irq);
+                       retval = -EBUSY;
                        goto err1;
                }
        }
index 15055395cd95a1eff62591c81111501dda1e6560..94cac9f9919ffa1ce9c278812b4708b0b80bfcdf 100644 (file)
@@ -931,8 +931,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
                }
 
                info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
-               if (!info->screen_base)
+               if (!info->screen_base) {
+                       ret = -ENOMEM;
                        goto release_intmem;
+               }
 
                /*
                 * Don't clear the framebuffer -- someone may have set
@@ -960,6 +962,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
        sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len);
        if (!sinfo->mmio) {
                dev_err(dev, "cannot map LCDC registers\n");
+               ret = -ENOMEM;
                goto release_mem;
        }
 
index 995f0164c9b082c7da2836123adfcb2b7f10a6c7..069983ca49ff89da5d241649283e11f2699b6d9e 100644 (file)
@@ -213,7 +213,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
        pb->exit = data->exit;
        pb->dev = &pdev->dev;
 
-       pb->pwm = pwm_get(&pdev->dev, NULL);
+       pb->pwm = devm_pwm_get(&pdev->dev, NULL);
        if (IS_ERR(pb->pwm)) {
                dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n");
 
@@ -246,7 +246,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
        if (IS_ERR(bl)) {
                dev_err(&pdev->dev, "failed to register backlight\n");
                ret = PTR_ERR(bl);
-               goto err_bl;
+               goto err_alloc;
        }
 
        bl->props.brightness = data->dft_brightness;
@@ -255,8 +255,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, bl);
        return 0;
 
-err_bl:
-       pwm_put(pb->pwm);
 err_alloc:
        if (data->exit)
                data->exit(&pdev->dev);
@@ -271,7 +269,6 @@ static int pwm_backlight_remove(struct platform_device *pdev)
        backlight_device_unregister(bl);
        pwm_config(pb->pwm, 0, pb->period);
        pwm_disable(pb->pwm);
-       pwm_put(pb->pwm);
        if (pb->exit)
                pb->exit(&pdev->dev);
        return 0;
index befbc80d11fca4d82c4718a7cc47b580003db3b9..7347aa1e5e4ac1e9957510b19889d1d3446784e0 100644 (file)
@@ -760,18 +760,20 @@ static int __devinit bfin_lq035_probe(struct platform_device *pdev)
        bfin_lq035_fb.flags = FBINFO_DEFAULT;
 
 
-       bfin_lq035_fb.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
+       bfin_lq035_fb.pseudo_palette = devm_kzalloc(&pdev->dev,
+                                                   sizeof(u32) * 16,
+                                                   GFP_KERNEL);
        if (bfin_lq035_fb.pseudo_palette == NULL) {
                pr_err("failed to allocate pseudo_palette\n");
                ret = -ENOMEM;
-               goto out_palette;
+               goto out_table;
        }
 
        if (fb_alloc_cmap(&bfin_lq035_fb.cmap, NBR_PALETTE, 0) < 0) {
                pr_err("failed to allocate colormap (%d entries)\n",
                        NBR_PALETTE);
                ret = -EFAULT;
-               goto out_cmap;
+               goto out_table;
        }
 
        if (register_framebuffer(&bfin_lq035_fb) < 0) {
@@ -804,9 +806,6 @@ out_lcd:
        unregister_framebuffer(&bfin_lq035_fb);
 out_reg:
        fb_dealloc_cmap(&bfin_lq035_fb.cmap);
-out_cmap:
-       kfree(bfin_lq035_fb.pseudo_palette);
-out_palette:
 out_table:
        dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
        fb_buffer = NULL;
@@ -834,7 +833,6 @@ static int __devexit bfin_lq035_remove(struct platform_device *pdev)
        free_dma(CH_PPI);
 
 
-       kfree(bfin_lq035_fb.pseudo_palette);
        fb_dealloc_cmap(&bfin_lq035_fb.cmap);
 
 
index dc2f0047769ba83f39be09989e1134b62c17bf50..ff5663f5c64f5d1dbb97448b27658c8f3ea62272 100644 (file)
@@ -525,6 +525,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
        info = fbinfo->par;
        info->fb = fbinfo;
        info->dev = &pdev->dev;
+       spin_lock_init(&info->lock);
 
        platform_set_drvdata(pdev, fbinfo);
 
@@ -601,7 +602,8 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
 
        fbinfo->fbops = &bfin_bf54x_fb_ops;
 
-       fbinfo->pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
+       fbinfo->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16,
+                                             GFP_KERNEL);
        if (!fbinfo->pseudo_palette) {
                printk(KERN_ERR DRIVER_NAME
                       "Fail to allocate pseudo_palette\n");
@@ -616,7 +618,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
                       "Fail to allocate colormap (%d entries)\n",
                       BFIN_LCD_NBR_PALETTE_ENTRIES);
                ret = -EFAULT;
-               goto out5;
+               goto out4;
        }
 
        if (request_ports(info)) {
@@ -671,8 +673,6 @@ out7:
        free_ports(info);
 out6:
        fb_dealloc_cmap(&fbinfo->cmap);
-out5:
-       kfree(fbinfo->pseudo_palette);
 out4:
        dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
                          info->dma_handle);
@@ -699,7 +699,6 @@ static int __devexit bfin_bf54x_remove(struct platform_device *pdev)
                dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
                                  info->dma_handle);
 
-       kfree(fbinfo->pseudo_palette);
        fb_dealloc_cmap(&fbinfo->cmap);
 
 #ifndef NO_BL_SUPPORT
index 353c02fe8a952816af0f5c0d668d80e81f31d204..6fbc75c2f0a10bc77c8176e5bd05e6eb1dfc940c 100644 (file)
@@ -577,6 +577,7 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
        info = fbinfo->par;
        info->fb = fbinfo;
        info->dev = &pdev->dev;
+       spin_lock_init(&info->lock);
 
        info->disp_info = pdev->dev.platform_data;
 
@@ -853,17 +854,7 @@ static struct platform_driver bfin_lq035q1_driver = {
        },
 };
 
-static int __init bfin_lq035q1_driver_init(void)
-{
-       return platform_driver_register(&bfin_lq035q1_driver);
-}
-module_init(bfin_lq035q1_driver_init);
-
-static void __exit bfin_lq035q1_driver_cleanup(void)
-{
-       platform_driver_unregister(&bfin_lq035q1_driver);
-}
-module_exit(bfin_lq035q1_driver_cleanup);
+module_platform_driver(bfin_lq035q1_driver);
 
 MODULE_DESCRIPTION("Blackfin TFT LCD Driver");
 MODULE_LICENSE("GPL");
index 7a0c05f3537eed362fb11102cf3a5a760185dd6f..ae0fb24b8b4330a6228db62081faf52b0cf8fad6 100644 (file)
@@ -447,6 +447,7 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
        info = fbinfo->par;
        info->fb = fbinfo;
        info->dev = &pdev->dev;
+       spin_lock_init(&info->lock);
 
        platform_set_drvdata(pdev, fbinfo);
 
index 7ba74cd4be61afced18e8a94e6ebbc57c83a00b2..6bea9a9367989f314aaf389ca07d9d5ef24d0833 100644 (file)
@@ -319,8 +319,10 @@ static int __devinit bw2_probe(struct platform_device *op)
 
        info->screen_base = of_ioremap(&op->resource[0], 0,
                                       info->fix.smem_len, "bw2 ram");
-       if (!info->screen_base)
+       if (!info->screen_base) {
+               err = -ENOMEM;
                goto out_unmap_regs;
+       }
 
        bw2_blank(FB_BLANK_UNBLANK, info);
 
index f927a7b1a8d4c3a82df0e1c9f4ff243dccda49c0..c5e7612ff8760609152eea65fc6f7bb6e6db872c 100644 (file)
@@ -398,7 +398,8 @@ static int __devinit cg3_probe(struct platform_device *op)
                        goto out_unmap_screen;
        }
 
-       if (fb_alloc_cmap(&info->cmap, 256, 0))
+       err = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (err)
                goto out_unmap_screen;
 
        fb_set_cmap(&info->cmap, info);
index eae46f6457e2a59788c1fbd46995cab8ea6739c4..01a4ee7cc6b1b069be59593fa9baef0ec37c3176 100644 (file)
@@ -348,7 +348,8 @@ static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)
        }
 
        info->screen_size = resource_size(res);
-       info->screen_base = ioremap(res->start, info->screen_size);
+       info->screen_base = devm_ioremap(&dev->dev, res->start,
+                                        info->screen_size);
        info->fbops = &cobalt_lcd_fbops;
        info->fix = cobalt_lcdfb_fix;
        info->fix.smem_start = res->start;
@@ -359,7 +360,6 @@ static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)
 
        retval = register_framebuffer(info);
        if (retval < 0) {
-               iounmap(info->screen_base);
                framebuffer_release(info);
                return retval;
        }
@@ -380,7 +380,6 @@ static int __devexit cobalt_lcdfb_remove(struct platform_device *dev)
 
        info = platform_get_drvdata(dev);
        if (info) {
-               iounmap(info->screen_base);
                unregister_framebuffer(info);
                framebuffer_release(info);
        }
index fa6e698e63c4d81cfab4089bcaa70e18ce829a31..838caa1cfef70d1eec3ee3ae9ecdb2c24a933add 100644 (file)
@@ -1092,7 +1092,7 @@ static const unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
        /*{*/   /*   Char 124: '|' */
        0x44,   /*=   [ *  ]        */
        0x44,   /*=   [ *  ]        */
-       0x00,   /*=   [    ]        */
+       0x44,   /*=   [ *  ]        */
        0x44,   /*=   [ *  ]        */
        0x44,   /*=   [ *  ]        */
        0x00,   /*=   [    ]        */
index 5abf290c6eb76fbd8e2c3c91f5d229b3c409b59d..268151325b83e00b0e7e36e32ea69ff2e8bfac7e 100644 (file)
@@ -127,7 +127,7 @@ static const unsigned char fontdata_sun8x16[FONTDATAMAX] = {
 /*y*/ 0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00,
 /*z*/ 0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00,
 /*{*/ 0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00,
-/*|*/ 0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+/*|*/ 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
 /*}*/ 0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,
 /*~*/ 0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 /* */ 0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00,
index c1527f5b47eec53af0c54f33ff8e143afcf1c402..e40125cb313e95080e49abdcad344195707c4232 100644 (file)
@@ -1804,8 +1804,10 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
        cfb->irq = dev->irq;
        cfb->region = pci_ioremap_bar(dev, 0);
-       if (!cfb->region)
+       if (!cfb->region) {
+               err = -ENOMEM;
                goto failed_ioremap;
+       }
 
        cfb->regs = cfb->region + MMIO_OFFSET;
        cfb->fb.device = &dev->dev;
index 113d43a16f546b95cce777ba62f2a5d5d0e3370c..80665f66ac1ab844b283bb432a39f0591908d84d 100644 (file)
@@ -26,7 +26,9 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/uaccess.h>
+#include <linux/pm_runtime.h>
 #include <linux/interrupt.h>
+#include <linux/wait.h>
 #include <linux/clk.h>
 #include <linux/cpufreq.h>
 #include <linux/console.h>
@@ -48,6 +50,7 @@
 #define LCD_PL_LOAD_DONE               BIT(6)
 #define LCD_FIFO_UNDERFLOW             BIT(5)
 #define LCD_SYNC_LOST                  BIT(2)
+#define LCD_FRAME_DONE                 BIT(0)
 
 /* LCD DMA Control Register */
 #define LCD_DMA_BURST_SIZE(x)          ((x) << 4)
@@ -86,6 +89,8 @@
 #define LCD_V2_LIDD_CLK_EN             BIT(1)
 #define LCD_V2_CORE_CLK_EN             BIT(0)
 #define LCD_V2_LPP_B10                 26
+#define LCD_V2_TFT_24BPP_MODE          BIT(25)
+#define LCD_V2_TFT_24BPP_UNPACK                BIT(26)
 
 /* LCD Raster Timing 2 Register */
 #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x)     ((x) << 16)
@@ -135,6 +140,8 @@ static void __iomem *da8xx_fb_reg_base;
 static struct resource *lcdc_regs;
 static unsigned int lcd_revision;
 static irq_handler_t lcdc_irq_handler;
+static wait_queue_head_t frame_done_wq;
+static int frame_done_flag;
 
 static inline unsigned int lcdc_read(unsigned int addr)
 {
@@ -156,7 +163,6 @@ struct da8xx_fb_par {
        unsigned int            dma_end;
        struct clk *lcdc_clk;
        int irq;
-       unsigned short pseudo_palette[16];
        unsigned int palette_sz;
        unsigned int pxl_clk;
        int blank;
@@ -175,6 +181,7 @@ struct da8xx_fb_par {
        unsigned int            lcd_fck_rate;
 #endif
        void (*panel_power_ctrl)(int);
+       u32 pseudo_palette[16];
 };
 
 /* Variable Screen Information */
@@ -288,13 +295,26 @@ static inline void lcd_enable_raster(void)
 }
 
 /* Disable the Raster Engine of the LCD Controller */
-static inline void lcd_disable_raster(void)
+static inline void lcd_disable_raster(bool wait_for_frame_done)
 {
        u32 reg;
+       int ret;
 
        reg = lcdc_read(LCD_RASTER_CTRL_REG);
        if (reg & LCD_RASTER_ENABLE)
                lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
+       else
+               /* return if already disabled */
+               return;
+
+       if ((wait_for_frame_done == true) && (lcd_revision == LCD_VERSION_2)) {
+               frame_done_flag = 0;
+               ret = wait_event_interruptible_timeout(frame_done_wq,
+                               frame_done_flag != 0,
+                               msecs_to_jiffies(50));
+               if (ret == 0)
+                       pr_err("LCD Controller timed out\n");
+       }
 }
 
 static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
@@ -321,7 +341,8 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
                } else {
                        reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
                                LCD_V2_END_OF_FRAME0_INT_ENA |
-                               LCD_V2_END_OF_FRAME1_INT_ENA;
+                               LCD_V2_END_OF_FRAME1_INT_ENA |
+                               LCD_FRAME_DONE;
                        lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
                }
                reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
@@ -499,6 +520,9 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
 {
        u32 reg;
 
+       if (bpp > 16 && lcd_revision == LCD_VERSION_1)
+               return -EINVAL;
+
        /* Set the Panel Width */
        /* Pixels per line = (PPL + 1)*16 */
        if (lcd_revision == LCD_VERSION_1) {
@@ -542,14 +566,19 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
        reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);
        if (raster_order)
                reg |= LCD_RASTER_ORDER;
-       lcdc_write(reg, LCD_RASTER_CTRL_REG);
+
+       par->palette_sz = 16 * 2;
 
        switch (bpp) {
        case 1:
        case 2:
        case 4:
        case 16:
-               par->palette_sz = 16 * 2;
+               break;
+       case 24:
+               reg |= LCD_V2_TFT_24BPP_MODE;
+       case 32:
+               reg |= LCD_V2_TFT_24BPP_UNPACK;
                break;
 
        case 8:
@@ -560,9 +589,12 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
                return -EINVAL;
        }
 
+       lcdc_write(reg, LCD_RASTER_CTRL_REG);
+
        return 0;
 }
 
+#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
 static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
                              unsigned blue, unsigned transp,
                              struct fb_info *info)
@@ -578,13 +610,38 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
        if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
                return 1;
 
-       if (info->var.bits_per_pixel == 4) {
-               if (regno > 15)
-                       return 1;
+       if (info->var.bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1)
+               return -EINVAL;
 
-               if (info->var.grayscale) {
-                       pal = regno;
-               } else {
+       switch (info->fix.visual) {
+       case FB_VISUAL_TRUECOLOR:
+               red = CNVT_TOHW(red, info->var.red.length);
+               green = CNVT_TOHW(green, info->var.green.length);
+               blue = CNVT_TOHW(blue, info->var.blue.length);
+               break;
+       case FB_VISUAL_PSEUDOCOLOR:
+               switch (info->var.bits_per_pixel) {
+               case 4:
+                       if (regno > 15)
+                               return -EINVAL;
+
+                       if (info->var.grayscale) {
+                               pal = regno;
+                       } else {
+                               red >>= 4;
+                               green >>= 8;
+                               blue >>= 12;
+
+                               pal = red & 0x0f00;
+                               pal |= green & 0x00f0;
+                               pal |= blue & 0x000f;
+                       }
+                       if (regno == 0)
+                               pal |= 0x2000;
+                       palette[regno] = pal;
+                       break;
+
+               case 8:
                        red >>= 4;
                        green >>= 8;
                        blue >>= 12;
@@ -592,36 +649,36 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
                        pal = (red & 0x0f00);
                        pal |= (green & 0x00f0);
                        pal |= (blue & 0x000f);
-               }
-               if (regno == 0)
-                       pal |= 0x2000;
-               palette[regno] = pal;
-
-       } else if (info->var.bits_per_pixel == 8) {
-               red >>= 4;
-               green >>= 8;
-               blue >>= 12;
-
-               pal = (red & 0x0f00);
-               pal |= (green & 0x00f0);
-               pal |= (blue & 0x000f);
 
-               if (palette[regno] != pal) {
-                       update_hw = 1;
-                       palette[regno] = pal;
+                       if (palette[regno] != pal) {
+                               update_hw = 1;
+                               palette[regno] = pal;
+                       }
+                       break;
                }
-       } else if ((info->var.bits_per_pixel == 16) && regno < 16) {
-               red >>= (16 - info->var.red.length);
-               red <<= info->var.red.offset;
+               break;
+       }
 
-               green >>= (16 - info->var.green.length);
-               green <<= info->var.green.offset;
+       /* Truecolor has hardware independent palette */
+       if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+               u32 v;
 
-               blue >>= (16 - info->var.blue.length);
-               blue <<= info->var.blue.offset;
+               if (regno > 15)
+                       return -EINVAL;
 
-               par->pseudo_palette[regno] = red | green | blue;
+               v = (red << info->var.red.offset) |
+                       (green << info->var.green.offset) |
+                       (blue << info->var.blue.offset);
 
+               switch (info->var.bits_per_pixel) {
+               case 16:
+                       ((u16 *) (info->pseudo_palette))[regno] = v;
+                       break;
+               case 24:
+               case 32:
+                       ((u32 *) (info->pseudo_palette))[regno] = v;
+                       break;
+               }
                if (palette[0] != 0x4000) {
                        update_hw = 1;
                        palette[0] = 0x4000;
@@ -634,11 +691,12 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
 
        return 0;
 }
+#undef CNVT_TOHW
 
 static void lcd_reset(struct da8xx_fb_par *par)
 {
        /* Disable the Raster if previously Enabled */
-       lcd_disable_raster();
+       lcd_disable_raster(false);
 
        /* DMA has to be disabled */
        lcdc_write(0, LCD_DMA_CTRL_REG);
@@ -734,7 +792,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
        u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
 
        if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
-               lcd_disable_raster();
+               lcd_disable_raster(false);
                lcdc_write(stat, LCD_MASKED_STAT_REG);
                lcd_enable_raster();
        } else if (stat & LCD_PL_LOAD_DONE) {
@@ -744,7 +802,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
                 * interrupt via the following write to the status register. If
                 * this is done after then one gets multiple PL done interrupts.
                 */
-               lcd_disable_raster();
+               lcd_disable_raster(false);
 
                lcdc_write(stat, LCD_MASKED_STAT_REG);
 
@@ -775,6 +833,14 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
                        par->vsync_flag = 1;
                        wake_up_interruptible(&par->vsync_wait);
                }
+
+               /* Set only when controller is disabled and at the end of
+                * active frame
+                */
+               if (stat & BIT(0)) {
+                       frame_done_flag = 1;
+                       wake_up_interruptible(&frame_done_wq);
+               }
        }
 
        lcdc_write(0, LCD_END_OF_INT_IND_REG);
@@ -789,7 +855,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
        u32 reg_ras;
 
        if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
-               lcd_disable_raster();
+               lcd_disable_raster(false);
                lcdc_write(stat, LCD_STAT_REG);
                lcd_enable_raster();
        } else if (stat & LCD_PL_LOAD_DONE) {
@@ -799,7 +865,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
                 * interrupt via the following write to the status register. If
                 * this is done after then one gets multiple PL done interrupts.
                 */
-               lcd_disable_raster();
+               lcd_disable_raster(false);
 
                lcdc_write(stat, LCD_STAT_REG);
 
@@ -842,6 +908,9 @@ static int fb_check_var(struct fb_var_screeninfo *var,
 {
        int err = 0;
 
+       if (var->bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1)
+               return -EINVAL;
+
        switch (var->bits_per_pixel) {
        case 1:
        case 8:
@@ -877,6 +946,26 @@ static int fb_check_var(struct fb_var_screeninfo *var,
                var->transp.length = 0;
                var->nonstd = 0;
                break;
+       case 24:
+               var->red.offset = 16;
+               var->red.length = 8;
+               var->green.offset = 8;
+               var->green.length = 8;
+               var->blue.offset = 0;
+               var->blue.length = 8;
+               var->nonstd = 0;
+               break;
+       case 32:
+               var->transp.offset = 24;
+               var->transp.length = 8;
+               var->red.offset = 16;
+               var->red.length = 8;
+               var->green.offset = 8;
+               var->green.length = 8;
+               var->blue.offset = 0;
+               var->blue.length = 8;
+               var->nonstd = 0;
+               break;
        default:
                err = -EINVAL;
        }
@@ -898,9 +987,10 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
        if (val == CPUFREQ_POSTCHANGE) {
                if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) {
                        par->lcd_fck_rate = clk_get_rate(par->lcdc_clk);
-                       lcd_disable_raster();
+                       lcd_disable_raster(true);
                        lcd_calc_clk_divider(par);
-                       lcd_enable_raster();
+                       if (par->blank == FB_BLANK_UNBLANK)
+                               lcd_enable_raster();
                }
        }
 
@@ -935,7 +1025,7 @@ static int __devexit fb_remove(struct platform_device *dev)
                if (par->panel_power_ctrl)
                        par->panel_power_ctrl(0);
 
-               lcd_disable_raster();
+               lcd_disable_raster(true);
                lcdc_write(0, LCD_RASTER_CTRL_REG);
 
                /* disable DMA  */
@@ -948,8 +1038,8 @@ static int __devexit fb_remove(struct platform_device *dev)
                dma_free_coherent(NULL, par->vram_size, par->vram_virt,
                                  par->vram_phys);
                free_irq(par->irq, par);
-               clk_disable(par->lcdc_clk);
-               clk_put(par->lcdc_clk);
+               pm_runtime_put_sync(&dev->dev);
+               pm_runtime_disable(&dev->dev);
                framebuffer_release(info);
                iounmap(da8xx_fb_reg_base);
                release_mem_region(lcdc_regs->start, resource_size(lcdc_regs));
@@ -1051,7 +1141,7 @@ static int cfb_blank(int blank, struct fb_info *info)
                if (par->panel_power_ctrl)
                        par->panel_power_ctrl(0);
 
-               lcd_disable_raster();
+               lcd_disable_raster(true);
                break;
        default:
                ret = -EINVAL;
@@ -1183,9 +1273,9 @@ static int __devinit fb_probe(struct platform_device *device)
                ret = -ENODEV;
                goto err_ioremap;
        }
-       ret = clk_enable(fb_clk);
-       if (ret)
-               goto err_clk_put;
+
+       pm_runtime_enable(&device->dev);
+       pm_runtime_get_sync(&device->dev);
 
        /* Determine LCD IP Version */
        switch (lcdc_read(LCD_PID_REG)) {
@@ -1213,7 +1303,7 @@ static int __devinit fb_probe(struct platform_device *device)
        if (i == ARRAY_SIZE(known_lcd_panels)) {
                dev_err(&device->dev, "GLCD: No valid panel found\n");
                ret = -ENODEV;
-               goto err_clk_disable;
+               goto err_pm_runtime_disable;
        } else
                dev_info(&device->dev, "GLCD: Found %s panel\n",
                                        fb_pdata->type);
@@ -1225,7 +1315,7 @@ static int __devinit fb_probe(struct platform_device *device)
        if (!da8xx_fb_info) {
                dev_dbg(&device->dev, "Memory allocation failed for fb_info\n");
                ret = -ENOMEM;
-               goto err_clk_disable;
+               goto err_pm_runtime_disable;
        }
 
        par = da8xx_fb_info->par;
@@ -1356,8 +1446,10 @@ static int __devinit fb_probe(struct platform_device *device)
 
        if (lcd_revision == LCD_VERSION_1)
                lcdc_irq_handler = lcdc_irq_handler_rev01;
-       else
+       else {
+               init_waitqueue_head(&frame_done_wq);
                lcdc_irq_handler = lcdc_irq_handler_rev02;
+       }
 
        ret = request_irq(par->irq, lcdc_irq_handler, 0,
                        DRIVER_NAME, par);
@@ -1385,11 +1477,9 @@ err_release_fb_mem:
 err_release_fb:
        framebuffer_release(da8xx_fb_info);
 
-err_clk_disable:
-       clk_disable(fb_clk);
-
-err_clk_put:
-       clk_put(fb_clk);
+err_pm_runtime_disable:
+       pm_runtime_put_sync(&device->dev);
+       pm_runtime_disable(&device->dev);
 
 err_ioremap:
        iounmap(da8xx_fb_reg_base);
@@ -1401,6 +1491,69 @@ err_request_mem:
 }
 
 #ifdef CONFIG_PM
+struct lcdc_context {
+       u32 clk_enable;
+       u32 ctrl;
+       u32 dma_ctrl;
+       u32 raster_timing_0;
+       u32 raster_timing_1;
+       u32 raster_timing_2;
+       u32 int_enable_set;
+       u32 dma_frm_buf_base_addr_0;
+       u32 dma_frm_buf_ceiling_addr_0;
+       u32 dma_frm_buf_base_addr_1;
+       u32 dma_frm_buf_ceiling_addr_1;
+       u32 raster_ctrl;
+} reg_context;
+
+static void lcd_context_save(void)
+{
+       if (lcd_revision == LCD_VERSION_2) {
+               reg_context.clk_enable = lcdc_read(LCD_CLK_ENABLE_REG);
+               reg_context.int_enable_set = lcdc_read(LCD_INT_ENABLE_SET_REG);
+       }
+
+       reg_context.ctrl = lcdc_read(LCD_CTRL_REG);
+       reg_context.dma_ctrl = lcdc_read(LCD_DMA_CTRL_REG);
+       reg_context.raster_timing_0 = lcdc_read(LCD_RASTER_TIMING_0_REG);
+       reg_context.raster_timing_1 = lcdc_read(LCD_RASTER_TIMING_1_REG);
+       reg_context.raster_timing_2 = lcdc_read(LCD_RASTER_TIMING_2_REG);
+       reg_context.dma_frm_buf_base_addr_0 =
+               lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
+       reg_context.dma_frm_buf_ceiling_addr_0 =
+               lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
+       reg_context.dma_frm_buf_base_addr_1 =
+               lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
+       reg_context.dma_frm_buf_ceiling_addr_1 =
+               lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
+       reg_context.raster_ctrl = lcdc_read(LCD_RASTER_CTRL_REG);
+       return;
+}
+
+static void lcd_context_restore(void)
+{
+       if (lcd_revision == LCD_VERSION_2) {
+               lcdc_write(reg_context.clk_enable, LCD_CLK_ENABLE_REG);
+               lcdc_write(reg_context.int_enable_set, LCD_INT_ENABLE_SET_REG);
+       }
+
+       lcdc_write(reg_context.ctrl, LCD_CTRL_REG);
+       lcdc_write(reg_context.dma_ctrl, LCD_DMA_CTRL_REG);
+       lcdc_write(reg_context.raster_timing_0, LCD_RASTER_TIMING_0_REG);
+       lcdc_write(reg_context.raster_timing_1, LCD_RASTER_TIMING_1_REG);
+       lcdc_write(reg_context.raster_timing_2, LCD_RASTER_TIMING_2_REG);
+       lcdc_write(reg_context.dma_frm_buf_base_addr_0,
+                       LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
+       lcdc_write(reg_context.dma_frm_buf_ceiling_addr_0,
+                       LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
+       lcdc_write(reg_context.dma_frm_buf_base_addr_1,
+                       LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
+       lcdc_write(reg_context.dma_frm_buf_ceiling_addr_1,
+                       LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
+       lcdc_write(reg_context.raster_ctrl, LCD_RASTER_CTRL_REG);
+       return;
+}
+
 static int fb_suspend(struct platform_device *dev, pm_message_t state)
 {
        struct fb_info *info = platform_get_drvdata(dev);
@@ -1411,8 +1564,9 @@ static int fb_suspend(struct platform_device *dev, pm_message_t state)
                par->panel_power_ctrl(0);
 
        fb_set_suspend(info, 1);
-       lcd_disable_raster();
-       clk_disable(par->lcdc_clk);
+       lcd_disable_raster(true);
+       lcd_context_save();
+       pm_runtime_put_sync(&dev->dev);
        console_unlock();
 
        return 0;
@@ -1423,11 +1577,14 @@ static int fb_resume(struct platform_device *dev)
        struct da8xx_fb_par *par = info->par;
 
        console_lock();
-       clk_enable(par->lcdc_clk);
-       lcd_enable_raster();
+       pm_runtime_get_sync(&dev->dev);
+       lcd_context_restore();
+       if (par->blank == FB_BLANK_UNBLANK) {
+               lcd_enable_raster();
 
-       if (par->panel_power_ctrl)
-               par->panel_power_ctrl(1);
+               if (par->panel_power_ctrl)
+                       par->panel_power_ctrl(1);
+       }
 
        fb_set_suspend(info, 0);
        console_unlock();
index f2c092da84b0fb85c4f628414f6a4dba235ffa81..755ef3e65caf4c980b8791cdfb2603dc3b576942 100644 (file)
@@ -529,7 +529,8 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
         * any of the framebuffer registers.
         */
        fbi->res = res;
-       fbi->mmio_base = ioremap(res->start, resource_size(res));
+       fbi->mmio_base = devm_ioremap(&pdev->dev, res->start,
+                                     resource_size(res));
        if (!fbi->mmio_base) {
                err = -ENXIO;
                goto failed_resource;
@@ -553,20 +554,20 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
        if (err == 0) {
                dev_err(info->dev, "No suitable video mode found\n");
                err = -EINVAL;
-               goto failed_mode;
+               goto failed_resource;
        }
 
        if (mach_info->setup) {
                err = mach_info->setup(pdev);
                if (err)
-                       goto failed_mode;
+                       goto failed_resource;
        }
 
        err = ep93xxfb_check_var(&info->var, info);
        if (err)
                goto failed_check;
 
-       fbi->clk = clk_get(info->dev, NULL);
+       fbi->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(fbi->clk)) {
                err = PTR_ERR(fbi->clk);
                fbi->clk = NULL;
@@ -578,19 +579,15 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
 
        err = register_framebuffer(info);
        if (err)
-               goto failed;
+               goto failed_check;
 
        dev_info(info->dev, "registered. Mode = %dx%d-%d\n",
                 info->var.xres, info->var.yres, info->var.bits_per_pixel);
        return 0;
 
-failed:
-       clk_put(fbi->clk);
 failed_check:
        if (fbi->mach_info->teardown)
                fbi->mach_info->teardown(pdev);
-failed_mode:
-       iounmap(fbi->mmio_base);
 failed_resource:
        ep93xxfb_dealloc_videomem(info);
 failed_videomem:
@@ -609,8 +606,6 @@ static int __devexit ep93xxfb_remove(struct platform_device *pdev)
 
        unregister_framebuffer(info);
        clk_disable(fbi->clk);
-       clk_put(fbi->clk);
-       iounmap(fbi->mmio_base);
        ep93xxfb_dealloc_videomem(info);
        fb_dealloc_cmap(&info->cmap);
 
index c6c016a506ce4e5799bc2582287ae39efeb787c7..d55470e754126f4b8d54d0b4586682aaa1b00991 100644 (file)
@@ -29,6 +29,9 @@ static int exynos_dp_init_dp(struct exynos_dp_device *dp)
 
        exynos_dp_swreset(dp);
 
+       exynos_dp_init_analog_param(dp);
+       exynos_dp_init_interrupt(dp);
+
        /* SW defined function Normal operation */
        exynos_dp_enable_sw_function(dp);
 
@@ -260,7 +263,7 @@ static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
 
 static void exynos_dp_link_start(struct exynos_dp_device *dp)
 {
-       u8 buf[5];
+       u8 buf[4];
        int lane;
        int lane_count;
 
@@ -295,10 +298,10 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
        exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
 
        /* Set RX training pattern */
-       buf[0] = DPCD_SCRAMBLING_DISABLED |
-                DPCD_TRAINING_PATTERN_1;
        exynos_dp_write_byte_to_dpcd(dp,
-               DPCD_ADDR_TRAINING_PATTERN_SET, buf[0]);
+               DPCD_ADDR_TRAINING_PATTERN_SET,
+               DPCD_SCRAMBLING_DISABLED |
+               DPCD_TRAINING_PATTERN_1);
 
        for (lane = 0; lane < lane_count; lane++)
                buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
@@ -308,7 +311,7 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
                lane_count, buf);
 }
 
-static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane)
+static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
 {
        int shift = (lane & 1) * 4;
        u8 link_value = link_status[lane>>1];
@@ -316,7 +319,7 @@ static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane)
        return (link_value >> shift) & 0xf;
 }
 
-static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count)
+static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
 {
        int lane;
        u8 lane_status;
@@ -329,22 +332,23 @@ static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count)
        return 0;
 }
 
-static int exynos_dp_channel_eq_ok(u8 link_status[6], int lane_count)
+static int exynos_dp_channel_eq_ok(u8 link_align[3], int lane_count)
 {
        int lane;
        u8 lane_align;
        u8 lane_status;
 
-       lane_align = link_status[2];
+       lane_align = link_align[2];
        if ((lane_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
                return -EINVAL;
 
        for (lane = 0; lane < lane_count; lane++) {
-               lane_status = exynos_dp_get_lane_status(link_status, lane);
+               lane_status = exynos_dp_get_lane_status(link_align, lane);
                lane_status &= DPCD_CHANNEL_EQ_BITS;
                if (lane_status != DPCD_CHANNEL_EQ_BITS)
                        return -EINVAL;
        }
+
        return 0;
 }
 
@@ -417,69 +421,17 @@ static unsigned int exynos_dp_get_lane_link_training(
 
 static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
 {
-       if (dp->link_train.link_rate == LINK_RATE_2_70GBPS) {
-               /* set to reduced bit rate */
-               dp->link_train.link_rate = LINK_RATE_1_62GBPS;
-               dev_err(dp->dev, "set to bandwidth %.2x\n",
-                       dp->link_train.link_rate);
-               dp->link_train.lt_state = START;
-       } else {
-               exynos_dp_training_pattern_dis(dp);
-               /* set enhanced mode if available */
-               exynos_dp_set_enhanced_mode(dp);
-               dp->link_train.lt_state = FAILED;
-       }
-}
+       exynos_dp_training_pattern_dis(dp);
+       exynos_dp_set_enhanced_mode(dp);
 
-static void exynos_dp_get_adjust_train(struct exynos_dp_device *dp,
-                               u8 adjust_request[2])
-{
-       int lane;
-       int lane_count;
-       u8 voltage_swing;
-       u8 pre_emphasis;
-       u8 training_lane;
-
-       lane_count = dp->link_train.lane_count;
-       for (lane = 0; lane < lane_count; lane++) {
-               voltage_swing = exynos_dp_get_adjust_request_voltage(
-                                               adjust_request, lane);
-               pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
-                                               adjust_request, lane);
-               training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
-                               DPCD_PRE_EMPHASIS_SET(pre_emphasis);
-
-               if (voltage_swing == VOLTAGE_LEVEL_3 ||
-                  pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
-                       training_lane |= DPCD_MAX_SWING_REACHED;
-                       training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
-               }
-               dp->link_train.training_lane[lane] = training_lane;
-       }
-}
-
-static int exynos_dp_check_max_cr_loop(struct exynos_dp_device *dp,
-                                       u8 voltage_swing)
-{
-       int lane;
-       int lane_count;
-
-       lane_count = dp->link_train.lane_count;
-       for (lane = 0; lane < lane_count; lane++) {
-               if (voltage_swing == VOLTAGE_LEVEL_3 ||
-                       dp->link_train.cr_loop[lane] == MAX_CR_LOOP)
-                       return -EINVAL;
-       }
-       return 0;
+       dp->link_train.lt_state = FAILED;
 }
 
 static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
 {
-       u8 data;
-       u8 link_status[6];
+       u8 link_status[2];
        int lane;
        int lane_count;
-       u8 buf[5];
 
        u8 adjust_request[2];
        u8 voltage_swing;
@@ -488,100 +440,154 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
 
        usleep_range(100, 101);
 
-       exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
-                               6, link_status);
        lane_count = dp->link_train.lane_count;
 
+       exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
+                               2, link_status);
+
        if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
                /* set training pattern 2 for EQ */
                exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
 
-               adjust_request[0] = link_status[4];
-               adjust_request[1] = link_status[5];
+               for (lane = 0; lane < lane_count; lane++) {
+                       exynos_dp_read_bytes_from_dpcd(dp,
+                                       DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
+                                       2, adjust_request);
+                       voltage_swing = exynos_dp_get_adjust_request_voltage(
+                                                       adjust_request, lane);
+                       pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
+                                                       adjust_request, lane);
+                       training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
+                                       DPCD_PRE_EMPHASIS_SET(pre_emphasis);
 
-               exynos_dp_get_adjust_train(dp, adjust_request);
+                       if (voltage_swing == VOLTAGE_LEVEL_3)
+                               training_lane |= DPCD_MAX_SWING_REACHED;
+                       if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
+                               training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
 
-               buf[0] = DPCD_SCRAMBLING_DISABLED |
-                        DPCD_TRAINING_PATTERN_2;
-               exynos_dp_write_byte_to_dpcd(dp,
-                       DPCD_ADDR_TRAINING_PATTERN_SET,
-                       buf[0]);
+                       dp->link_train.training_lane[lane] = training_lane;
 
-               for (lane = 0; lane < lane_count; lane++) {
                        exynos_dp_set_lane_link_training(dp,
                                dp->link_train.training_lane[lane],
                                lane);
-                       buf[lane] = dp->link_train.training_lane[lane];
-                       exynos_dp_write_byte_to_dpcd(dp,
-                               DPCD_ADDR_TRAINING_LANE0_SET + lane,
-                               buf[lane]);
                }
-               dp->link_train.lt_state = EQUALIZER_TRAINING;
-       } else {
-               exynos_dp_read_byte_from_dpcd(dp,
-                       DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
-                       &data);
-               adjust_request[0] = data;
 
-               exynos_dp_read_byte_from_dpcd(dp,
-                       DPCD_ADDR_ADJUST_REQUEST_LANE2_3,
-                       &data);
-               adjust_request[1] = data;
+               exynos_dp_write_byte_to_dpcd(dp,
+                       DPCD_ADDR_TRAINING_PATTERN_SET,
+                       DPCD_SCRAMBLING_DISABLED |
+                       DPCD_TRAINING_PATTERN_2);
+
+               exynos_dp_write_bytes_to_dpcd(dp,
+                       DPCD_ADDR_TRAINING_LANE0_SET,
+                       lane_count,
+                       dp->link_train.training_lane);
 
+               dev_info(dp->dev, "Link Training Clock Recovery success\n");
+               dp->link_train.lt_state = EQUALIZER_TRAINING;
+       } else {
                for (lane = 0; lane < lane_count; lane++) {
                        training_lane = exynos_dp_get_lane_link_training(
                                                        dp, lane);
+                       exynos_dp_read_bytes_from_dpcd(dp,
+                                       DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
+                                       2, adjust_request);
                        voltage_swing = exynos_dp_get_adjust_request_voltage(
                                                        adjust_request, lane);
                        pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
                                                        adjust_request, lane);
-                       if ((DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing) &&
-                           (DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis))
-                               dp->link_train.cr_loop[lane]++;
-                       dp->link_train.training_lane[lane] = training_lane;
-               }
 
-               if (exynos_dp_check_max_cr_loop(dp, voltage_swing) != 0) {
-                       exynos_dp_reduce_link_rate(dp);
-               } else {
-                       exynos_dp_get_adjust_train(dp, adjust_request);
+                       if (voltage_swing == VOLTAGE_LEVEL_3 ||
+                           pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
+                               dev_err(dp->dev, "voltage or pre emphasis reached max level\n");
+                               goto reduce_link_rate;
+                       }
 
-                       for (lane = 0; lane < lane_count; lane++) {
-                               exynos_dp_set_lane_link_training(dp,
-                                       dp->link_train.training_lane[lane],
-                                       lane);
-                               buf[lane] = dp->link_train.training_lane[lane];
-                               exynos_dp_write_byte_to_dpcd(dp,
-                                       DPCD_ADDR_TRAINING_LANE0_SET + lane,
-                                       buf[lane]);
+                       if ((DPCD_VOLTAGE_SWING_GET(training_lane) ==
+                                       voltage_swing) &&
+                          (DPCD_PRE_EMPHASIS_GET(training_lane) ==
+                                       pre_emphasis)) {
+                               dp->link_train.cr_loop[lane]++;
+                               if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP) {
+                                       dev_err(dp->dev, "CR Max loop\n");
+                                       goto reduce_link_rate;
+                               }
                        }
+
+                       training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
+                                       DPCD_PRE_EMPHASIS_SET(pre_emphasis);
+
+                       if (voltage_swing == VOLTAGE_LEVEL_3)
+                               training_lane |= DPCD_MAX_SWING_REACHED;
+                       if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
+                               training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
+
+                       dp->link_train.training_lane[lane] = training_lane;
+
+                       exynos_dp_set_lane_link_training(dp,
+                               dp->link_train.training_lane[lane], lane);
                }
+
+               exynos_dp_write_bytes_to_dpcd(dp,
+                       DPCD_ADDR_TRAINING_LANE0_SET,
+                       lane_count,
+                       dp->link_train.training_lane);
        }
 
        return 0;
+
+reduce_link_rate:
+       exynos_dp_reduce_link_rate(dp);
+       return -EIO;
 }
 
 static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
 {
-       u8 link_status[6];
+       u8 link_status[2];
+       u8 link_align[3];
        int lane;
        int lane_count;
-       u8 buf[5];
        u32 reg;
 
        u8 adjust_request[2];
+       u8 voltage_swing;
+       u8 pre_emphasis;
+       u8 training_lane;
 
        usleep_range(400, 401);
 
-       exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
-                               6, link_status);
        lane_count = dp->link_train.lane_count;
 
+       exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
+                               2, link_status);
+
        if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
-               adjust_request[0] = link_status[4];
-               adjust_request[1] = link_status[5];
+               link_align[0] = link_status[0];
+               link_align[1] = link_status[1];
 
-               if (exynos_dp_channel_eq_ok(link_status, lane_count) == 0) {
+               exynos_dp_read_byte_from_dpcd(dp,
+                       DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED,
+                       &link_align[2]);
+
+               for (lane = 0; lane < lane_count; lane++) {
+                       exynos_dp_read_bytes_from_dpcd(dp,
+                                       DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
+                                       2, adjust_request);
+                       voltage_swing = exynos_dp_get_adjust_request_voltage(
+                                                       adjust_request, lane);
+                       pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
+                                                       adjust_request, lane);
+                       training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
+                                       DPCD_PRE_EMPHASIS_SET(pre_emphasis);
+
+                       if (voltage_swing == VOLTAGE_LEVEL_3)
+                               training_lane |= DPCD_MAX_SWING_REACHED;
+                       if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
+                               training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
+
+                       dp->link_train.training_lane[lane] = training_lane;
+               }
+
+               if (exynos_dp_channel_eq_ok(link_align, lane_count) == 0) {
                        /* traing pattern Set to Normal */
                        exynos_dp_training_pattern_dis(dp);
 
@@ -596,39 +602,42 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
                        dp->link_train.lane_count = reg;
                        dev_dbg(dp->dev, "final lane count = %.2x\n",
                                dp->link_train.lane_count);
+
                        /* set enhanced mode if available */
                        exynos_dp_set_enhanced_mode(dp);
-
                        dp->link_train.lt_state = FINISHED;
                } else {
                        /* not all locked */
                        dp->link_train.eq_loop++;
 
                        if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
-                               exynos_dp_reduce_link_rate(dp);
-                       } else {
-                               exynos_dp_get_adjust_train(dp, adjust_request);
-
-                               for (lane = 0; lane < lane_count; lane++) {
-                                       exynos_dp_set_lane_link_training(dp,
-                                               dp->link_train.training_lane[lane],
-                                               lane);
-                                       buf[lane] = dp->link_train.training_lane[lane];
-                                       exynos_dp_write_byte_to_dpcd(dp,
-                                               DPCD_ADDR_TRAINING_LANE0_SET + lane,
-                                               buf[lane]);
-                               }
+                               dev_err(dp->dev, "EQ Max loop\n");
+                               goto reduce_link_rate;
                        }
+
+                       for (lane = 0; lane < lane_count; lane++)
+                               exynos_dp_set_lane_link_training(dp,
+                                       dp->link_train.training_lane[lane],
+                                       lane);
+
+                       exynos_dp_write_bytes_to_dpcd(dp,
+                               DPCD_ADDR_TRAINING_LANE0_SET,
+                               lane_count,
+                               dp->link_train.training_lane);
                }
        } else {
-               exynos_dp_reduce_link_rate(dp);
+               goto reduce_link_rate;
        }
 
        return 0;
+
+reduce_link_rate:
+       exynos_dp_reduce_link_rate(dp);
+       return -EIO;
 }
 
 static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
-                       u8 *bandwidth)
+                                       u8 *bandwidth)
 {
        u8 data;
 
@@ -641,7 +650,7 @@ static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
 }
 
 static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
-                       u8 *lane_count)
+                                       u8 *lane_count)
 {
        u8 data;
 
@@ -693,13 +702,7 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp,
 static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
 {
        int retval = 0;
-       int training_finished;
-
-       /* Turn off unnecessary lane */
-       if (dp->link_train.lane_count == 1)
-               exynos_dp_set_analog_power_down(dp, CH1_BLOCK, 1);
-
-       training_finished = 0;
+       int training_finished = 0;
 
        dp->link_train.lt_state = START;
 
@@ -710,10 +713,14 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
                        exynos_dp_link_start(dp);
                        break;
                case CLOCK_RECOVERY:
-                       exynos_dp_process_clock_recovery(dp);
+                       retval = exynos_dp_process_clock_recovery(dp);
+                       if (retval)
+                               dev_err(dp->dev, "LT CR failed!\n");
                        break;
                case EQUALIZER_TRAINING:
-                       exynos_dp_process_equalizer_training(dp);
+                       retval = exynos_dp_process_equalizer_training(dp);
+                       if (retval)
+                               dev_err(dp->dev, "LT EQ failed!\n");
                        break;
                case FINISHED:
                        training_finished = 1;
@@ -872,40 +879,33 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
 
        dp->dev = &pdev->dev;
 
-       dp->clock = clk_get(&pdev->dev, "dp");
+       dp->clock = devm_clk_get(&pdev->dev, "dp");
        if (IS_ERR(dp->clock)) {
                dev_err(&pdev->dev, "failed to get clock\n");
                return PTR_ERR(dp->clock);
        }
 
-       clk_enable(dp->clock);
+       clk_prepare_enable(dp->clock);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "failed to get registers\n");
-               ret = -EINVAL;
-               goto err_clock;
-       }
 
        dp->reg_base = devm_request_and_ioremap(&pdev->dev, res);
        if (!dp->reg_base) {
                dev_err(&pdev->dev, "failed to ioremap\n");
-               ret = -ENOMEM;
-               goto err_clock;
+               return -ENOMEM;
        }
 
        dp->irq = platform_get_irq(pdev, 0);
        if (!dp->irq) {
                dev_err(&pdev->dev, "failed to get irq\n");
-               ret = -ENODEV;
-               goto err_clock;
+               return -ENODEV;
        }
 
        ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
                                "exynos-dp", dp);
        if (ret) {
                dev_err(&pdev->dev, "failed to request irq\n");
-               goto err_clock;
+               return ret;
        }
 
        dp->video_info = pdata->video_info;
@@ -917,7 +917,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
        ret = exynos_dp_detect_hpd(dp);
        if (ret) {
                dev_err(&pdev->dev, "unable to detect hpd\n");
-               goto err_clock;
+               return ret;
        }
 
        exynos_dp_handle_edid(dp);
@@ -926,7 +926,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
                                dp->video_info->link_rate);
        if (ret) {
                dev_err(&pdev->dev, "unable to do link train\n");
-               goto err_clock;
+               return ret;
        }
 
        exynos_dp_enable_scramble(dp, 1);
@@ -940,17 +940,12 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
        ret = exynos_dp_config_video(dp, dp->video_info);
        if (ret) {
                dev_err(&pdev->dev, "unable to config video\n");
-               goto err_clock;
+               return ret;
        }
 
        platform_set_drvdata(pdev, dp);
 
        return 0;
-
-err_clock:
-       clk_put(dp->clock);
-
-       return ret;
 }
 
 static int __devexit exynos_dp_remove(struct platform_device *pdev)
@@ -961,8 +956,7 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
        if (pdata && pdata->phy_exit)
                pdata->phy_exit();
 
-       clk_disable(dp->clock);
-       clk_put(dp->clock);
+       clk_disable_unprepare(dp->clock);
 
        return 0;
 }
@@ -977,7 +971,7 @@ static int exynos_dp_suspend(struct device *dev)
        if (pdata && pdata->phy_exit)
                pdata->phy_exit();
 
-       clk_disable(dp->clock);
+       clk_disable_unprepare(dp->clock);
 
        return 0;
 }
@@ -991,7 +985,7 @@ static int exynos_dp_resume(struct device *dev)
        if (pdata && pdata->phy_init)
                pdata->phy_init();
 
-       clk_enable(dp->clock);
+       clk_prepare_enable(dp->clock);
 
        exynos_dp_init_dp(dp);
 
index 8526e548c3857a6ea299b457570afd482c964c4c..57b8a6531c0ea1fb58c9babf5423ed26c586f826 100644 (file)
@@ -43,7 +43,7 @@ void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
 void exynos_dp_reset(struct exynos_dp_device *dp);
 void exynos_dp_swreset(struct exynos_dp_device *dp);
 void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
-u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
+enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
 void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);
 void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
                                enum analog_power_block block,
@@ -105,7 +105,7 @@ u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
 u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
 u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
 void exynos_dp_reset_macro(struct exynos_dp_device *dp);
-int exynos_dp_init_video(struct exynos_dp_device *dp);
+void exynos_dp_init_video(struct exynos_dp_device *dp);
 
 void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
                                u32 color_depth,
@@ -144,7 +144,7 @@ void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
 #define DPCD_ADDR_TRAINING_PATTERN_SET         0x0102
 #define DPCD_ADDR_TRAINING_LANE0_SET           0x0103
 #define DPCD_ADDR_LANE0_1_STATUS               0x0202
-#define DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED   0x0204
+#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED    0x0204
 #define DPCD_ADDR_ADJUST_REQUEST_LANE0_1       0x0206
 #define DPCD_ADDR_ADJUST_REQUEST_LANE2_3       0x0207
 #define DPCD_ADDR_TEST_REQUEST                 0x0218
index 2db5b9aa250a067045d65b01aa0a281362db8d0e..3f5ca8a0d5ea45076d3929decfb514a1d9e5e52c 100644 (file)
@@ -77,7 +77,7 @@ void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
        writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
 
        reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
-               TX_CUR1_2X | TX_CUR_8_MA;
+               TX_CUR1_2X | TX_CUR_16_MA;
        writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
 
        reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
@@ -148,9 +148,6 @@ void exynos_dp_reset(struct exynos_dp_device *dp)
        writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
 
        writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-
-       exynos_dp_init_analog_param(dp);
-       exynos_dp_init_interrupt(dp);
 }
 
 void exynos_dp_swreset(struct exynos_dp_device *dp)
@@ -179,7 +176,7 @@ void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
        writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
 }
 
-u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
+enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
 {
        u32 reg;
 
@@ -401,6 +398,7 @@ int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
 {
        int reg;
        int retval = 0;
+       int timeout_loop = 0;
 
        /* Enable AUX CH operation */
        reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
@@ -409,8 +407,15 @@ int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
 
        /* Is AUX CH command reply received? */
        reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
-       while (!(reg & RPLY_RECEIV))
+       while (!(reg & RPLY_RECEIV)) {
+               timeout_loop++;
+               if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+                       dev_err(dp->dev, "AUX CH command reply failed!\n");
+                       return -ETIMEDOUT;
+               }
                reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
+               usleep_range(10, 11);
+       }
 
        /* Clear interrupt source for AUX CH command reply */
        writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
@@ -471,7 +476,8 @@ int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
                if (retval == 0)
                        break;
                else
-                       dev_err(dp->dev, "Aux Transaction fail!\n");
+                       dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+                               __func__);
        }
 
        return retval;
@@ -511,7 +517,8 @@ int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
                if (retval == 0)
                        break;
                else
-                       dev_err(dp->dev, "Aux Transaction fail!\n");
+                       dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+                               __func__);
        }
 
        /* Read data buffer */
@@ -575,7 +582,8 @@ int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
                        if (retval == 0)
                                break;
                        else
-                               dev_err(dp->dev, "Aux Transaction fail!\n");
+                               dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+                                       __func__);
                }
 
                start_offset += cur_data_count;
@@ -632,7 +640,8 @@ int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
                        if (retval == 0)
                                break;
                        else
-                               dev_err(dp->dev, "Aux Transaction fail!\n");
+                               dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+                                       __func__);
                }
 
                for (cur_data_idx = 0; cur_data_idx < cur_data_count;
@@ -677,7 +686,7 @@ int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
        /* Start AUX transaction */
        retval = exynos_dp_start_aux_transaction(dp);
        if (retval != 0)
-               dev_err(dp->dev, "Aux Transaction fail!\n");
+               dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
 
        return retval;
 }
@@ -717,7 +726,8 @@ int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
                if (retval == 0)
                        break;
                else
-                       dev_err(dp->dev, "Aux Transaction fail!\n");
+                       dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+                               __func__);
        }
 
        /* Read data */
@@ -777,7 +787,9 @@ int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
                                if (retval == 0)
                                        break;
                                else
-                                       dev_err(dp->dev, "Aux Transaction fail!\n");
+                                       dev_dbg(dp->dev,
+                                               "%s: Aux Transaction fail!\n",
+                                               __func__);
                        }
                        /* Check if Rx sends defer */
                        reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
@@ -883,7 +895,9 @@ void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)
 {
        u32 reg;
 
-       reg = level << PRE_EMPHASIS_SET_SHIFT;
+       reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
+       reg &= ~PRE_EMPHASIS_SET_MASK;
+       reg |= level << PRE_EMPHASIS_SET_SHIFT;
        writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
 }
 
@@ -891,7 +905,9 @@ void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)
 {
        u32 reg;
 
-       reg = level << PRE_EMPHASIS_SET_SHIFT;
+       reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
+       reg &= ~PRE_EMPHASIS_SET_MASK;
+       reg |= level << PRE_EMPHASIS_SET_SHIFT;
        writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
 }
 
@@ -899,7 +915,9 @@ void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)
 {
        u32 reg;
 
-       reg = level << PRE_EMPHASIS_SET_SHIFT;
+       reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
+       reg &= ~PRE_EMPHASIS_SET_MASK;
+       reg |= level << PRE_EMPHASIS_SET_SHIFT;
        writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
 }
 
@@ -907,7 +925,9 @@ void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)
 {
        u32 reg;
 
-       reg = level << PRE_EMPHASIS_SET_SHIFT;
+       reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
+       reg &= ~PRE_EMPHASIS_SET_MASK;
+       reg |= level << PRE_EMPHASIS_SET_SHIFT;
        writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
 }
 
@@ -994,7 +1014,7 @@ void exynos_dp_reset_macro(struct exynos_dp_device *dp)
        writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
 }
 
-int exynos_dp_init_video(struct exynos_dp_device *dp)
+void exynos_dp_init_video(struct exynos_dp_device *dp)
 {
        u32 reg;
 
@@ -1012,8 +1032,6 @@ int exynos_dp_init_video(struct exynos_dp_device *dp)
 
        reg = VID_HRES_TH(2) | VID_VRES_TH(0);
        writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
-
-       return 0;
 }
 
 void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
index 125b27cd57aebd3f44acf997cf08f711928b61dd..1f2f014cfe88687c323428ba31c1e29c1cac9c2e 100644 (file)
 #define PD_RING_OSC                            (0x1 << 6)
 #define AUX_TERMINAL_CTRL_50_OHM               (0x2 << 4)
 #define TX_CUR1_2X                             (0x1 << 2)
-#define TX_CUR_8_MA                            (0x2 << 0)
+#define TX_CUR_16_MA                           (0x3 << 0)
 
 /* EXYNOS_DP_TX_AMP_TUNING_CTL */
 #define CH3_AMP_400_MV                         (0x0 << 24)
 #define SW_TRAINING_PATTERN_SET_NORMAL         (0x0 << 0)
 
 /* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
+#define PRE_EMPHASIS_SET_MASK                  (0x3 << 3)
 #define PRE_EMPHASIS_SET_SHIFT                 (3)
 
 /* EXYNOS_DP_DEBUG_CTL */
index 663c308d0e73291c22632cbb6291ccb3e34e813b..07d70a3a628bfc987018131538281b1b6484ed17 100644 (file)
@@ -205,7 +205,8 @@ int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
        return 0;
 }
 
-struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(struct mipi_dsim_lcd_driver *lcd_drv)
+static struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(
+                                       struct mipi_dsim_lcd_driver *lcd_drv)
 {
        struct mipi_dsim_ddi *dsim_ddi, *next;
        struct mipi_dsim_lcd_device *lcd_dev;
@@ -265,7 +266,8 @@ int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
 
 }
 
-struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device *dsim,
+static struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(
+                                               struct mipi_dsim_device *dsim,
                                                const char *name)
 {
        struct mipi_dsim_ddi *dsim_ddi, *next;
@@ -373,6 +375,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)
        dsim->clock = clk_get(&pdev->dev, "dsim0");
        if (IS_ERR(dsim->clock)) {
                dev_err(&pdev->dev, "failed to get dsim clock source\n");
+               ret = -ENODEV;
                goto err_clock_get;
        }
 
@@ -381,6 +384,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(&pdev->dev, "failed to get io memory region\n");
+               ret = -ENODEV;
                goto err_platform_get;
        }
 
@@ -405,6 +409,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)
        dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);
        if (!dsim_ddi) {
                dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n");
+               ret = -EINVAL;
                goto err_bind;
        }
 
index 47b533a183be2979ede8a29bb9db0d89b0e309bb..3cd29a4fc10af93cf4fc0329fc27e57857211185 100644 (file)
@@ -79,11 +79,6 @@ irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id)
        struct mipi_dsim_device *dsim = dev_id;
        unsigned int intsrc, intmsk;
 
-       if (dsim == NULL) {
-               dev_err(dsim->dev, "%s: wrong parameter\n", __func__);
-               return IRQ_NONE;
-       }
-
        intsrc = exynos_mipi_dsi_read_interrupt(dsim);
        intmsk = exynos_mipi_dsi_read_interrupt_mask(dsim);
        intmsk = ~intmsk & intsrc;
@@ -288,9 +283,6 @@ int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
                mutex_unlock(&dsim->lock);
                return -EINVAL;
        }
-
-       mutex_unlock(&dsim->lock);
-       return 0;
 }
 
 static unsigned int exynos_mipi_dsi_long_data_rd(struct mipi_dsim_device *dsim,
index 458c00664ade6110a6b26d58397086b2b1d4290f..ede9e55413f80ad33e932f48c652785069bb2fb8 100644 (file)
@@ -1501,8 +1501,8 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
        unsigned int i;
        int ret;
 
-       data = dma_alloc_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
-                                 &dma_addr, GFP_DMA | __GFP_ZERO);
+       data = dmam_alloc_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
+                                  &dma_addr, GFP_DMA | __GFP_ZERO);
        if (!data)
                return -ENOMEM;
        data->dma_addr = dma_addr;
@@ -1628,9 +1628,6 @@ error:
 
        iounmap(data->diu_reg);
 
-       dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data,
-                         data->dma_addr);
-
        return ret;
 }
 
@@ -1648,9 +1645,6 @@ static int fsl_diu_remove(struct platform_device *pdev)
 
        iounmap(data->diu_reg);
 
-       dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data,
-                         data->dma_addr);
-
        return 0;
 }
 
index 05e2a8a99d8fbc63545da7625298e6a895ba5c6c..3dad31975db8cceaf8fe16963d3ca1d37180b85e 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/module.h>
+#include <linux/io.h>
 
 #ifdef CONFIG_X86
 #include <asm/mtrr.h>
@@ -28,7 +29,6 @@
 #include <asm/addrspace.h>
 #endif
 #include <asm/byteorder.h>
-#include <asm/io.h>
 #include <asm/tlbflush.h>
 
 #include <video/gbe.h>
@@ -1156,7 +1156,8 @@ static int __devinit gbefb_probe(struct platform_device *p_dev)
                goto out_release_framebuffer;
        }
 
-       gbe = (struct sgi_gbe *) ioremap(GBE_BASE, sizeof(struct sgi_gbe));
+       gbe = (struct sgi_gbe *) devm_ioremap(&p_dev->dev, GBE_BASE,
+                                             sizeof(struct sgi_gbe));
        if (!gbe) {
                printk(KERN_ERR "gbefb: couldn't map mmio region\n");
                ret = -ENXIO;
@@ -1170,12 +1171,13 @@ static int __devinit gbefb_probe(struct platform_device *p_dev)
        if (!gbe_tiles.cpu) {
                printk(KERN_ERR "gbefb: couldn't allocate tiles table\n");
                ret = -ENOMEM;
-               goto out_unmap;
+               goto out_release_mem_region;
        }
 
        if (gbe_mem_phys) {
                /* memory was allocated at boot time */
-               gbe_mem = ioremap_nocache(gbe_mem_phys, gbe_mem_size);
+               gbe_mem = devm_ioremap_nocache(&p_dev->dev, gbe_mem_phys,
+                                              gbe_mem_size);
                if (!gbe_mem) {
                        printk(KERN_ERR "gbefb: couldn't map framebuffer\n");
                        ret = -ENOMEM;
@@ -1241,13 +1243,9 @@ static int __devinit gbefb_probe(struct platform_device *p_dev)
 out_gbe_unmap:
        if (gbe_dma_addr)
                dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
-       else
-               iounmap(gbe_mem);
 out_tiles_free:
        dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
                          (void *)gbe_tiles.cpu, gbe_tiles.dma);
-out_unmap:
-       iounmap(gbe);
 out_release_mem_region:
        release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
 out_release_framebuffer:
@@ -1264,12 +1262,9 @@ static int __devexit gbefb_remove(struct platform_device* p_dev)
        gbe_turn_off();
        if (gbe_dma_addr)
                dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
-       else
-               iounmap(gbe_mem);
        dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
                          (void *)gbe_tiles.cpu, gbe_tiles.dma);
        release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
-       iounmap(gbe);
        gbefb_remove_sysfs(&p_dev->dev);
        framebuffer_release(info);
 
index ebf8495ff198b601220ee25b43545b4efe65b3b9..7324865f965f4c5c1d9c5fe4639dbb8f66f39808 100644 (file)
@@ -210,6 +210,7 @@ static int __devinit hpfb_init_one(unsigned long phys_base,
                                   unsigned long virt_base)
 {
        unsigned long fboff, fb_width, fb_height, fb_start;
+       int ret;
 
        fb_regs = virt_base;
        fboff = (in_8(fb_regs + HPFB_FBOMSB) << 8) | in_8(fb_regs + HPFB_FBOLSB);
@@ -290,19 +291,29 @@ static int __devinit hpfb_init_one(unsigned long phys_base,
        fb_info.var   = hpfb_defined;
        fb_info.screen_base = (char *)fb_start;
 
-       fb_alloc_cmap(&fb_info.cmap, 1 << hpfb_defined.bits_per_pixel, 0);
+       ret = fb_alloc_cmap(&fb_info.cmap, 1 << hpfb_defined.bits_per_pixel, 0);
+       if (ret < 0)
+               goto unmap_screen_base;
 
-       if (register_framebuffer(&fb_info) < 0) {
-               fb_dealloc_cmap(&fb_info.cmap);
-               iounmap(fb_info.screen_base);
-               fb_info.screen_base = NULL;
-               return 1;
-       }
+       ret = register_framebuffer(&fb_info);
+       if (ret < 0)
+               goto dealloc_cmap;
 
        printk(KERN_INFO "fb%d: %s frame buffer device\n",
               fb_info.node, fb_info.fix.id);
 
        return 0;
+
+dealloc_cmap:
+       fb_dealloc_cmap(&fb_info.cmap);
+
+unmap_screen_base:
+       if (fb_info.screen_base) {
+               iounmap(fb_info.screen_base);
+               fb_info.screen_base = NULL;
+       }
+
+       return ret;
 }
 
 /* 
@@ -345,6 +356,9 @@ static void __devexit hpfb_remove_one(struct dio_dev *d)
        if (d->scode >= DIOII_SCBASE)
                iounmap((void *)fb_regs);
        release_mem_region(d->resource.start, resource_size(&d->resource));
+       fb_dealloc_cmap(&fb_info.cmap);
+       if (fb_info.screen_base)
+               iounmap(fb_info.screen_base);
 }
 
 static struct dio_device_id hpfb_dio_tbl[] = {
index 53ffdfc82a75f18616b08b469cee6682595de989..cf2688de083244c2ab25da05638c6edb2d7e3a47 100644 (file)
@@ -803,6 +803,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
        fbi->regs = ioremap(res->start, resource_size(res));
        if (fbi->regs == NULL) {
                dev_err(&pdev->dev, "Cannot map frame buffer registers\n");
+               ret = -ENOMEM;
                goto failed_ioremap;
        }
 
index 3c63fc24bb1f139c197e430d4889aa2b443be706..4d25711b99829926c9033d77240265025efecaa7 100644 (file)
@@ -632,23 +632,10 @@ static int __devinit jzfb_probe(struct platform_device *pdev)
                return -ENXIO;
        }
 
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!mem) {
-               dev_err(&pdev->dev, "Failed to get register memory resource\n");
-               return -ENXIO;
-       }
-
-       mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
-       if (!mem) {
-               dev_err(&pdev->dev, "Failed to request register memory region\n");
-               return -EBUSY;
-       }
-
        fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
        if (!fb) {
                dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
-               ret = -ENOMEM;
-               goto err_release_mem_region;
+               return -ENOMEM;
        }
 
        fb->fbops = &jzfb_ops;
@@ -657,27 +644,26 @@ static int __devinit jzfb_probe(struct platform_device *pdev)
        jzfb = fb->par;
        jzfb->pdev = pdev;
        jzfb->pdata = pdata;
-       jzfb->mem = mem;
 
-       jzfb->ldclk = clk_get(&pdev->dev, "lcd");
+       jzfb->ldclk = devm_clk_get(&pdev->dev, "lcd");
        if (IS_ERR(jzfb->ldclk)) {
                ret = PTR_ERR(jzfb->ldclk);
                dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);
                goto err_framebuffer_release;
        }
 
-       jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk");
+       jzfb->lpclk = devm_clk_get(&pdev->dev, "lcd_pclk");
        if (IS_ERR(jzfb->lpclk)) {
                ret = PTR_ERR(jzfb->lpclk);
                dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret);
-               goto err_put_ldclk;
+               goto err_framebuffer_release;
        }
 
-       jzfb->base = ioremap(mem->start, resource_size(mem));
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       jzfb->base = devm_request_and_ioremap(&pdev->dev, mem);
        if (!jzfb->base) {
-               dev_err(&pdev->dev, "Failed to ioremap register memory region\n");
                ret = -EBUSY;
-               goto err_put_lpclk;
+               goto err_framebuffer_release;
        }
 
        platform_set_drvdata(pdev, jzfb);
@@ -693,7 +679,7 @@ static int __devinit jzfb_probe(struct platform_device *pdev)
        ret = jzfb_alloc_devmem(jzfb);
        if (ret) {
                dev_err(&pdev->dev, "Failed to allocate video memory\n");
-               goto err_iounmap;
+               goto err_framebuffer_release;
        }
 
        fb->fix = jzfb_fix;
@@ -734,16 +720,8 @@ err_free_devmem:
 
        fb_dealloc_cmap(&fb->cmap);
        jzfb_free_devmem(jzfb);
-err_iounmap:
-       iounmap(jzfb->base);
-err_put_lpclk:
-       clk_put(jzfb->lpclk);
-err_put_ldclk:
-       clk_put(jzfb->ldclk);
 err_framebuffer_release:
        framebuffer_release(fb);
-err_release_mem_region:
-       release_mem_region(mem->start, resource_size(mem));
        return ret;
 }
 
@@ -756,17 +734,11 @@ static int __devexit jzfb_remove(struct platform_device *pdev)
        jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
        jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
 
-       iounmap(jzfb->base);
-       release_mem_region(jzfb->mem->start, resource_size(jzfb->mem));
-
        fb_dealloc_cmap(&jzfb->fb->cmap);
        jzfb_free_devmem(jzfb);
 
        platform_set_drvdata(pdev, NULL);
 
-       clk_put(jzfb->lpclk);
-       clk_put(jzfb->ldclk);
-
        framebuffer_release(jzfb->fb);
 
        return 0;
index 57d940be5f3d7eaa25b2358c83e169947a779bdf..d68e332aa21c39d963b37bc3e7f5039a01c8c85c 100644 (file)
@@ -1052,12 +1052,14 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
                break;
        default:
                /* should never occur */
+               ret = -EIO;
                goto rel_reg;
        }
 
        par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram);
        if (par->fb_base == NULL) {
                dev_err(dev, "Cannot map framebuffer\n");
+               ret = -EIO;
                goto rel_reg;
        }
 
@@ -1073,11 +1075,13 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
        dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n",
                (unsigned long long)par->mmio_base_phys, (ulong)par->mmio_len);
 
-       if (mb862xx_pci_gdc_init(par))
+       ret = mb862xx_pci_gdc_init(par);
+       if (ret)
                goto io_unmap;
 
-       if (request_irq(par->irq, mb862xx_intr, IRQF_SHARED,
-                       DRV_NAME, (void *)par)) {
+       ret = request_irq(par->irq, mb862xx_intr, IRQF_SHARED,
+                         DRV_NAME, (void *)par);
+       if (ret) {
                dev_err(dev, "Cannot request irq\n");
                goto io_unmap;
        }
index 85e4f44bfa61df1e5ab463b326d881bac37c544b..6563e50413c1c01dde5e703281ee47cac459f4b6 100644 (file)
@@ -26,8 +26,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/uaccess.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
 
 #include <video/mbxfb.h>
 
@@ -939,8 +938,9 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
        }
        mfbi->reg_phys_addr = mfbi->reg_res->start;
 
-       mfbi->reg_virt_addr = ioremap_nocache(mfbi->reg_phys_addr,
-                                             res_size(mfbi->reg_req));
+       mfbi->reg_virt_addr = devm_ioremap_nocache(&dev->dev,
+                                                  mfbi->reg_phys_addr,
+                                                  res_size(mfbi->reg_req));
        if (!mfbi->reg_virt_addr) {
                dev_err(&dev->dev, "failed to ioremap Marathon registers\n");
                ret = -EINVAL;
@@ -948,12 +948,12 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
        }
        virt_base_2700 = mfbi->reg_virt_addr;
 
-       mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr,
-                                            res_size(mfbi->fb_req));
+       mfbi->fb_virt_addr = devm_ioremap_nocache(&dev->dev, mfbi->fb_phys_addr,
+                                                 res_size(mfbi->fb_req));
        if (!mfbi->fb_virt_addr) {
                dev_err(&dev->dev, "failed to ioremap frame buffer\n");
                ret = -EINVAL;
-               goto err4;
+               goto err3;
        }
 
        fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000);
@@ -971,7 +971,7 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
        if (ret < 0) {
                dev_err(&dev->dev, "fb_alloc_cmap failed\n");
                ret = -EINVAL;
-               goto err5;
+               goto err3;
        }
 
        platform_set_drvdata(dev, fbi);
@@ -996,10 +996,6 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
 
 err6:
        fb_dealloc_cmap(&fbi->cmap);
-err5:
-       iounmap(mfbi->fb_virt_addr);
-err4:
-       iounmap(mfbi->reg_virt_addr);
 err3:
        release_mem_region(mfbi->reg_res->start, res_size(mfbi->reg_res));
 err2:
@@ -1026,10 +1022,7 @@ static int __devexit mbxfb_remove(struct platform_device *dev)
                        if (mfbi->platform_remove)
                                mfbi->platform_remove(fbi);
 
-                       if (mfbi->fb_virt_addr)
-                               iounmap(mfbi->fb_virt_addr);
-                       if (mfbi->reg_virt_addr)
-                               iounmap(mfbi->reg_virt_addr);
+
                        if (mfbi->reg_req)
                                release_mem_region(mfbi->reg_req->start,
                                                   res_size(mfbi->reg_req));
index bf73f048006183da73d75377faddce1d143917d2..35ac9e8bee63f13a30133382dca3a8f43aa7a25d 100644 (file)
@@ -26,9 +26,6 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/sched.h>
-#include <mach/msm_iomap.h>
-#include <mach/irqs.h>
-#include <mach/board.h>
 #include <linux/platform_data/video-msm_fb.h>
 #include "mddi_hw.h"
 
index d7a5bf84fb2ac07a08eda5957fd179981ed4dca0..f96df32e5509a4581209cb867827c2ba35c68305 100644 (file)
@@ -189,8 +189,9 @@ static int mddi_nt35399_probe(struct platform_device *pdev)
 
        int ret;
 
-       struct panel_info *panel = kzalloc(sizeof(struct panel_info),
-                                          GFP_KERNEL);
+       struct panel_info *panel = devm_kzalloc(&pdev->dev,
+                                               sizeof(struct panel_info),
+                                               GFP_KERNEL);
 
        printk(KERN_DEBUG "%s: enter.\n", __func__);
 
@@ -233,7 +234,6 @@ static int mddi_nt35399_remove(struct platform_device *pdev)
        struct panel_info *panel = platform_get_drvdata(pdev);
 
        setup_vsync(panel, 0);
-       kfree(panel);
        return 0;
 }
 
index 2e0f3bab61143410971a45f3686f0796823bdd21..f2566c19e71cb10442e42552e9c492b5a3ba1db8 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 
-#include <mach/msm_iomap.h>
 #include <linux/platform_data/video-msm_fb.h>
 #include <linux/platform_device.h>
 #include <linux/export.h>
index a0bacf581b32896deb3186168c08808791e733fa..35848d7410015f60ca5c64272557091cb5dc39a8 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef _MDP_HW_H_
 #define _MDP_HW_H_
 
-#include <mach/msm_iomap.h>
 #include <linux/platform_data/video-msm_fb.h>
 
 struct mdp_info {
index d7381088a180fc21bc655e1e63a2a0d431211021..ce1d452464ed5171d537346bdd1a0132a7d321d1 100644 (file)
@@ -1568,7 +1568,8 @@ static int mx3fb_remove(struct platform_device *dev)
 
 static struct platform_driver mx3fb_driver = {
        .driver = {
-                  .name = MX3FB_NAME,
+               .name = MX3FB_NAME,
+               .owner = THIS_MODULE,
        },
        .probe = mx3fb_probe,
        .remove = mx3fb_remove,
index 93387555337e6a35170625b1385c264be81338f5..475dfee82c4a1207e7ce1107e6a94fd6b49f1a46 100644 (file)
@@ -387,7 +387,7 @@ static int nuc900fb_init_registers(struct fb_info *info)
  *    The buffer should be a non-cached, non-buffered, memory region
  *    to allow palette and pixel writes without flushing the cache.
  */
-static int __init nuc900fb_map_video_memory(struct fb_info *info)
+static int __devinit nuc900fb_map_video_memory(struct fb_info *info)
 {
        struct nuc900fb_info *fbi = info->par;
        dma_addr_t map_dma;
index 9f1d23c319cb0bb8b920fbd11b39ede3fe4f68d4..f349ee6f0ceafd6ee490835e2931f973f5e4c020 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/clk.h>
 #include <linux/interrupt.h>
 
-#include <plat/dma.h>
 #include "omapfb.h"
 
 #define HWA742_REV_CODE_REG       0x0
index 88c31eb0cd6c7768ad84d72f504fc1fb0f63a855..ff4fb624b9043aac47ca57b3f71778b5ba7f9f51 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
-#include <plat/fpga.h>
 #include "omapfb.h"
 
 static int palmte_panel_init(struct lcd_panel *panel,
index f54b463709e9f5808f37bf4bb187da6a560fb06e..4351c438b76f5f52cd0ea7f03c28c1b9cb48492d 100644 (file)
@@ -131,15 +131,6 @@ static void omapfb_rqueue_unlock(struct omapfb_device *fbdev)
  * LCD controller and LCD DMA
  * ---------------------------------------------------------------------------
  */
-/* Lookup table to map elem size to elem type. */
-static const int dma_elem_type[] = {
-       0,
-       OMAP_DMA_DATA_TYPE_S8,
-       OMAP_DMA_DATA_TYPE_S16,
-       0,
-       OMAP_DMA_DATA_TYPE_S32,
-};
-
 /*
  * Allocate resources needed for LCD controller and LCD DMA operations. Video
  * memory is allocated from system memory according to the virtual display
index eaeed4340e04eaf49afd176ec3f95ed2b56d8734..c835aa70f96fb64829e7b7a8f8a328a64dd720e3 100644 (file)
@@ -600,6 +600,9 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
 
        mutex_lock(&md->mutex);
 
+       omapdss_sdi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_sdi_set_datapairs(dssdev, dssdev->phy.sdi.datapairs);
+
        r = omapdss_sdi_display_enable(dssdev);
        if (r) {
                pr_err("%s sdi enable failed\n", __func__);
@@ -731,18 +734,9 @@ static int acx_panel_resume(struct omap_dss_device *dssdev)
 static void acx_panel_set_timings(struct omap_dss_device *dssdev,
                struct omap_video_timings *timings)
 {
-       int r;
-
-       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
-               omapdss_sdi_display_disable(dssdev);
+       omapdss_sdi_set_timings(dssdev, timings);
 
        dssdev->panel.timings = *timings;
-
-       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
-               r = omapdss_sdi_display_enable(dssdev);
-               if (r)
-                       dev_err(&dssdev->dev, "%s enable failed\n", __func__);
-       }
 }
 
 static int acx_panel_check_timings(struct omap_dss_device *dssdev,
index bc5af2500eb923952a9c7a80aaedfb430ee50974..88295c526815e76a628e1e5641902e1ceac0b07d 100644 (file)
@@ -545,6 +545,8 @@ struct panel_drv_data {
        struct omap_dss_device *dssdev;
 
        struct panel_config *panel_config;
+
+       struct mutex lock;
 };
 
 static inline struct panel_generic_dpi_data
@@ -563,6 +565,9 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
@@ -634,6 +639,8 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
        drv_data->dssdev = dssdev;
        drv_data->panel_config = panel_config;
 
+       mutex_init(&drv_data->lock);
+
        dev_set_drvdata(&dssdev->dev, drv_data);
 
        return 0;
@@ -652,56 +659,108 @@ static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
 
 static int generic_dpi_panel_enable(struct omap_dss_device *dssdev)
 {
-       int r = 0;
+       struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+       int r;
+
+       mutex_lock(&drv_data->lock);
 
        r = generic_dpi_panel_power_on(dssdev);
        if (r)
-               return r;
+               goto err;
 
        dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+err:
+       mutex_unlock(&drv_data->lock);
 
-       return 0;
+       return r;
 }
 
 static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
 {
+       struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&drv_data->lock);
+
        generic_dpi_panel_power_off(dssdev);
 
        dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+       mutex_unlock(&drv_data->lock);
 }
 
 static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
 {
+       struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&drv_data->lock);
+
        generic_dpi_panel_power_off(dssdev);
 
        dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
 
+       mutex_unlock(&drv_data->lock);
+
        return 0;
 }
 
 static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
 {
-       int r = 0;
+       struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+       int r;
+
+       mutex_lock(&drv_data->lock);
 
        r = generic_dpi_panel_power_on(dssdev);
        if (r)
-               return r;
+               goto err;
 
        dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
 
-       return 0;
+err:
+       mutex_unlock(&drv_data->lock);
+
+       return r;
 }
 
 static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
                struct omap_video_timings *timings)
 {
-       dpi_set_timings(dssdev, timings);
+       struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&drv_data->lock);
+
+       omapdss_dpi_set_timings(dssdev, timings);
+
+       dssdev->panel.timings = *timings;
+
+       mutex_unlock(&drv_data->lock);
+}
+
+static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&drv_data->lock);
+
+       *timings = dssdev->panel.timings;
+
+       mutex_unlock(&drv_data->lock);
 }
 
 static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
                struct omap_video_timings *timings)
 {
-       return dpi_check_timings(dssdev, timings);
+       struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+       int r;
+
+       mutex_lock(&drv_data->lock);
+
+       r = dpi_check_timings(dssdev, timings);
+
+       mutex_unlock(&drv_data->lock);
+
+       return r;
 }
 
 static struct omap_dss_driver dpi_driver = {
@@ -714,6 +773,7 @@ static struct omap_dss_driver dpi_driver = {
        .resume         = generic_dpi_panel_resume,
 
        .set_timings    = generic_dpi_panel_set_timings,
+       .get_timings    = generic_dpi_panel_get_timings,
        .check_timings  = generic_dpi_panel_check_timings,
 
        .driver         = {
index 802807798846a3ff976019784b51158f16df4b66..90c1cabf244e183ea7572b083a3a2b9a9fa3cc69 100644 (file)
@@ -55,6 +55,9 @@ static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
index e6c115373c0088cce331cb9bcf74aae22ec10830..3fc5ad081a212906c92c69497436ddbe08a8807f 100644 (file)
@@ -150,11 +150,17 @@ static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
                        BLIZZARD_SRC_WRITE_LCD :
                        BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
 
-       omap_rfbi_configure(dssdev, 16, 8);
+       omapdss_rfbi_set_pixel_size(dssdev, 16);
+       omapdss_rfbi_set_data_lines(dssdev, 8);
+
+       omap_rfbi_configure(dssdev);
 
        blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
 
-       omap_rfbi_configure(dssdev, 16, 16);
+       omapdss_rfbi_set_pixel_size(dssdev, 16);
+       omapdss_rfbi_set_data_lines(dssdev, 16);
+
+       omap_rfbi_configure(dssdev);
 }
 
 static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
@@ -297,6 +303,12 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
                        goto err_plat_en;
        }
 
+       omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
+               dssdev->panel.timings.y_res);
+       omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
+       omapdss_rfbi_set_data_lines(dssdev, dssdev->phy.rfbi.data_lines);
+       omapdss_rfbi_set_interface_timings(dssdev, &dssdev->ctrl.rfbi_timings);
+
        r = omapdss_rfbi_display_enable(dssdev);
        if (r)
                goto err_rfbi_en;
@@ -477,6 +489,7 @@ static int n8x0_panel_probe(struct omap_dss_device *dssdev)
        dssdev->panel.timings.y_res = 480;
        dssdev->ctrl.pixel_size = 16;
        dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
+       dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
 
        memset(&props, 0, sizeof(props));
        props.max_brightness = 127;
@@ -625,17 +638,25 @@ static int n8x0_panel_update(struct omap_dss_device *dssdev,
                u16 x, u16 y, u16 w, u16 h)
 {
        struct panel_drv_data *ddata = get_drv_data(dssdev);
+       u16 dw, dh;
 
        dev_dbg(&dssdev->dev, "update\n");
 
+       dw = dssdev->panel.timings.x_res;
+       dh = dssdev->panel.timings.y_res;
+
+       if (x != 0 || y != 0 || w != dw || h != dh) {
+               dev_err(&dssdev->dev, "invaid update region %d, %d, %d, %d\n",
+                       x, y, w, h);
+               return -EINVAL;
+       }
+
        mutex_lock(&ddata->lock);
        rfbi_bus_lock();
 
-       omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h);
-
        blizzard_ctrl_setup_update(dssdev, x, y, w, h);
 
-       omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL);
+       omap_rfbi_update(dssdev, update_done, NULL);
 
        mutex_unlock(&ddata->lock);
 
index b122b0f31c43b34602a0f8215ca8106819ea3512..908fd268f3dc90fd98b3eb4827166a5f5e94214f 100644 (file)
@@ -175,6 +175,9 @@ static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
index 2d35bd388860001c08ddbaf5cc1a551764a2f5a5..9df87640ddd2b0ed574d93e30c69492756167628 100644 (file)
@@ -377,6 +377,10 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
         * then only i2c commands can be successfully sent to dpp2600
         */
        msleep(1000);
+
+       omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r) {
                dev_err(&dssdev->dev, "failed to enable DPI\n");
index bd86ba9ccf7600bed53c29c257e164c7dda763ec..1ec3b277ff155edca2861be48f3d013b01334aa1 100644 (file)
@@ -142,6 +142,9 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
index 6b5e6e0e202f253cada3b80ddf5d14db9b4b0bd7..f2f644680ca8dfe2262fac39c42fcd50766982f0 100644 (file)
@@ -121,6 +121,18 @@ struct taal_data {
 
        struct omap_dss_device *dssdev;
 
+       /* panel specific HW info */
+       struct panel_config *panel_config;
+
+       /* panel HW configuration from DT or platform data */
+       int reset_gpio;
+       int ext_te_gpio;
+
+       bool use_dsi_backlight;
+
+       struct omap_dsi_pin_config pin_config;
+
+       /* runtime variables */
        bool enabled;
        u8 rotate;
        bool mirror;
@@ -145,16 +157,8 @@ struct taal_data {
        bool ulps_enabled;
        unsigned ulps_timeout;
        struct delayed_work ulps_work;
-
-       struct panel_config *panel_config;
 };
 
-static inline struct nokia_dsi_panel_data
-*get_panel_data(const struct omap_dss_device *dssdev)
-{
-       return (struct nokia_dsi_panel_data *) dssdev->data;
-}
-
 static void taal_esd_work(struct work_struct *work);
 static void taal_ulps_work(struct work_struct *work);
 
@@ -371,7 +375,6 @@ static void taal_cancel_ulps_work(struct omap_dss_device *dssdev)
 static int taal_enter_ulps(struct omap_dss_device *dssdev)
 {
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-       struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
        int r;
 
        if (td->ulps_enabled)
@@ -383,7 +386,8 @@ static int taal_enter_ulps(struct omap_dss_device *dssdev)
        if (r)
                goto err;
 
-       disable_irq(gpio_to_irq(panel_data->ext_te_gpio));
+       if (gpio_is_valid(td->ext_te_gpio))
+               disable_irq(gpio_to_irq(td->ext_te_gpio));
 
        omapdss_dsi_display_disable(dssdev, false, true);
 
@@ -405,7 +409,6 @@ err:
 static int taal_exit_ulps(struct omap_dss_device *dssdev)
 {
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-       struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
        int r;
 
        if (!td->ulps_enabled)
@@ -425,7 +428,8 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
                goto err2;
        }
 
-       enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
+       if (gpio_is_valid(td->ext_te_gpio))
+               enable_irq(gpio_to_irq(td->ext_te_gpio));
 
        taal_queue_ulps_work(dssdev);
 
@@ -438,7 +442,8 @@ err2:
 
        r = taal_panel_reset(dssdev);
        if (!r) {
-               enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
+               if (gpio_is_valid(td->ext_te_gpio))
+                       enable_irq(gpio_to_irq(td->ext_te_gpio));
                td->ulps_enabled = false;
        }
 err1:
@@ -835,94 +840,135 @@ static struct attribute_group taal_attr_group = {
 static void taal_hw_reset(struct omap_dss_device *dssdev)
 {
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-       struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
 
-       if (panel_data->reset_gpio == -1)
+       if (!gpio_is_valid(td->reset_gpio))
                return;
 
-       gpio_set_value(panel_data->reset_gpio, 1);
+       gpio_set_value(td->reset_gpio, 1);
        if (td->panel_config->reset_sequence.high)
                udelay(td->panel_config->reset_sequence.high);
        /* reset the panel */
-       gpio_set_value(panel_data->reset_gpio, 0);
+       gpio_set_value(td->reset_gpio, 0);
        /* assert reset */
        if (td->panel_config->reset_sequence.low)
                udelay(td->panel_config->reset_sequence.low);
-       gpio_set_value(panel_data->reset_gpio, 1);
+       gpio_set_value(td->reset_gpio, 1);
        /* wait after releasing reset */
        if (td->panel_config->sleep.hw_reset)
                msleep(td->panel_config->sleep.hw_reset);
 }
 
+static void taal_probe_pdata(struct taal_data *td,
+               const struct nokia_dsi_panel_data *pdata)
+{
+       td->reset_gpio = pdata->reset_gpio;
+
+       if (pdata->use_ext_te)
+               td->ext_te_gpio = pdata->ext_te_gpio;
+       else
+               td->ext_te_gpio = -1;
+
+       td->esd_interval = pdata->esd_interval;
+       td->ulps_timeout = pdata->ulps_timeout;
+
+       td->use_dsi_backlight = pdata->use_dsi_backlight;
+
+       td->pin_config = pdata->pin_config;
+}
+
 static int taal_probe(struct omap_dss_device *dssdev)
 {
        struct backlight_properties props;
        struct taal_data *td;
        struct backlight_device *bldev = NULL;
-       struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
-       struct panel_config *panel_config = NULL;
        int r, i;
+       const char *panel_name;
 
        dev_dbg(&dssdev->dev, "probe\n");
 
-       if (!panel_data || !panel_data->name) {
-               r = -EINVAL;
-               goto err;
+       td = devm_kzalloc(&dssdev->dev, sizeof(*td), GFP_KERNEL);
+       if (!td)
+               return -ENOMEM;
+
+       dev_set_drvdata(&dssdev->dev, td);
+       td->dssdev = dssdev;
+
+       if (dssdev->data) {
+               const struct nokia_dsi_panel_data *pdata = dssdev->data;
+
+               taal_probe_pdata(td, pdata);
+
+               panel_name = pdata->name;
+       } else {
+               return -ENODEV;
        }
 
+       if (panel_name == NULL)
+               return -EINVAL;
+
        for (i = 0; i < ARRAY_SIZE(panel_configs); i++) {
-               if (strcmp(panel_data->name, panel_configs[i].name) == 0) {
-                       panel_config = &panel_configs[i];
+               if (strcmp(panel_name, panel_configs[i].name) == 0) {
+                       td->panel_config = &panel_configs[i];
                        break;
                }
        }
 
-       if (!panel_config) {
-               r = -EINVAL;
-               goto err;
-       }
+       if (!td->panel_config)
+               return -EINVAL;
 
-       dssdev->panel.timings = panel_config->timings;
+       dssdev->panel.timings = td->panel_config->timings;
        dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
-
-       td = kzalloc(sizeof(*td), GFP_KERNEL);
-       if (!td) {
-               r = -ENOMEM;
-               goto err;
-       }
-       td->dssdev = dssdev;
-       td->panel_config = panel_config;
-       td->esd_interval = panel_data->esd_interval;
-       td->ulps_enabled = false;
-       td->ulps_timeout = panel_data->ulps_timeout;
+       dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
+               OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
 
        mutex_init(&td->lock);
 
        atomic_set(&td->do_update, 0);
 
-       td->workqueue = create_singlethread_workqueue("taal_esd");
-       if (td->workqueue == NULL) {
-               dev_err(&dssdev->dev, "can't create ESD workqueue\n");
-               r = -ENOMEM;
-               goto err_wq;
+       if (gpio_is_valid(td->reset_gpio)) {
+               r = devm_gpio_request_one(&dssdev->dev, td->reset_gpio,
+                               GPIOF_OUT_INIT_LOW, "taal rst");
+               if (r) {
+                       dev_err(&dssdev->dev, "failed to request reset gpio\n");
+                       return r;
+               }
        }
-       INIT_DEFERRABLE_WORK(&td->esd_work, taal_esd_work);
-       INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work);
 
-       dev_set_drvdata(&dssdev->dev, td);
+       if (gpio_is_valid(td->ext_te_gpio)) {
+               r = devm_gpio_request_one(&dssdev->dev, td->ext_te_gpio,
+                               GPIOF_IN, "taal irq");
+               if (r) {
+                       dev_err(&dssdev->dev, "GPIO request failed\n");
+                       return r;
+               }
+
+               r = devm_request_irq(&dssdev->dev, gpio_to_irq(td->ext_te_gpio),
+                               taal_te_isr,
+                               IRQF_TRIGGER_RISING,
+                               "taal vsync", dssdev);
 
-       if (gpio_is_valid(panel_data->reset_gpio)) {
-               r = gpio_request_one(panel_data->reset_gpio, GPIOF_OUT_INIT_LOW,
-                               "taal rst");
                if (r) {
-                       dev_err(&dssdev->dev, "failed to request reset gpio\n");
-                       goto err_rst_gpio;
+                       dev_err(&dssdev->dev, "IRQ request failed\n");
+                       return r;
                }
+
+               INIT_DEFERRABLE_WORK(&td->te_timeout_work,
+                                       taal_te_timeout_work_callback);
+
+               dev_dbg(&dssdev->dev, "Using GPIO TE\n");
        }
 
+       td->workqueue = create_singlethread_workqueue("taal_esd");
+       if (td->workqueue == NULL) {
+               dev_err(&dssdev->dev, "can't create ESD workqueue\n");
+               return -ENOMEM;
+       }
+       INIT_DEFERRABLE_WORK(&td->esd_work, taal_esd_work);
+       INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work);
+
        taal_hw_reset(dssdev);
 
-       if (panel_data->use_dsi_backlight) {
+       if (td->use_dsi_backlight) {
                memset(&props, 0, sizeof(struct backlight_properties));
                props.max_brightness = 255;
 
@@ -943,31 +989,6 @@ static int taal_probe(struct omap_dss_device *dssdev)
                taal_bl_update_status(bldev);
        }
 
-       if (panel_data->use_ext_te) {
-               int gpio = panel_data->ext_te_gpio;
-
-               r = gpio_request_one(gpio, GPIOF_IN, "taal irq");
-               if (r) {
-                       dev_err(&dssdev->dev, "GPIO request failed\n");
-                       goto err_gpio;
-               }
-
-               r = request_irq(gpio_to_irq(gpio), taal_te_isr,
-                               IRQF_TRIGGER_RISING,
-                               "taal vsync", dssdev);
-
-               if (r) {
-                       dev_err(&dssdev->dev, "IRQ request failed\n");
-                       gpio_free(gpio);
-                       goto err_irq;
-               }
-
-               INIT_DEFERRABLE_WORK(&td->te_timeout_work,
-                                    taal_te_timeout_work_callback);
-
-               dev_dbg(&dssdev->dev, "Using GPIO TE\n");
-       }
-
        r = omap_dsi_request_vc(dssdev, &td->channel);
        if (r) {
                dev_err(&dssdev->dev, "failed to get virtual channel\n");
@@ -991,29 +1012,16 @@ static int taal_probe(struct omap_dss_device *dssdev)
 err_vc_id:
        omap_dsi_release_vc(dssdev, td->channel);
 err_req_vc:
-       if (panel_data->use_ext_te)
-               free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev);
-err_irq:
-       if (panel_data->use_ext_te)
-               gpio_free(panel_data->ext_te_gpio);
-err_gpio:
        if (bldev != NULL)
                backlight_device_unregister(bldev);
 err_bl:
-       if (gpio_is_valid(panel_data->reset_gpio))
-               gpio_free(panel_data->reset_gpio);
-err_rst_gpio:
        destroy_workqueue(td->workqueue);
-err_wq:
-       kfree(td);
-err:
        return r;
 }
 
 static void __exit taal_remove(struct omap_dss_device *dssdev)
 {
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-       struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
        struct backlight_device *bldev;
 
        dev_dbg(&dssdev->dev, "remove\n");
@@ -1021,12 +1029,6 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
        sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
        omap_dsi_release_vc(dssdev, td->channel);
 
-       if (panel_data->use_ext_te) {
-               int gpio = panel_data->ext_te_gpio;
-               free_irq(gpio_to_irq(gpio), dssdev);
-               gpio_free(gpio);
-       }
-
        bldev = td->bldev;
        if (bldev != NULL) {
                bldev->props.power = FB_BLANK_POWERDOWN;
@@ -1040,26 +1042,31 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
 
        /* reset, to be sure that the panel is in a valid state */
        taal_hw_reset(dssdev);
-
-       if (gpio_is_valid(panel_data->reset_gpio))
-               gpio_free(panel_data->reset_gpio);
-
-       kfree(td);
 }
 
 static int taal_power_on(struct omap_dss_device *dssdev)
 {
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-       struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
        u8 id1, id2, id3;
        int r;
 
-       r = omapdss_dsi_configure_pins(dssdev, &panel_data->pin_config);
+       r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
        if (r) {
                dev_err(&dssdev->dev, "failed to configure DSI pins\n");
                goto err0;
        };
 
+       omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res,
+               dssdev->panel.timings.y_res);
+       omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888);
+       omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE);
+
+       r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000);
+       if (r) {
+               dev_err(&dssdev->dev, "failed to set HS and LP clocks\n");
+               goto err0;
+       }
+
        r = omapdss_dsi_display_enable(dssdev);
        if (r) {
                dev_err(&dssdev->dev, "failed to enable DSI\n");
@@ -1356,7 +1363,6 @@ static int taal_update(struct omap_dss_device *dssdev,
                                    u16 x, u16 y, u16 w, u16 h)
 {
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-       struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
        int r;
 
        dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
@@ -1380,7 +1386,7 @@ static int taal_update(struct omap_dss_device *dssdev,
        if (r)
                goto err;
 
-       if (td->te_enabled && panel_data->use_ext_te) {
+       if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) {
                schedule_delayed_work(&td->te_timeout_work,
                                msecs_to_jiffies(250));
                atomic_set(&td->do_update, 1);
@@ -1419,7 +1425,6 @@ static int taal_sync(struct omap_dss_device *dssdev)
 static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
 {
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-       struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
        int r;
 
        if (enable)
@@ -1427,7 +1432,7 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
        else
                r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF);
 
-       if (!panel_data->use_ext_te)
+       if (!gpio_is_valid(td->ext_te_gpio))
                omapdss_dsi_enable_te(dssdev, enable);
 
        if (td->panel_config->sleep.enable_te)
@@ -1487,6 +1492,7 @@ static int taal_get_te(struct omap_dss_device *dssdev)
 static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
 {
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+       u16 dw, dh;
        int r;
 
        dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
@@ -1508,6 +1514,16 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
                        goto err;
        }
 
+       if (rotate == 0 || rotate == 2) {
+               dw = dssdev->panel.timings.x_res;
+               dh = dssdev->panel.timings.y_res;
+       } else {
+               dw = dssdev->panel.timings.y_res;
+               dh = dssdev->panel.timings.x_res;
+       }
+
+       omapdss_dsi_set_size(dssdev, dw, dh);
+
        td->rotate = rotate;
 
        dsi_bus_unlock(dssdev);
@@ -1726,7 +1742,6 @@ static void taal_esd_work(struct work_struct *work)
        struct taal_data *td = container_of(work, struct taal_data,
                        esd_work.work);
        struct omap_dss_device *dssdev = td->dssdev;
-       struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
        u8 state1, state2;
        int r;
 
@@ -1773,7 +1788,7 @@ static void taal_esd_work(struct work_struct *work)
        }
        /* Self-diagnostics result is also shown on TE GPIO line. We need
         * to re-enable TE after self diagnostics */
-       if (td->te_enabled && panel_data->use_ext_te) {
+       if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) {
                r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
                if (r)
                        goto err;
index 40cc0cfa5d179c77ce8c4bcf0282391162140766..383811cf8648bfb199847b9d183d5b50b562cd23 100644 (file)
@@ -65,6 +65,9 @@ static int tfp410_power_on(struct omap_dss_device *dssdev)
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
@@ -116,8 +119,8 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
        }
 
        if (gpio_is_valid(ddata->pd_gpio)) {
-               r = gpio_request_one(ddata->pd_gpio, GPIOF_OUT_INIT_LOW,
-                               "tfp410 pd");
+               r = devm_gpio_request_one(&dssdev->dev, ddata->pd_gpio,
+                               GPIOF_OUT_INIT_LOW, "tfp410 pd");
                if (r) {
                        dev_err(&dssdev->dev, "Failed to request PD GPIO %d\n",
                                        ddata->pd_gpio);
@@ -132,8 +135,7 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
                if (!adapter) {
                        dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
                                        i2c_bus_num);
-                       r = -EINVAL;
-                       goto err_i2c;
+                       return -EINVAL;
                }
 
                ddata->i2c_adapter = adapter;
@@ -142,10 +144,6 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
        dev_set_drvdata(&dssdev->dev, ddata);
 
        return 0;
-err_i2c:
-       if (gpio_is_valid(ddata->pd_gpio))
-               gpio_free(ddata->pd_gpio);
-       return r;
 }
 
 static void __exit tfp410_remove(struct omap_dss_device *dssdev)
@@ -157,9 +155,6 @@ static void __exit tfp410_remove(struct omap_dss_device *dssdev)
        if (ddata->i2c_adapter)
                i2c_put_adapter(ddata->i2c_adapter);
 
-       if (gpio_is_valid(ddata->pd_gpio))
-               gpio_free(ddata->pd_gpio);
-
        dev_set_drvdata(&dssdev->dev, NULL);
 
        mutex_unlock(&ddata->lock);
@@ -231,7 +226,8 @@ static void tfp410_set_timings(struct omap_dss_device *dssdev,
        struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
 
        mutex_lock(&ddata->lock);
-       dpi_set_timings(dssdev, timings);
+       omapdss_dpi_set_timings(dssdev, timings);
+       dssdev->panel.timings = *timings;
        mutex_unlock(&ddata->lock);
 }
 
index fa7baa650ae06bcc18a911a3e3fed34cb4e6f0b2..b5e6dbc59f0a654c79d9d3b6b40eaba955680c2a 100644 (file)
@@ -337,6 +337,9 @@ static int tpo_td043_enable_dss(struct omap_dss_device *dssdev)
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
@@ -480,7 +483,9 @@ static void tpo_td043_remove(struct omap_dss_device *dssdev)
 static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
                struct omap_video_timings *timings)
 {
-       dpi_set_timings(dssdev, timings);
+       omapdss_dpi_set_timings(dssdev, timings);
+
+       dssdev->panel.timings = *timings;
 }
 
 static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
index b337a8469fd85441b051b28f5cd808b52d927cf5..80f5390aa1368984266071f21e15e6dca859b0e3 100644 (file)
@@ -84,7 +84,7 @@ config OMAP2_DSS_SDI
 
 config OMAP2_DSS_DSI
        bool "DSI support"
-       depends on ARCH_OMAP3 || ARCH_OMAP4
+       depends on ARCH_OMAP3 || ARCH_OMAP4 || ARCH_OMAP5
         default n
        help
          MIPI DSI (Display Serial Interface) support.
index 5c450b0f94d0bb03a5bfef064ac613424e527247..4549869bfe1a75ef6ffb1262409d918295151754 100644 (file)
@@ -1,9 +1,9 @@
 obj-$(CONFIG_OMAP2_DSS) += omapdss.o
 omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
-       manager.o overlay.o apply.o
+       manager.o manager-sysfs.o overlay.o overlay-sysfs.o output.o apply.o
 omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
 omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
-omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
+omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
 omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
 omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
 omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
index 0fefc68372b93ca326b9c194f4529fd201b6161c..19d66f471b4bae9eafe0331b511a24265f4717ee 100644 (file)
@@ -111,9 +111,6 @@ static struct {
        struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
        struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
 
-       bool fifo_merge_dirty;
-       bool fifo_merge;
-
        bool irq_enabled;
 } dss_data;
 
@@ -424,17 +421,25 @@ static void wait_pending_extra_info_updates(void)
 int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
 {
        unsigned long timeout = msecs_to_jiffies(500);
-       struct mgr_priv_data *mp;
+       struct mgr_priv_data *mp = get_mgr_priv(mgr);
        u32 irq;
+       unsigned long flags;
        int r;
        int i;
-       struct omap_dss_device *dssdev = mgr->device;
 
-       if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+       spin_lock_irqsave(&data_lock, flags);
+
+       if (mgr_manual_update(mgr)) {
+               spin_unlock_irqrestore(&data_lock, flags);
                return 0;
+       }
 
-       if (mgr_manual_update(mgr))
+       if (!mp->enabled) {
+               spin_unlock_irqrestore(&data_lock, flags);
                return 0;
+       }
+
+       spin_unlock_irqrestore(&data_lock, flags);
 
        r = dispc_runtime_get();
        if (r)
@@ -442,10 +447,8 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
 
        irq = dispc_mgr_get_vsync_irq(mgr->id);
 
-       mp = get_mgr_priv(mgr);
        i = 0;
        while (1) {
-               unsigned long flags;
                bool shadow_dirty, dirty;
 
                spin_lock_irqsave(&data_lock, flags);
@@ -489,21 +492,30 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
 {
        unsigned long timeout = msecs_to_jiffies(500);
        struct ovl_priv_data *op;
-       struct omap_dss_device *dssdev;
+       struct mgr_priv_data *mp;
        u32 irq;
+       unsigned long flags;
        int r;
        int i;
 
        if (!ovl->manager)
                return 0;
 
-       dssdev = ovl->manager->device;
+       mp = get_mgr_priv(ovl->manager);
+
+       spin_lock_irqsave(&data_lock, flags);
 
-       if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+       if (ovl_manual_update(ovl)) {
+               spin_unlock_irqrestore(&data_lock, flags);
                return 0;
+       }
 
-       if (ovl_manual_update(ovl))
+       if (!mp->enabled) {
+               spin_unlock_irqrestore(&data_lock, flags);
                return 0;
+       }
+
+       spin_unlock_irqrestore(&data_lock, flags);
 
        r = dispc_runtime_get();
        if (r)
@@ -514,7 +526,6 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
        op = get_ovl_priv(ovl);
        i = 0;
        while (1) {
-               unsigned long flags;
                bool shadow_dirty, dirty;
 
                spin_lock_irqsave(&data_lock, flags);
@@ -573,7 +584,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
 
        replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
 
-       r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings);
+       r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
        if (r) {
                /*
                 * We can't do much here, as this function can be called from
@@ -677,40 +688,11 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
                mp->shadow_extra_info_dirty = true;
 }
 
-static void dss_write_regs_common(void)
-{
-       const int num_mgrs = omap_dss_get_num_overlay_managers();
-       int i;
-
-       if (!dss_data.fifo_merge_dirty)
-               return;
-
-       for (i = 0; i < num_mgrs; ++i) {
-               struct omap_overlay_manager *mgr;
-               struct mgr_priv_data *mp;
-
-               mgr = omap_dss_get_overlay_manager(i);
-               mp = get_mgr_priv(mgr);
-
-               if (mp->enabled) {
-                       if (dss_data.fifo_merge_dirty) {
-                               dispc_enable_fifomerge(dss_data.fifo_merge);
-                               dss_data.fifo_merge_dirty = false;
-                       }
-
-                       if (mp->updating)
-                               mp->shadow_info_dirty = true;
-               }
-       }
-}
-
 static void dss_write_regs(void)
 {
        const int num_mgrs = omap_dss_get_num_overlay_managers();
        int i;
 
-       dss_write_regs_common();
-
        for (i = 0; i < num_mgrs; ++i) {
                struct omap_overlay_manager *mgr;
                struct mgr_priv_data *mp;
@@ -799,8 +781,6 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
        dss_mgr_write_regs(mgr);
        dss_mgr_write_regs_extra(mgr);
 
-       dss_write_regs_common();
-
        mp->updating = true;
 
        if (!dss_data.irq_enabled && need_isr())
@@ -984,20 +964,11 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
        op->extra_info_dirty = true;
 }
 
-static void dss_apply_fifo_merge(bool use_fifo_merge)
-{
-       if (dss_data.fifo_merge == use_fifo_merge)
-               return;
-
-       dss_data.fifo_merge = use_fifo_merge;
-       dss_data.fifo_merge_dirty = true;
-}
-
-static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
-               bool use_fifo_merge)
+static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
 {
        struct ovl_priv_data *op = get_ovl_priv(ovl);
        u32 fifo_low, fifo_high;
+       bool use_fifo_merge = false;
 
        if (!op->enabled && !op->enabling)
                return;
@@ -1008,8 +979,7 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
        dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
 }
 
-static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,
-               bool use_fifo_merge)
+static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
 {
        struct omap_overlay *ovl;
        struct mgr_priv_data *mp;
@@ -1020,94 +990,19 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,
                return;
 
        list_for_each_entry(ovl, &mgr->overlays, list)
-               dss_ovl_setup_fifo(ovl, use_fifo_merge);
-}
-
-static void dss_setup_fifos(bool use_fifo_merge)
-{
-       const int num_mgrs = omap_dss_get_num_overlay_managers();
-       struct omap_overlay_manager *mgr;
-       int i;
-
-       for (i = 0; i < num_mgrs; ++i) {
-               mgr = omap_dss_get_overlay_manager(i);
-               dss_mgr_setup_fifos(mgr, use_fifo_merge);
-       }
+               dss_ovl_setup_fifo(ovl);
 }
 
-static int get_num_used_managers(void)
+static void dss_setup_fifos(void)
 {
        const int num_mgrs = omap_dss_get_num_overlay_managers();
        struct omap_overlay_manager *mgr;
-       struct mgr_priv_data *mp;
        int i;
-       int enabled_mgrs;
-
-       enabled_mgrs = 0;
 
        for (i = 0; i < num_mgrs; ++i) {
                mgr = omap_dss_get_overlay_manager(i);
-               mp = get_mgr_priv(mgr);
-
-               if (!mp->enabled)
-                       continue;
-
-               enabled_mgrs++;
+               dss_mgr_setup_fifos(mgr);
        }
-
-       return enabled_mgrs;
-}
-
-static int get_num_used_overlays(void)
-{
-       const int num_ovls = omap_dss_get_num_overlays();
-       struct omap_overlay *ovl;
-       struct ovl_priv_data *op;
-       struct mgr_priv_data *mp;
-       int i;
-       int enabled_ovls;
-
-       enabled_ovls = 0;
-
-       for (i = 0; i < num_ovls; ++i) {
-               ovl = omap_dss_get_overlay(i);
-               op = get_ovl_priv(ovl);
-
-               if (!op->enabled && !op->enabling)
-                       continue;
-
-               mp = get_mgr_priv(ovl->manager);
-
-               if (!mp->enabled)
-                       continue;
-
-               enabled_ovls++;
-       }
-
-       return enabled_ovls;
-}
-
-static bool get_use_fifo_merge(void)
-{
-       int enabled_mgrs = get_num_used_managers();
-       int enabled_ovls = get_num_used_overlays();
-
-       if (!dss_has_feature(FEAT_FIFO_MERGE))
-               return false;
-
-       /*
-        * In theory the only requirement for fifomerge is enabled_ovls <= 1.
-        * However, if we have two managers enabled and set/unset the fifomerge,
-        * we need to set the GO bits in particular sequence for the managers,
-        * and wait in between.
-        *
-        * This is rather difficult as new apply calls can happen at any time,
-        * so we simplify the problem by requiring also that enabled_mgrs <= 1.
-        * In practice this shouldn't matter, because when only one overlay is
-        * enabled, most likely only one output is enabled.
-        */
-
-       return enabled_mgrs <= 1 && enabled_ovls <= 1;
 }
 
 int dss_mgr_enable(struct omap_overlay_manager *mgr)
@@ -1115,7 +1010,6 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
        unsigned long flags;
        int r;
-       bool fifo_merge;
 
        mutex_lock(&apply_lock);
 
@@ -1133,23 +1027,11 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
                goto err;
        }
 
-       /* step 1: setup fifos/fifomerge before enabling the manager */
-
-       fifo_merge = get_use_fifo_merge();
-       dss_setup_fifos(fifo_merge);
-       dss_apply_fifo_merge(fifo_merge);
+       dss_setup_fifos();
 
        dss_write_regs();
        dss_set_go_bits();
 
-       spin_unlock_irqrestore(&data_lock, flags);
-
-       /* wait until fifo config is in */
-       wait_pending_extra_info_updates();
-
-       /* step 2: enable the manager */
-       spin_lock_irqsave(&data_lock, flags);
-
        if (!mgr_manual_update(mgr))
                mp->updating = true;
 
@@ -1174,7 +1056,6 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
 {
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
        unsigned long flags;
-       bool fifo_merge;
 
        mutex_lock(&apply_lock);
 
@@ -1189,16 +1070,8 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
        mp->updating = false;
        mp->enabled = false;
 
-       fifo_merge = get_use_fifo_merge();
-       dss_setup_fifos(fifo_merge);
-       dss_apply_fifo_merge(fifo_merge);
-
-       dss_write_regs();
-       dss_set_go_bits();
-
        spin_unlock_irqrestore(&data_lock, flags);
 
-       wait_pending_extra_info_updates();
 out:
        mutex_unlock(&apply_lock);
 }
@@ -1237,29 +1110,29 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
        spin_unlock_irqrestore(&data_lock, flags);
 }
 
-int dss_mgr_set_device(struct omap_overlay_manager *mgr,
-               struct omap_dss_device *dssdev)
+int dss_mgr_set_output(struct omap_overlay_manager *mgr,
+               struct omap_dss_output *output)
 {
        int r;
 
        mutex_lock(&apply_lock);
 
-       if (dssdev->manager) {
-               DSSERR("display '%s' already has a manager '%s'\n",
-                              dssdev->name, dssdev->manager->name);
+       if (mgr->output) {
+               DSSERR("manager %s is already connected to an output\n",
+                       mgr->name);
                r = -EINVAL;
                goto err;
        }
 
-       if ((mgr->supported_displays & dssdev->type) == 0) {
-               DSSERR("display '%s' does not support manager '%s'\n",
-                              dssdev->name, mgr->name);
+       if ((mgr->supported_outputs & output->id) == 0) {
+               DSSERR("output does not support manager %s\n",
+                       mgr->name);
                r = -EINVAL;
                goto err;
        }
 
-       dssdev->manager = mgr;
-       mgr->device = dssdev;
+       output->manager = mgr;
+       mgr->output = output;
 
        mutex_unlock(&apply_lock);
 
@@ -1269,40 +1142,46 @@ err:
        return r;
 }
 
-int dss_mgr_unset_device(struct omap_overlay_manager *mgr)
+int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
 {
        int r;
+       struct mgr_priv_data *mp = get_mgr_priv(mgr);
+       unsigned long flags;
 
        mutex_lock(&apply_lock);
 
-       if (!mgr->device) {
-               DSSERR("failed to unset display, display not set.\n");
+       if (!mgr->output) {
+               DSSERR("failed to unset output, output not set\n");
                r = -EINVAL;
                goto err;
        }
 
-       /*
-        * Don't allow currently enabled displays to have the overlay manager
-        * pulled out from underneath them
-        */
-       if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) {
+       spin_lock_irqsave(&data_lock, flags);
+
+       if (mp->enabled) {
+               DSSERR("output can't be unset when manager is enabled\n");
                r = -EINVAL;
-               goto err;
+               goto err1;
        }
 
-       mgr->device->manager = NULL;
-       mgr->device = NULL;
+       spin_unlock_irqrestore(&data_lock, flags);
+
+       mgr->output->manager = NULL;
+       mgr->output = NULL;
 
        mutex_unlock(&apply_lock);
 
        return 0;
+err1:
+       spin_unlock_irqrestore(&data_lock, flags);
 err:
        mutex_unlock(&apply_lock);
+
        return r;
 }
 
 static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
-               struct omap_video_timings *timings)
+               const struct omap_video_timings *timings)
 {
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
 
@@ -1311,24 +1190,22 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
 }
 
 void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
-               struct omap_video_timings *timings)
+               const struct omap_video_timings *timings)
 {
        unsigned long flags;
-
-       mutex_lock(&apply_lock);
+       struct mgr_priv_data *mp = get_mgr_priv(mgr);
 
        spin_lock_irqsave(&data_lock, flags);
 
-       dss_apply_mgr_timings(mgr, timings);
-
-       dss_write_regs();
-       dss_set_go_bits();
+       if (mp->updating) {
+               DSSERR("cannot set timings for %s: manager needs to be disabled\n",
+                       mgr->name);
+               goto out;
+       }
 
+       dss_apply_mgr_timings(mgr, timings);
+out:
        spin_unlock_irqrestore(&data_lock, flags);
-
-       wait_pending_extra_info_updates();
-
-       mutex_unlock(&apply_lock);
 }
 
 static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
@@ -1346,7 +1223,7 @@ void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
        unsigned long flags;
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
 
-       mutex_lock(&apply_lock);
+       spin_lock_irqsave(&data_lock, flags);
 
        if (mp->enabled) {
                DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
@@ -1354,19 +1231,9 @@ void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
                goto out;
        }
 
-       spin_lock_irqsave(&data_lock, flags);
-
        dss_apply_mgr_lcd_config(mgr, config);
-
-       dss_write_regs();
-       dss_set_go_bits();
-
-       spin_unlock_irqrestore(&data_lock, flags);
-
-       wait_pending_extra_info_updates();
-
 out:
-       mutex_unlock(&apply_lock);
+       spin_unlock_irqrestore(&data_lock, flags);
 }
 
 int dss_ovl_set_info(struct omap_overlay *ovl,
@@ -1483,6 +1350,13 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)
                goto err;
        }
 
+       spin_unlock_irqrestore(&data_lock, flags);
+
+       /* wait for pending extra_info updates to ensure the ovl is disabled */
+       wait_pending_extra_info_updates();
+
+       spin_lock_irqsave(&data_lock, flags);
+
        op->channel = -1;
 
        ovl->manager = NULL;
@@ -1517,7 +1391,6 @@ int dss_ovl_enable(struct omap_overlay *ovl)
 {
        struct ovl_priv_data *op = get_ovl_priv(ovl);
        unsigned long flags;
-       bool fifo_merge;
        int r;
 
        mutex_lock(&apply_lock);
@@ -1527,7 +1400,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
                goto err1;
        }
 
-       if (ovl->manager == NULL || ovl->manager->device == NULL) {
+       if (ovl->manager == NULL || ovl->manager->output == NULL) {
                r = -EINVAL;
                goto err1;
        }
@@ -1543,22 +1416,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
                goto err2;
        }
 
-       /* step 1: configure fifos/fifomerge for currently enabled ovls */
-
-       fifo_merge = get_use_fifo_merge();
-       dss_setup_fifos(fifo_merge);
-       dss_apply_fifo_merge(fifo_merge);
-
-       dss_write_regs();
-       dss_set_go_bits();
-
-       spin_unlock_irqrestore(&data_lock, flags);
-
-       /* wait for fifo configs to go in */
-       wait_pending_extra_info_updates();
-
-       /* step 2: enable the overlay */
-       spin_lock_irqsave(&data_lock, flags);
+       dss_setup_fifos();
 
        op->enabling = false;
        dss_apply_ovl_enable(ovl, true);
@@ -1568,9 +1426,6 @@ int dss_ovl_enable(struct omap_overlay *ovl)
 
        spin_unlock_irqrestore(&data_lock, flags);
 
-       /* wait for overlay to be enabled */
-       wait_pending_extra_info_updates();
-
        mutex_unlock(&apply_lock);
 
        return 0;
@@ -1586,7 +1441,6 @@ int dss_ovl_disable(struct omap_overlay *ovl)
 {
        struct ovl_priv_data *op = get_ovl_priv(ovl);
        unsigned long flags;
-       bool fifo_merge;
        int r;
 
        mutex_lock(&apply_lock);
@@ -1596,39 +1450,19 @@ int dss_ovl_disable(struct omap_overlay *ovl)
                goto err;
        }
 
-       if (ovl->manager == NULL || ovl->manager->device == NULL) {
+       if (ovl->manager == NULL || ovl->manager->output == NULL) {
                r = -EINVAL;
                goto err;
        }
 
-       /* step 1: disable the overlay */
        spin_lock_irqsave(&data_lock, flags);
 
        dss_apply_ovl_enable(ovl, false);
-
        dss_write_regs();
        dss_set_go_bits();
 
        spin_unlock_irqrestore(&data_lock, flags);
 
-       /* wait for the overlay to be disabled */
-       wait_pending_extra_info_updates();
-
-       /* step 2: configure fifos/fifomerge */
-       spin_lock_irqsave(&data_lock, flags);
-
-       fifo_merge = get_use_fifo_merge();
-       dss_setup_fifos(fifo_merge);
-       dss_apply_fifo_merge(fifo_merge);
-
-       dss_write_regs();
-       dss_set_go_bits();
-
-       spin_unlock_irqrestore(&data_lock, flags);
-
-       /* wait for fifo config to go in */
-       wait_pending_extra_info_updates();
-
        mutex_unlock(&apply_lock);
 
        return 0;
index 58bd9c27369df9d4a39d1352f9d9cad74ec51b37..b2af72dc20bdb2cf0cc5f880008916fb85d09826 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/suspend.h>
+#include <linux/slab.h>
 
 #include <video/omapdss.h>
 
@@ -57,6 +58,11 @@ bool dss_debug;
 module_param_named(debug, dss_debug, bool, 0644);
 #endif
 
+const char *dss_get_default_display_name(void)
+{
+       return core.default_display_name;
+}
+
 /* REGULATORS */
 
 struct regulator *dss_get_vdds_dsi(void)
@@ -347,17 +353,14 @@ static int dss_driver_probe(struct device *dev)
        int r;
        struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
        struct omap_dss_device *dssdev = to_dss_device(dev);
-       bool force;
 
        DSSDBG("driver_probe: dev %s/%s, drv %s\n",
                                dev_name(dev), dssdev->driver_name,
                                dssdrv->driver.name);
 
-       dss_init_device(core.pdev, dssdev);
-
-       force = core.default_display_name &&
-               strcmp(core.default_display_name, dssdev->name) == 0;
-       dss_recheck_connections(dssdev, force);
+       r = dss_init_device(core.pdev, dssdev);
+       if (r)
+               return r;
 
        r = dssdrv->probe(dssdev);
 
@@ -416,54 +419,44 @@ void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
 EXPORT_SYMBOL(omap_dss_unregister_driver);
 
 /* DEVICE */
-static void reset_device(struct device *dev, int check)
-{
-       u8 *dev_p = (u8 *)dev;
-       u8 *dev_end = dev_p + sizeof(*dev);
-       void *saved_pdata;
-
-       saved_pdata = dev->platform_data;
-       if (check) {
-               /*
-                * Check if there is any other setting than platform_data
-                * in struct device; warn that these will be reset by our
-                * init.
-                */
-               dev->platform_data = NULL;
-               while (dev_p < dev_end) {
-                       if (*dev_p) {
-                               WARN("%s: struct device fields will be "
-                                               "discarded\n",
-                                    __func__);
-                               break;
-                       }
-                       dev_p++;
-               }
-       }
-       memset(dev, 0, sizeof(*dev));
-       dev->platform_data = saved_pdata;
-}
-
 
 static void omap_dss_dev_release(struct device *dev)
 {
-       reset_device(dev, 0);
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       kfree(dssdev);
 }
 
-int omap_dss_register_device(struct omap_dss_device *dssdev,
-               struct device *parent, int disp_num)
+static int disp_num_counter;
+
+struct omap_dss_device *dss_alloc_and_init_device(struct device *parent)
 {
-       WARN_ON(!dssdev->driver_name);
+       struct omap_dss_device *dssdev;
+
+       dssdev = kzalloc(sizeof(*dssdev), GFP_KERNEL);
+       if (!dssdev)
+               return NULL;
 
-       reset_device(&dssdev->dev, 1);
        dssdev->dev.bus = &dss_bus_type;
        dssdev->dev.parent = parent;
        dssdev->dev.release = omap_dss_dev_release;
-       dev_set_name(&dssdev->dev, "display%d", disp_num);
-       return device_register(&dssdev->dev);
+       dev_set_name(&dssdev->dev, "display%d", disp_num_counter++);
+
+       device_initialize(&dssdev->dev);
+
+       return dssdev;
+}
+
+int dss_add_device(struct omap_dss_device *dssdev)
+{
+       return device_add(&dssdev->dev);
+}
+
+void dss_put_device(struct omap_dss_device *dssdev)
+{
+       put_device(&dssdev->dev);
 }
 
-void omap_dss_unregister_device(struct omap_dss_device *dssdev)
+void dss_unregister_device(struct omap_dss_device *dssdev)
 {
        device_unregister(&dssdev->dev);
 }
@@ -471,15 +464,25 @@ void omap_dss_unregister_device(struct omap_dss_device *dssdev)
 static int dss_unregister_dss_dev(struct device *dev, void *data)
 {
        struct omap_dss_device *dssdev = to_dss_device(dev);
-       omap_dss_unregister_device(dssdev);
+       dss_unregister_device(dssdev);
        return 0;
 }
 
-void omap_dss_unregister_child_devices(struct device *parent)
+void dss_unregister_child_devices(struct device *parent)
 {
        device_for_each_child(parent, NULL, dss_unregister_dss_dev);
 }
 
+void dss_copy_device_pdata(struct omap_dss_device *dst,
+               const struct omap_dss_device *src)
+{
+       u8 *d = (u8 *)dst;
+       u8 *s = (u8 *)src;
+       size_t dsize = sizeof(struct device);
+
+       memcpy(d + dsize, s + dsize, sizeof(struct omap_dss_device) - dsize);
+}
+
 /* BUS */
 static int __init omap_dss_bus_register(void)
 {
index ee9e29639dcc4323c5d1d87b31390da0a1ad5373..b43477a5fae869e5e8981faaea48f51c15827e49 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/pm_runtime.h>
 
 #include <plat/cpu.h>
-#include <plat/clock.h>
 
 #include <video/omapdss.h>
 
@@ -82,6 +81,30 @@ struct dispc_irq_stats {
        unsigned irqs[32];
 };
 
+struct dispc_features {
+       u8 sw_start;
+       u8 fp_start;
+       u8 bp_start;
+       u16 sw_max;
+       u16 vp_max;
+       u16 hp_max;
+       int (*calc_scaling) (enum omap_plane plane,
+               const struct omap_video_timings *mgr_timings,
+               u16 width, u16 height, u16 out_width, u16 out_height,
+               enum omap_color_mode color_mode, bool *five_taps,
+               int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+               u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
+       unsigned long (*calc_core_clk) (enum omap_plane plane,
+               u16 width, u16 height, u16 out_width, u16 out_height,
+               bool mem_to_mem);
+       u8 num_fifos;
+
+       /* swap GFX & WB fifos */
+       bool gfx_fifo_workaround:1;
+};
+
+#define DISPC_MAX_NR_FIFOS 5
+
 static struct {
        struct platform_device *pdev;
        void __iomem    *base;
@@ -91,7 +114,9 @@ static struct {
        int irq;
        struct clk *dss_clk;
 
-       u32     fifo_size[MAX_DSS_OVERLAYS];
+       u32 fifo_size[DISPC_MAX_NR_FIFOS];
+       /* maps which plane is using a fifo. fifo-id -> plane-id */
+       int fifo_assignment[DISPC_MAX_NR_FIFOS];
 
        spinlock_t irq_lock;
        u32 irq_error_mask;
@@ -102,6 +127,8 @@ static struct {
        bool            ctx_valid;
        u32             ctx[DISPC_SZ_REGS / sizeof(u32)];
 
+       const struct dispc_features *feat;
+
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
        spinlock_t irq_stats_lock;
        struct dispc_irq_stats irq_stats;
@@ -211,7 +238,14 @@ static const struct {
        },
 };
 
+struct color_conv_coef {
+       int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
+       int full_range;
+};
+
 static void _omap_dispc_set_irqs(void);
+static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
+static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
 
 static inline void dispc_write_reg(const u16 idx, u32 val)
 {
@@ -509,6 +543,11 @@ u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
        return mgr_desc[channel].framedone_irq;
 }
 
+u32 dispc_wb_get_framedone_irq(void)
+{
+       return DISPC_IRQ_FRAMEDONEWB;
+}
+
 bool dispc_mgr_go_busy(enum omap_channel channel)
 {
        return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
@@ -536,6 +575,30 @@ void dispc_mgr_go(enum omap_channel channel)
        mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
 }
 
+bool dispc_wb_go_busy(void)
+{
+       return REG_GET(DISPC_CONTROL2, 6, 6) == 1;
+}
+
+void dispc_wb_go(void)
+{
+       enum omap_plane plane = OMAP_DSS_WB;
+       bool enable, go;
+
+       enable = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0) == 1;
+
+       if (!enable)
+               return;
+
+       go = REG_GET(DISPC_CONTROL2, 6, 6) == 1;
+       if (go) {
+               DSSERR("GO bit not down for WB\n");
+               return;
+       }
+
+       REG_FLD_MOD(DISPC_CONTROL2, 1, 6, 6);
+}
+
 static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value)
 {
        dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
@@ -618,41 +681,41 @@ static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc,
        }
 }
 
-static void _dispc_setup_color_conv_coef(void)
-{
-       int i;
-       const struct color_conv_coef {
-               int  ry,  rcr,  rcb,   gy,  gcr,  gcb,   by,  bcr,  bcb;
-               int  full_range;
-       }  ctbl_bt601_5 = {
-               298,  409,    0,  298, -208, -100,  298,    0,  517, 0,
-       };
-
-       const struct color_conv_coef *ct;
 
+static void dispc_ovl_write_color_conv_coef(enum omap_plane plane,
+               const struct color_conv_coef *ct)
+{
 #define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
 
-       ct = &ctbl_bt601_5;
+       dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->rcr, ct->ry));
+       dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->gy,  ct->rcb));
+       dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->gcb, ct->gcr));
+       dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->bcr, ct->by));
+       dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->bcb));
 
-       for (i = 1; i < dss_feat_get_num_ovls(); i++) {
-               dispc_write_reg(DISPC_OVL_CONV_COEF(i, 0),
-                       CVAL(ct->rcr, ct->ry));
-               dispc_write_reg(DISPC_OVL_CONV_COEF(i, 1),
-                       CVAL(ct->gy,  ct->rcb));
-               dispc_write_reg(DISPC_OVL_CONV_COEF(i, 2),
-                       CVAL(ct->gcb, ct->gcr));
-               dispc_write_reg(DISPC_OVL_CONV_COEF(i, 3),
-                       CVAL(ct->bcr, ct->by));
-               dispc_write_reg(DISPC_OVL_CONV_COEF(i, 4),
-                       CVAL(0, ct->bcb));
-
-               REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), ct->full_range,
-                       11, 11);
-       }
+       REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11);
 
 #undef CVAL
 }
 
+static void dispc_setup_color_conv_coef(void)
+{
+       int i;
+       int num_ovl = dss_feat_get_num_ovls();
+       int num_wb = dss_feat_get_num_wbs();
+       const struct color_conv_coef ctbl_bt601_5_ovl = {
+               298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
+       };
+       const struct color_conv_coef ctbl_bt601_5_wb = {
+               66, 112, -38, 129, -94, -74, 25, -18, 112, 0,
+       };
+
+       for (i = 1; i < num_ovl; i++)
+               dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_ovl);
+
+       for (; i < num_wb; i++)
+               dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_wb);
+}
 
 static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr)
 {
@@ -674,24 +737,32 @@ static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr)
        dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);
 }
 
-static void dispc_ovl_set_pos(enum omap_plane plane, int x, int y)
+static void dispc_ovl_set_pos(enum omap_plane plane,
+               enum omap_overlay_caps caps, int x, int y)
 {
-       u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
+       u32 val;
+
+       if ((caps & OMAP_DSS_OVL_CAP_POS) == 0)
+               return;
+
+       val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
 
        dispc_write_reg(DISPC_OVL_POSITION(plane), val);
 }
 
-static void dispc_ovl_set_pic_size(enum omap_plane plane, int width, int height)
+static void dispc_ovl_set_input_size(enum omap_plane plane, int width,
+               int height)
 {
        u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
 
-       if (plane == OMAP_DSS_GFX)
+       if (plane == OMAP_DSS_GFX || plane == OMAP_DSS_WB)
                dispc_write_reg(DISPC_OVL_SIZE(plane), val);
        else
                dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
 }
 
-static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height)
+static void dispc_ovl_set_output_size(enum omap_plane plane, int width,
+               int height)
 {
        u32 val;
 
@@ -699,14 +770,16 @@ static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height)
 
        val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
 
-       dispc_write_reg(DISPC_OVL_SIZE(plane), val);
+       if (plane == OMAP_DSS_WB)
+               dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
+       else
+               dispc_write_reg(DISPC_OVL_SIZE(plane), val);
 }
 
-static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder)
+static void dispc_ovl_set_zorder(enum omap_plane plane,
+               enum omap_overlay_caps caps, u8 zorder)
 {
-       struct omap_overlay *ovl = omap_dss_get_overlay(plane);
-
-       if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
+       if ((caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
                return;
 
        REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
@@ -723,23 +796,22 @@ static void dispc_ovl_enable_zorder_planes(void)
                REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
 }
 
-static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable)
+static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane,
+               enum omap_overlay_caps caps, bool enable)
 {
-       struct omap_overlay *ovl = omap_dss_get_overlay(plane);
-
-       if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
+       if ((caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
                return;
 
        REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
 }
 
-static void dispc_ovl_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
+static void dispc_ovl_setup_global_alpha(enum omap_plane plane,
+               enum omap_overlay_caps caps, u8 global_alpha)
 {
        static const unsigned shifts[] = { 0, 8, 16, 24, };
        int shift;
-       struct omap_overlay *ovl = omap_dss_get_overlay(plane);
 
-       if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
+       if ((caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
                return;
 
        shift = shifts[plane];
@@ -947,10 +1019,17 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
        return channel;
 }
 
+void dispc_wb_set_channel_in(enum dss_writeback_channel channel)
+{
+       enum omap_plane plane = OMAP_DSS_WB;
+
+       REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), channel, 18, 16);
+}
+
 static void dispc_ovl_set_burst_size(enum omap_plane plane,
                enum omap_burst_size burst_size)
 {
-       static const unsigned shifts[] = { 6, 14, 14, 14, };
+       static const unsigned shifts[] = { 6, 14, 14, 14, 14, };
        int shift;
 
        shift = shifts[plane];
@@ -1027,11 +1106,15 @@ static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable)
        dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
 }
 
-static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable)
+static void dispc_ovl_enable_replication(enum omap_plane plane,
+               enum omap_overlay_caps caps, bool enable)
 {
        static const unsigned shifts[] = { 5, 10, 10, 10 };
        int shift;
 
+       if ((caps & OMAP_DSS_OVL_CAP_REPLICATION) == 0)
+               return;
+
        shift = shifts[plane];
        REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
 }
@@ -1045,10 +1128,10 @@ static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
        dispc_write_reg(DISPC_SIZE_MGR(channel), val);
 }
 
-static void dispc_read_plane_fifo_sizes(void)
+static void dispc_init_fifos(void)
 {
        u32 size;
-       int plane;
+       int fifo;
        u8 start, end;
        u32 unit;
 
@@ -1056,16 +1139,53 @@ static void dispc_read_plane_fifo_sizes(void)
 
        dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
 
-       for (plane = 0; plane < dss_feat_get_num_ovls(); ++plane) {
-               size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end);
+       for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
+               size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(fifo), start, end);
                size *= unit;
-               dispc.fifo_size[plane] = size;
+               dispc.fifo_size[fifo] = size;
+
+               /*
+                * By default fifos are mapped directly to overlays, fifo 0 to
+                * ovl 0, fifo 1 to ovl 1, etc.
+                */
+               dispc.fifo_assignment[fifo] = fifo;
+       }
+
+       /*
+        * The GFX fifo on OMAP4 is smaller than the other fifos. The small fifo
+        * causes problems with certain use cases, like using the tiler in 2D
+        * mode. The below hack swaps the fifos of GFX and WB planes, thus
+        * giving GFX plane a larger fifo. WB but should work fine with a
+        * smaller fifo.
+        */
+       if (dispc.feat->gfx_fifo_workaround) {
+               u32 v;
+
+               v = dispc_read_reg(DISPC_GLOBAL_BUFFER);
+
+               v = FLD_MOD(v, 4, 2, 0); /* GFX BUF top to WB */
+               v = FLD_MOD(v, 4, 5, 3); /* GFX BUF bottom to WB */
+               v = FLD_MOD(v, 0, 26, 24); /* WB BUF top to GFX */
+               v = FLD_MOD(v, 0, 29, 27); /* WB BUF bottom to GFX */
+
+               dispc_write_reg(DISPC_GLOBAL_BUFFER, v);
+
+               dispc.fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB;
+               dispc.fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX;
        }
 }
 
 static u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
 {
-       return dispc.fifo_size[plane];
+       int fifo;
+       u32 size = 0;
+
+       for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
+               if (dispc.fifo_assignment[fifo] == plane)
+                       size += dispc.fifo_size[fifo];
+       }
+
+       return size;
 }
 
 void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
@@ -1141,6 +1261,14 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
        if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
                *fifo_low = ovl_fifo_size - burst_size * 2;
                *fifo_high = total_fifo_size - burst_size;
+       } else if (plane == OMAP_DSS_WB) {
+               /*
+                * Most optimal configuration for writeback is to push out data
+                * to the interconnect the moment writeback pushes enough pixels
+                * in the FIFO to form a burst
+                */
+               *fifo_low = 0;
+               *fifo_high = burst_size;
        } else {
                *fifo_low = ovl_fifo_size - burst_size;
                *fifo_high = total_fifo_size - buf_unit;
@@ -1383,6 +1511,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
 {
        int scale_x = out_width != orig_width;
        int scale_y = out_height != orig_height;
+       bool chroma_upscale = plane != OMAP_DSS_WB ? true : false;
 
        if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))
                return;
@@ -1390,7 +1519,8 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
                        color_mode != OMAP_DSS_COLOR_UYVY &&
                        color_mode != OMAP_DSS_COLOR_NV12)) {
                /* reset chroma resampling for RGB formats  */
-               REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
+               if (plane != OMAP_DSS_WB)
+                       REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
                return;
        }
 
@@ -1399,23 +1529,34 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
 
        switch (color_mode) {
        case OMAP_DSS_COLOR_NV12:
-               /* UV is subsampled by 2 vertically*/
-               orig_height >>= 1;
-               /* UV is subsampled by 2 horz.*/
-               orig_width >>= 1;
+               if (chroma_upscale) {
+                       /* UV is subsampled by 2 horizontally and vertically */
+                       orig_height >>= 1;
+                       orig_width >>= 1;
+               } else {
+                       /* UV is downsampled by 2 horizontally and vertically */
+                       orig_height <<= 1;
+                       orig_width <<= 1;
+               }
+
                break;
        case OMAP_DSS_COLOR_YUV2:
        case OMAP_DSS_COLOR_UYVY:
-               /*For YUV422 with 90/270 rotation,
-                *we don't upsample chroma
-                */
+               /* For YUV422 with 90/270 rotation, we don't upsample chroma */
                if (rotation == OMAP_DSS_ROT_0 ||
-                       rotation == OMAP_DSS_ROT_180)
-                       /* UV is subsampled by 2 hrz*/
-                       orig_width >>= 1;
+                               rotation == OMAP_DSS_ROT_180) {
+                       if (chroma_upscale)
+                               /* UV is subsampled by 2 horizontally */
+                               orig_width >>= 1;
+                       else
+                               /* UV is downsampled by 2 horizontally */
+                               orig_width <<= 1;
+               }
+
                /* must use FIR for YUV422 if rotated */
                if (rotation != OMAP_DSS_ROT_0)
                        scale_x = scale_y = true;
+
                break;
        default:
                BUG();
@@ -1431,8 +1572,10 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
                        out_width, out_height, five_taps,
                                rotation, DISPC_COLOR_COMPONENT_UV);
 
-       REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane),
-               (scale_x || scale_y) ? 1 : 0, 8, 8);
+       if (plane != OMAP_DSS_WB)
+               REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane),
+                       (scale_x || scale_y) ? 1 : 0, 8, 8);
+
        /* set H scaling */
        REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
        /* set V scaling */
@@ -1848,22 +1991,19 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
  * This function is used to avoid synclosts in OMAP3, because of some
  * undocumented horizontal position and timing related limitations.
  */
-static int check_horiz_timing_omap3(enum omap_channel channel,
+static int check_horiz_timing_omap3(enum omap_plane plane,
                const struct omap_video_timings *t, u16 pos_x,
                u16 width, u16 height, u16 out_width, u16 out_height)
 {
        int DS = DIV_ROUND_UP(height, out_height);
-       unsigned long nonactive, lclk, pclk;
+       unsigned long nonactive;
        static const u8 limits[3] = { 8, 10, 20 };
        u64 val, blank;
+       unsigned long pclk = dispc_plane_pclk_rate(plane);
+       unsigned long lclk = dispc_plane_lclk_rate(plane);
        int i;
 
        nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
-       pclk = dispc_mgr_pclk_rate(channel);
-       if (dss_mgr_is_lcd(channel))
-               lclk = dispc_mgr_lclk_rate(channel);
-       else
-               lclk = dispc_fclk_rate();
 
        i = 0;
        if (out_height < height)
@@ -1900,13 +2040,14 @@ static int check_horiz_timing_omap3(enum omap_channel channel,
        return 0;
 }
 
-static unsigned long calc_core_clk_five_taps(enum omap_channel channel,
+static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
                const struct omap_video_timings *mgr_timings, u16 width,
                u16 height, u16 out_width, u16 out_height,
                enum omap_color_mode color_mode)
 {
        u32 core_clk = 0;
-       u64 tmp, pclk = dispc_mgr_pclk_rate(channel);
+       u64 tmp;
+       unsigned long pclk = dispc_plane_pclk_rate(plane);
 
        if (height <= out_height && width <= out_width)
                return (unsigned long) pclk;
@@ -1940,11 +2081,22 @@ static unsigned long calc_core_clk_five_taps(enum omap_channel channel,
        return core_clk;
 }
 
-static unsigned long calc_core_clk(enum omap_channel channel, u16 width,
-               u16 height, u16 out_width, u16 out_height)
+static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width,
+               u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
+{
+       unsigned long pclk = dispc_plane_pclk_rate(plane);
+
+       if (height > out_height && width > out_width)
+               return pclk * 4;
+       else
+               return pclk * 2;
+}
+
+static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
+               u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
 {
        unsigned int hf, vf;
-       unsigned long pclk = dispc_mgr_pclk_rate(channel);
+       unsigned long pclk = dispc_plane_pclk_rate(plane);
 
        /*
         * FIXME how to determine the 'A' factor
@@ -1959,51 +2111,207 @@ static unsigned long calc_core_clk(enum omap_channel channel, u16 width,
                hf = 2;
        else
                hf = 1;
-
        if (height > out_height)
                vf = 2;
        else
                vf = 1;
 
-       if (cpu_is_omap24xx()) {
-               if (vf > 1 && hf > 1)
-                       return pclk * 4;
-               else
-                       return pclk * 2;
-       } else if (cpu_is_omap34xx()) {
-               return pclk * vf * hf;
-       } else {
-               if (hf > 1)
-                       return DIV_ROUND_UP(pclk, out_width) * width;
-               else
-                       return pclk;
+       return pclk * vf * hf;
+}
+
+static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
+               u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
+{
+       unsigned long pclk;
+
+       /*
+        * If the overlay/writeback is in mem to mem mode, there are no
+        * downscaling limitations with respect to pixel clock, return 1 as
+        * required core clock to represent that we have sufficient enough
+        * core clock to do maximum downscaling
+        */
+       if (mem_to_mem)
+               return 1;
+
+       pclk = dispc_plane_pclk_rate(plane);
+
+       if (width > out_width)
+               return DIV_ROUND_UP(pclk, out_width) * width;
+       else
+               return pclk;
+}
+
+static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
+               const struct omap_video_timings *mgr_timings,
+               u16 width, u16 height, u16 out_width, u16 out_height,
+               enum omap_color_mode color_mode, bool *five_taps,
+               int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+               u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
+{
+       int error;
+       u16 in_width, in_height;
+       int min_factor = min(*decim_x, *decim_y);
+       const int maxsinglelinewidth =
+                       dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
+
+       *five_taps = false;
+
+       do {
+               in_height = DIV_ROUND_UP(height, *decim_y);
+               in_width = DIV_ROUND_UP(width, *decim_x);
+               *core_clk = dispc.feat->calc_core_clk(plane, in_width,
+                               in_height, out_width, out_height, mem_to_mem);
+               error = (in_width > maxsinglelinewidth || !*core_clk ||
+                       *core_clk > dispc_core_clk_rate());
+               if (error) {
+                       if (*decim_x == *decim_y) {
+                               *decim_x = min_factor;
+                               ++*decim_y;
+                       } else {
+                               swap(*decim_x, *decim_y);
+                               if (*decim_x < *decim_y)
+                                       ++*decim_x;
+                       }
+               }
+       } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
+
+       if (in_width > maxsinglelinewidth) {
+               DSSERR("Cannot scale max input width exceeded");
+               return -EINVAL;
        }
+       return 0;
 }
 
-static int dispc_ovl_calc_scaling(enum omap_plane plane,
-               enum omap_channel channel,
+static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
                const struct omap_video_timings *mgr_timings,
                u16 width, u16 height, u16 out_width, u16 out_height,
                enum omap_color_mode color_mode, bool *five_taps,
-               int *x_predecim, int *y_predecim, u16 pos_x)
+               int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+               u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
 {
-       struct omap_overlay *ovl = omap_dss_get_overlay(plane);
-       const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
+       int error;
+       u16 in_width, in_height;
+       int min_factor = min(*decim_x, *decim_y);
+       const int maxsinglelinewidth =
+                       dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
+
+       do {
+               in_height = DIV_ROUND_UP(height, *decim_y);
+               in_width = DIV_ROUND_UP(width, *decim_x);
+               *core_clk = calc_core_clk_five_taps(plane, mgr_timings,
+                       in_width, in_height, out_width, out_height, color_mode);
+
+               error = check_horiz_timing_omap3(plane, mgr_timings,
+                               pos_x, in_width, in_height, out_width,
+                               out_height);
+
+               if (in_width > maxsinglelinewidth)
+                       if (in_height > out_height &&
+                                               in_height < out_height * 2)
+                               *five_taps = false;
+               if (!*five_taps)
+                       *core_clk = dispc.feat->calc_core_clk(plane, in_width,
+                                       in_height, out_width, out_height,
+                                       mem_to_mem);
+
+               error = (error || in_width > maxsinglelinewidth * 2 ||
+                       (in_width > maxsinglelinewidth && *five_taps) ||
+                       !*core_clk || *core_clk > dispc_core_clk_rate());
+               if (error) {
+                       if (*decim_x == *decim_y) {
+                               *decim_x = min_factor;
+                               ++*decim_y;
+                       } else {
+                               swap(*decim_x, *decim_y);
+                               if (*decim_x < *decim_y)
+                                       ++*decim_x;
+                       }
+               }
+       } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
+
+       if (check_horiz_timing_omap3(plane, mgr_timings, pos_x, width, height,
+               out_width, out_height)){
+                       DSSERR("horizontal timing too tight\n");
+                       return -EINVAL;
+       }
+
+       if (in_width > (maxsinglelinewidth * 2)) {
+               DSSERR("Cannot setup scaling");
+               DSSERR("width exceeds maximum width possible");
+               return -EINVAL;
+       }
+
+       if (in_width > maxsinglelinewidth && *five_taps) {
+               DSSERR("cannot setup scaling with five taps");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
+               const struct omap_video_timings *mgr_timings,
+               u16 width, u16 height, u16 out_width, u16 out_height,
+               enum omap_color_mode color_mode, bool *five_taps,
+               int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+               u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
+{
+       u16 in_width, in_width_max;
+       int decim_x_min = *decim_x;
+       u16 in_height = DIV_ROUND_UP(height, *decim_y);
        const int maxsinglelinewidth =
                                dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
+       unsigned long pclk = dispc_plane_pclk_rate(plane);
+       const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
+
+       if (mem_to_mem)
+               in_width_max = DIV_ROUND_UP(out_width, maxdownscale);
+       else
+               in_width_max = dispc_core_clk_rate() /
+                                       DIV_ROUND_UP(pclk, out_width);
+
+       *decim_x = DIV_ROUND_UP(width, in_width_max);
+
+       *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min;
+       if (*decim_x > *x_predecim)
+               return -EINVAL;
+
+       do {
+               in_width = DIV_ROUND_UP(width, *decim_x);
+       } while (*decim_x <= *x_predecim &&
+                       in_width > maxsinglelinewidth && ++*decim_x);
+
+       if (in_width > maxsinglelinewidth) {
+               DSSERR("Cannot scale width exceeds max line width");
+               return -EINVAL;
+       }
+
+       *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height,
+                               out_width, out_height, mem_to_mem);
+       return 0;
+}
+
+static int dispc_ovl_calc_scaling(enum omap_plane plane,
+               enum omap_overlay_caps caps,
+               const struct omap_video_timings *mgr_timings,
+               u16 width, u16 height, u16 out_width, u16 out_height,
+               enum omap_color_mode color_mode, bool *five_taps,
+               int *x_predecim, int *y_predecim, u16 pos_x,
+               enum omap_dss_rotation_type rotation_type, bool mem_to_mem)
+{
+       const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
        const int max_decim_limit = 16;
        unsigned long core_clk = 0;
-       int decim_x, decim_y, error, min_factor;
-       u16 in_width, in_height, in_width_max = 0;
+       int decim_x, decim_y, ret;
 
        if (width == out_width && height == out_height)
                return 0;
 
-       if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
+       if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
                return -EINVAL;
 
        *x_predecim = max_decim_limit;
-       *y_predecim = max_decim_limit;
+       *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
+                       dss_has_feature(FEAT_BURST_2D)) ? 2 : max_decim_limit;
 
        if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
            color_mode == OMAP_DSS_COLOR_CLUT2 ||
@@ -2018,118 +2326,18 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
        decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);
        decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale);
 
-       min_factor = min(decim_x, decim_y);
-
        if (decim_x > *x_predecim || out_width > width * 8)
                return -EINVAL;
 
        if (decim_y > *y_predecim || out_height > height * 8)
                return -EINVAL;
 
-       if (cpu_is_omap24xx()) {
-               *five_taps = false;
-
-               do {
-                       in_height = DIV_ROUND_UP(height, decim_y);
-                       in_width = DIV_ROUND_UP(width, decim_x);
-                       core_clk = calc_core_clk(channel, in_width, in_height,
-                                       out_width, out_height);
-                       error = (in_width > maxsinglelinewidth || !core_clk ||
-                               core_clk > dispc_core_clk_rate());
-                       if (error) {
-                               if (decim_x == decim_y) {
-                                       decim_x = min_factor;
-                                       decim_y++;
-                               } else {
-                                       swap(decim_x, decim_y);
-                                       if (decim_x < decim_y)
-                                               decim_x++;
-                               }
-                       }
-               } while (decim_x <= *x_predecim && decim_y <= *y_predecim &&
-                               error);
-
-               if (in_width > maxsinglelinewidth) {
-                       DSSERR("Cannot scale max input width exceeded");
-                       return -EINVAL;
-               }
-       } else if (cpu_is_omap34xx()) {
-
-               do {
-                       in_height = DIV_ROUND_UP(height, decim_y);
-                       in_width = DIV_ROUND_UP(width, decim_x);
-                       core_clk = calc_core_clk_five_taps(channel, mgr_timings,
-                               in_width, in_height, out_width, out_height,
-                               color_mode);
-
-                       error = check_horiz_timing_omap3(channel, mgr_timings,
-                               pos_x, in_width, in_height, out_width,
-                               out_height);
-
-                       if (in_width > maxsinglelinewidth)
-                               if (in_height > out_height &&
-                                       in_height < out_height * 2)
-                                       *five_taps = false;
-                       if (!*five_taps)
-                               core_clk = calc_core_clk(channel, in_width,
-                                       in_height, out_width, out_height);
-                       error = (error || in_width > maxsinglelinewidth * 2 ||
-                               (in_width > maxsinglelinewidth && *five_taps) ||
-                               !core_clk || core_clk > dispc_core_clk_rate());
-                       if (error) {
-                               if (decim_x == decim_y) {
-                                       decim_x = min_factor;
-                                       decim_y++;
-                               } else {
-                                       swap(decim_x, decim_y);
-                                       if (decim_x < decim_y)
-                                               decim_x++;
-                               }
-                       }
-               } while (decim_x <= *x_predecim && decim_y <= *y_predecim
-                       && error);
-
-               if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width,
-                       height, out_width, out_height)){
-                               DSSERR("horizontal timing too tight\n");
-                               return -EINVAL;
-               }
-
-               if (in_width > (maxsinglelinewidth * 2)) {
-                       DSSERR("Cannot setup scaling");
-                       DSSERR("width exceeds maximum width possible");
-                       return -EINVAL;
-               }
-
-               if (in_width > maxsinglelinewidth && *five_taps) {
-                       DSSERR("cannot setup scaling with five taps");
-                       return -EINVAL;
-               }
-       } else {
-               int decim_x_min = decim_x;
-               in_height = DIV_ROUND_UP(height, decim_y);
-               in_width_max = dispc_core_clk_rate() /
-                               DIV_ROUND_UP(dispc_mgr_pclk_rate(channel),
-                                               out_width);
-               decim_x = DIV_ROUND_UP(width, in_width_max);
-
-               decim_x = decim_x > decim_x_min ? decim_x : decim_x_min;
-               if (decim_x > *x_predecim)
-                       return -EINVAL;
-
-               do {
-                       in_width = DIV_ROUND_UP(width, decim_x);
-               } while (decim_x <= *x_predecim &&
-                               in_width > maxsinglelinewidth && decim_x++);
-
-               if (in_width > maxsinglelinewidth) {
-                       DSSERR("Cannot scale width exceeds max line width");
-                       return -EINVAL;
-               }
-
-               core_clk = calc_core_clk(channel, in_width, in_height,
-                               out_width, out_height);
-       }
+       ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height,
+               out_width, out_height, color_mode, five_taps,
+               x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
+               mem_to_mem);
+       if (ret)
+               return ret;
 
        DSSDBG("required core clk rate = %lu Hz\n", core_clk);
        DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
@@ -2147,69 +2355,64 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
        return 0;
 }
 
-int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
-               bool replication, const struct omap_video_timings *mgr_timings)
+static int dispc_ovl_setup_common(enum omap_plane plane,
+               enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
+               u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
+               u16 out_width, u16 out_height, enum omap_color_mode color_mode,
+               u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
+               u8 global_alpha, enum omap_dss_rotation_type rotation_type,
+               bool replication, const struct omap_video_timings *mgr_timings,
+               bool mem_to_mem)
 {
-       struct omap_overlay *ovl = omap_dss_get_overlay(plane);
        bool five_taps = true;
        bool fieldmode = 0;
        int r, cconv = 0;
        unsigned offset0, offset1;
        s32 row_inc;
        s32 pix_inc;
-       u16 frame_height = oi->height;
+       u16 frame_height = height;
        unsigned int field_offset = 0;
-       u16 in_height = oi->height;
-       u16 in_width = oi->width;
-       u16 out_width, out_height;
-       enum omap_channel channel;
+       u16 in_height = height;
+       u16 in_width = width;
        int x_predecim = 1, y_predecim = 1;
        bool ilace = mgr_timings->interlace;
 
-       channel = dispc_ovl_get_channel_out(plane);
-
-       DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
-               "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d\n",
-               plane, oi->paddr, oi->p_uv_addr,
-               oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
-               oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
-               oi->mirror, ilace, channel, replication);
-
-       if (oi->paddr == 0)
+       if (paddr == 0)
                return -EINVAL;
 
-       out_width = oi->out_width == 0 ? oi->width : oi->out_width;
-       out_height = oi->out_height == 0 ? oi->height : oi->out_height;
+       out_width = out_width == 0 ? width : out_width;
+       out_height = out_height == 0 ? height : out_height;
 
-       if (ilace && oi->height == out_height)
+       if (ilace && height == out_height)
                fieldmode = 1;
 
        if (ilace) {
                if (fieldmode)
                        in_height /= 2;
-               oi->pos_y /= 2;
+               pos_y /= 2;
                out_height /= 2;
 
                DSSDBG("adjusting for ilace: height %d, pos_y %d, "
-                               "out_height %d\n",
-                               in_height, oi->pos_y, out_height);
+                       "out_height %d\n", in_height, pos_y,
+                       out_height);
        }
 
-       if (!dss_feat_color_mode_supported(plane, oi->color_mode))
+       if (!dss_feat_color_mode_supported(plane, color_mode))
                return -EINVAL;
 
-       r = dispc_ovl_calc_scaling(plane, channel, mgr_timings, in_width,
-                       in_height, out_width, out_height, oi->color_mode,
-                       &five_taps, &x_predecim, &y_predecim, oi->pos_x);
+       r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width,
+                       in_height, out_width, out_height, color_mode,
+                       &five_taps, &x_predecim, &y_predecim, pos_x,
+                       rotation_type, mem_to_mem);
        if (r)
                return r;
 
        in_width = DIV_ROUND_UP(in_width, x_predecim);
        in_height = DIV_ROUND_UP(in_height, y_predecim);
 
-       if (oi->color_mode == OMAP_DSS_COLOR_YUV2 ||
-                       oi->color_mode == OMAP_DSS_COLOR_UYVY ||
-                       oi->color_mode == OMAP_DSS_COLOR_NV12)
+       if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+                       color_mode == OMAP_DSS_COLOR_UYVY ||
+                       color_mode == OMAP_DSS_COLOR_NV12)
                cconv = 1;
 
        if (ilace && !fieldmode) {
@@ -2235,70 +2438,144 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
        row_inc = 0;
        pix_inc = 0;
 
-       if (oi->rotation_type == OMAP_DSS_ROT_TILER)
-               calc_tiler_rotation_offset(oi->screen_width, in_width,
-                               oi->color_mode, fieldmode, field_offset,
+       if (rotation_type == OMAP_DSS_ROT_TILER)
+               calc_tiler_rotation_offset(screen_width, in_width,
+                               color_mode, fieldmode, field_offset,
                                &offset0, &offset1, &row_inc, &pix_inc,
                                x_predecim, y_predecim);
-       else if (oi->rotation_type == OMAP_DSS_ROT_DMA)
-               calc_dma_rotation_offset(oi->rotation, oi->mirror,
-                               oi->screen_width, in_width, frame_height,
-                               oi->color_mode, fieldmode, field_offset,
+       else if (rotation_type == OMAP_DSS_ROT_DMA)
+               calc_dma_rotation_offset(rotation, mirror,
+                               screen_width, in_width, frame_height,
+                               color_mode, fieldmode, field_offset,
                                &offset0, &offset1, &row_inc, &pix_inc,
                                x_predecim, y_predecim);
        else
-               calc_vrfb_rotation_offset(oi->rotation, oi->mirror,
-                               oi->screen_width, in_width, frame_height,
-                               oi->color_mode, fieldmode, field_offset,
+               calc_vrfb_rotation_offset(rotation, mirror,
+                               screen_width, in_width, frame_height,
+                               color_mode, fieldmode, field_offset,
                                &offset0, &offset1, &row_inc, &pix_inc,
                                x_predecim, y_predecim);
 
        DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
                        offset0, offset1, row_inc, pix_inc);
 
-       dispc_ovl_set_color_mode(plane, oi->color_mode);
+       dispc_ovl_set_color_mode(plane, color_mode);
 
-       dispc_ovl_configure_burst_type(plane, oi->rotation_type);
+       dispc_ovl_configure_burst_type(plane, rotation_type);
 
-       dispc_ovl_set_ba0(plane, oi->paddr + offset0);
-       dispc_ovl_set_ba1(plane, oi->paddr + offset1);
+       dispc_ovl_set_ba0(plane, paddr + offset0);
+       dispc_ovl_set_ba1(plane, paddr + offset1);
 
-       if (OMAP_DSS_COLOR_NV12 == oi->color_mode) {
-               dispc_ovl_set_ba0_uv(plane, oi->p_uv_addr + offset0);
-               dispc_ovl_set_ba1_uv(plane, oi->p_uv_addr + offset1);
+       if (OMAP_DSS_COLOR_NV12 == color_mode) {
+               dispc_ovl_set_ba0_uv(plane, p_uv_addr + offset0);
+               dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1);
        }
 
-
        dispc_ovl_set_row_inc(plane, row_inc);
        dispc_ovl_set_pix_inc(plane, pix_inc);
 
-       DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, in_width,
+       DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, in_width,
                        in_height, out_width, out_height);
 
-       dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y);
+       dispc_ovl_set_pos(plane, caps, pos_x, pos_y);
 
-       dispc_ovl_set_pic_size(plane, in_width, in_height);
+       dispc_ovl_set_input_size(plane, in_width, in_height);
 
-       if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) {
+       if (caps & OMAP_DSS_OVL_CAP_SCALE) {
                dispc_ovl_set_scaling(plane, in_width, in_height, out_width,
                                   out_height, ilace, five_taps, fieldmode,
-                                  oi->color_mode, oi->rotation);
-               dispc_ovl_set_vid_size(plane, out_width, out_height);
+                                  color_mode, rotation);
+               dispc_ovl_set_output_size(plane, out_width, out_height);
                dispc_ovl_set_vid_color_conv(plane, cconv);
        }
 
-       dispc_ovl_set_rotation_attrs(plane, oi->rotation, oi->mirror,
-                       oi->color_mode);
+       dispc_ovl_set_rotation_attrs(plane, rotation, mirror, color_mode);
 
-       dispc_ovl_set_zorder(plane, oi->zorder);
-       dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha);
-       dispc_ovl_setup_global_alpha(plane, oi->global_alpha);
+       dispc_ovl_set_zorder(plane, caps, zorder);
+       dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha);
+       dispc_ovl_setup_global_alpha(plane, caps, global_alpha);
 
-       dispc_ovl_enable_replication(plane, replication);
+       dispc_ovl_enable_replication(plane, caps, replication);
 
        return 0;
 }
 
+int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
+               bool replication, const struct omap_video_timings *mgr_timings,
+               bool mem_to_mem)
+{
+       int r;
+       struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+       enum omap_channel channel;
+
+       channel = dispc_ovl_get_channel_out(plane);
+
+       DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
+               "%dx%d, cmode %x, rot %d, mir %d, chan %d repl %d\n",
+               plane, oi->paddr, oi->p_uv_addr, oi->screen_width, oi->pos_x,
+               oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
+               oi->color_mode, oi->rotation, oi->mirror, channel, replication);
+
+       r = dispc_ovl_setup_common(plane, ovl->caps, oi->paddr, oi->p_uv_addr,
+               oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
+               oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
+               oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
+               oi->rotation_type, replication, mgr_timings, mem_to_mem);
+
+       return r;
+}
+
+int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
+               bool mem_to_mem, const struct omap_video_timings *mgr_timings)
+{
+       int r;
+       u32 l;
+       enum omap_plane plane = OMAP_DSS_WB;
+       const int pos_x = 0, pos_y = 0;
+       const u8 zorder = 0, global_alpha = 0;
+       const bool replication = false;
+       bool truncation;
+       int in_width = mgr_timings->x_res;
+       int in_height = mgr_timings->y_res;
+       enum omap_overlay_caps caps =
+               OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA;
+
+       DSSDBG("dispc_wb_setup, pa %x, pa_uv %x, %d,%d -> %dx%d, cmode %x, "
+               "rot %d, mir %d\n", wi->paddr, wi->p_uv_addr, in_width,
+               in_height, wi->width, wi->height, wi->color_mode, wi->rotation,
+               wi->mirror);
+
+       r = dispc_ovl_setup_common(plane, caps, wi->paddr, wi->p_uv_addr,
+               wi->buf_width, pos_x, pos_y, in_width, in_height, wi->width,
+               wi->height, wi->color_mode, wi->rotation, wi->mirror, zorder,
+               wi->pre_mult_alpha, global_alpha, wi->rotation_type,
+               replication, mgr_timings, mem_to_mem);
+
+       switch (wi->color_mode) {
+       case OMAP_DSS_COLOR_RGB16:
+       case OMAP_DSS_COLOR_RGB24P:
+       case OMAP_DSS_COLOR_ARGB16:
+       case OMAP_DSS_COLOR_RGBA16:
+       case OMAP_DSS_COLOR_RGB12U:
+       case OMAP_DSS_COLOR_ARGB16_1555:
+       case OMAP_DSS_COLOR_XRGB16_1555:
+       case OMAP_DSS_COLOR_RGBX16:
+               truncation = true;
+               break;
+       default:
+               truncation = false;
+               break;
+       }
+
+       /* setup extra DISPC_WB_ATTRIBUTES */
+       l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
+       l = FLD_MOD(l, truncation, 10, 10);     /* TRUNCATIONENABLE */
+       l = FLD_MOD(l, mem_to_mem, 19, 19);     /* WRITEBACKMODE */
+       dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l);
+
+       return r;
+}
+
 int dispc_ovl_enable(enum omap_plane plane, bool enable)
 {
        DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
@@ -2451,6 +2728,47 @@ void dispc_mgr_enable(enum omap_channel channel, bool enable)
                BUG();
 }
 
+void dispc_wb_enable(bool enable)
+{
+       enum omap_plane plane = OMAP_DSS_WB;
+       struct completion frame_done_completion;
+       bool is_on;
+       int r;
+       u32 irq;
+
+       is_on = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
+       irq = DISPC_IRQ_FRAMEDONEWB;
+
+       if (!enable && is_on) {
+               init_completion(&frame_done_completion);
+
+               r = omap_dispc_register_isr(dispc_disable_isr,
+                               &frame_done_completion, irq);
+               if (r)
+                       DSSERR("failed to register FRAMEDONEWB isr\n");
+       }
+
+       REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
+
+       if (!enable && is_on) {
+               if (!wait_for_completion_timeout(&frame_done_completion,
+                                       msecs_to_jiffies(100)))
+                       DSSERR("timeout waiting for FRAMEDONEWB\n");
+
+               r = omap_dispc_unregister_isr(dispc_disable_isr,
+                               &frame_done_completion, irq);
+               if (r)
+                       DSSERR("failed to unregister FRAMEDONEWB isr\n");
+       }
+}
+
+bool dispc_wb_is_enabled(void)
+{
+       enum omap_plane plane = OMAP_DSS_WB;
+
+       return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
+}
+
 void dispc_lcd_enable_signal_polarity(bool act_high)
 {
        if (!dss_has_feature(FEAT_LCDENABLEPOL))
@@ -2605,24 +2923,13 @@ static bool _dispc_mgr_size_ok(u16 width, u16 height)
 static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
                int vsw, int vfp, int vbp)
 {
-       if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
-               if (hsw < 1 || hsw > 64 ||
-                               hfp < 1 || hfp > 256 ||
-                               hbp < 1 || hbp > 256 ||
-                               vsw < 1 || vsw > 64 ||
-                               vfp < 0 || vfp > 255 ||
-                               vbp < 0 || vbp > 255)
-                       return false;
-       } else {
-               if (hsw < 1 || hsw > 256 ||
-                               hfp < 1 || hfp > 4096 ||
-                               hbp < 1 || hbp > 4096 ||
-                               vsw < 1 || vsw > 256 ||
-                               vfp < 0 || vfp > 4095 ||
-                               vbp < 0 || vbp > 4095)
-                       return false;
-       }
-
+       if (hsw < 1 || hsw > dispc.feat->sw_max ||
+                       hfp < 1 || hfp > dispc.feat->hp_max ||
+                       hbp < 1 || hbp > dispc.feat->hp_max ||
+                       vsw < 1 || vsw > dispc.feat->sw_max ||
+                       vfp < 0 || vfp > dispc.feat->vp_max ||
+                       vbp < 0 || vbp > dispc.feat->vp_max)
+               return false;
        return true;
 }
 
@@ -2654,19 +2961,12 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
        u32 timing_h, timing_v, l;
        bool onoff, rf, ipc;
 
-       if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
-               timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
-                       FLD_VAL(hbp-1, 27, 20);
-
-               timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
-                       FLD_VAL(vbp, 27, 20);
-       } else {
-               timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
-                       FLD_VAL(hbp-1, 31, 20);
-
-               timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
-                       FLD_VAL(vbp, 31, 20);
-       }
+       timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) |
+                       FLD_VAL(hfp-1, dispc.feat->fp_start, 8) |
+                       FLD_VAL(hbp-1, dispc.feat->bp_start, 20);
+       timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) |
+                       FLD_VAL(vfp, dispc.feat->fp_start, 8) |
+                       FLD_VAL(vbp, dispc.feat->bp_start, 20);
 
        dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
        dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
@@ -2872,6 +3172,23 @@ unsigned long dispc_core_clk_rate(void)
        return fclk / lcd;
 }
 
+static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
+{
+       enum omap_channel channel = dispc_ovl_get_channel_out(plane);
+
+       return dispc_mgr_pclk_rate(channel);
+}
+
+static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
+{
+       enum omap_channel channel = dispc_ovl_get_channel_out(plane);
+
+       if (dss_mgr_is_lcd(channel))
+               return dispc_mgr_lclk_rate(channel);
+       else
+               return dispc_fclk_rate();
+
+}
 static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
 {
        int lcd, pcd;
@@ -3492,7 +3809,7 @@ static void dispc_error_worker(struct work_struct *work)
                                        ovl->name);
                        dispc_ovl_enable(ovl->id, false);
                        dispc_mgr_go(ovl->manager->id);
-                       mdelay(50);
+                       msleep(50);
                }
        }
 
@@ -3504,7 +3821,7 @@ static void dispc_error_worker(struct work_struct *work)
                bit = mgr_desc[i].sync_lost_irq;
 
                if (bit & errors) {
-                       struct omap_dss_device *dssdev = mgr->device;
+                       struct omap_dss_device *dssdev = mgr->get_device(mgr);
                        bool enable;
 
                        DSSERR("SYNC_LOST on channel %s, restarting the output "
@@ -3524,7 +3841,7 @@ static void dispc_error_worker(struct work_struct *work)
                        }
 
                        dispc_mgr_go(mgr->id);
-                       mdelay(50);
+                       msleep(50);
 
                        if (enable)
                                dssdev->driver->enable(dssdev);
@@ -3535,9 +3852,13 @@ static void dispc_error_worker(struct work_struct *work)
                DSSERR("OCP_ERR\n");
                for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
                        struct omap_overlay_manager *mgr;
+                       struct omap_dss_device *dssdev;
+
                        mgr = omap_dss_get_overlay_manager(i);
-                       if (mgr->device && mgr->device->driver)
-                               mgr->device->driver->disable(mgr->device);
+                       dssdev = mgr->get_device(mgr);
+
+                       if (dssdev && dssdev->driver)
+                               dssdev->driver->disable(dssdev);
                }
        }
 
@@ -3661,17 +3982,98 @@ static void _omap_dispc_initial_config(void)
        if (dss_has_feature(FEAT_FUNCGATED))
                REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
 
-       _dispc_setup_color_conv_coef();
+       dispc_setup_color_conv_coef();
 
        dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
 
-       dispc_read_plane_fifo_sizes();
+       dispc_init_fifos();
 
        dispc_configure_burst_sizes();
 
        dispc_ovl_enable_zorder_planes();
 }
 
+static const struct dispc_features omap24xx_dispc_feats __initconst = {
+       .sw_start               =       5,
+       .fp_start               =       15,
+       .bp_start               =       27,
+       .sw_max                 =       64,
+       .vp_max                 =       255,
+       .hp_max                 =       256,
+       .calc_scaling           =       dispc_ovl_calc_scaling_24xx,
+       .calc_core_clk          =       calc_core_clk_24xx,
+       .num_fifos              =       3,
+};
+
+static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
+       .sw_start               =       5,
+       .fp_start               =       15,
+       .bp_start               =       27,
+       .sw_max                 =       64,
+       .vp_max                 =       255,
+       .hp_max                 =       256,
+       .calc_scaling           =       dispc_ovl_calc_scaling_34xx,
+       .calc_core_clk          =       calc_core_clk_34xx,
+       .num_fifos              =       3,
+};
+
+static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
+       .sw_start               =       7,
+       .fp_start               =       19,
+       .bp_start               =       31,
+       .sw_max                 =       256,
+       .vp_max                 =       4095,
+       .hp_max                 =       4096,
+       .calc_scaling           =       dispc_ovl_calc_scaling_34xx,
+       .calc_core_clk          =       calc_core_clk_34xx,
+       .num_fifos              =       3,
+};
+
+static const struct dispc_features omap44xx_dispc_feats __initconst = {
+       .sw_start               =       7,
+       .fp_start               =       19,
+       .bp_start               =       31,
+       .sw_max                 =       256,
+       .vp_max                 =       4095,
+       .hp_max                 =       4096,
+       .calc_scaling           =       dispc_ovl_calc_scaling_44xx,
+       .calc_core_clk          =       calc_core_clk_44xx,
+       .num_fifos              =       5,
+       .gfx_fifo_workaround    =       true,
+};
+
+static int __init dispc_init_features(struct device *dev)
+{
+       const struct dispc_features *src;
+       struct dispc_features *dst;
+
+       dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+       if (!dst) {
+               dev_err(dev, "Failed to allocate DISPC Features\n");
+               return -ENOMEM;
+       }
+
+       if (cpu_is_omap24xx()) {
+               src = &omap24xx_dispc_feats;
+       } else if (cpu_is_omap34xx()) {
+               if (omap_rev() < OMAP3430_REV_ES3_0)
+                       src = &omap34xx_rev1_0_dispc_feats;
+               else
+                       src = &omap34xx_rev3_0_dispc_feats;
+       } else if (cpu_is_omap44xx()) {
+               src = &omap44xx_dispc_feats;
+       } else if (soc_is_omap54xx()) {
+               src = &omap44xx_dispc_feats;
+       } else {
+               return -ENODEV;
+       }
+
+       memcpy(dst, src, sizeof(*dst));
+       dispc.feat = dst;
+
+       return 0;
+}
+
 /* DISPC HW IP initialisation */
 static int __init omap_dispchw_probe(struct platform_device *pdev)
 {
@@ -3682,6 +4084,10 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
 
        dispc.pdev = pdev;
 
+       r = dispc_init_features(&dispc.pdev->dev);
+       if (r)
+               return r;
+
        spin_lock_init(&dispc.irq_lock);
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
index 92d8a9be86fc640a5efae0541dd410166a03550f..222363c6e623f794402f68b98d419f5fc0d1f869 100644 (file)
@@ -36,6 +36,7 @@
 #define DISPC_CONTROL2                 0x0238
 #define DISPC_CONFIG2                  0x0620
 #define DISPC_DIVISOR                  0x0804
+#define DISPC_GLOBAL_BUFFER            0x0800
 #define DISPC_CONTROL3                  0x0848
 #define DISPC_CONFIG3                   0x084C
 
@@ -355,6 +356,8 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
                return 0x014C;
        case OMAP_DSS_VIDEO3:
                return 0x0300;
+       case OMAP_DSS_WB:
+               return 0x0500;
        default:
                BUG();
                return 0;
@@ -370,6 +373,7 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO2:
                return 0x0000;
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x0008;
        default:
                BUG();
@@ -385,6 +389,7 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO2:
                return 0x0004;
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x000C;
        default:
                BUG();
@@ -404,6 +409,8 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
                return 0x04BC;
        case OMAP_DSS_VIDEO3:
                return 0x0310;
+       case OMAP_DSS_WB:
+               return 0x0118;
        default:
                BUG();
                return 0;
@@ -422,6 +429,8 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
                return 0x04C0;
        case OMAP_DSS_VIDEO3:
                return 0x0314;
+       case OMAP_DSS_WB:
+               return 0x011C;
        default:
                BUG();
                return 0;
@@ -451,6 +460,7 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO2:
                return 0x000C;
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x00A8;
        default:
                BUG();
@@ -467,6 +477,7 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO2:
                return 0x0010;
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x0070;
        default:
                BUG();
@@ -486,6 +497,8 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
                return 0x04DC;
        case OMAP_DSS_VIDEO3:
                return 0x032C;
+       case OMAP_DSS_WB:
+               return 0x0310;
        default:
                BUG();
                return 0;
@@ -501,6 +514,7 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO2:
                return 0x0014;
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x008C;
        default:
                BUG();
@@ -517,6 +531,7 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO2:
                return 0x0018;
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x0088;
        default:
                BUG();
@@ -533,6 +548,7 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO2:
                return 0x001C;
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x00A4;
        default:
                BUG();
@@ -549,6 +565,7 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO2:
                return 0x0020;
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x0098;
        default:
                BUG();
@@ -598,6 +615,7 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO2:
                return 0x0024;
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x0090;
        default:
                BUG();
@@ -617,6 +635,8 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
                return 0x055C;
        case OMAP_DSS_VIDEO3:
                return 0x0424;
+       case OMAP_DSS_WB:
+               return 0x290;
        default:
                BUG();
                return 0;
@@ -633,6 +653,7 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO2:
                return 0x0028;
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x0094;
        default:
                BUG();
@@ -651,6 +672,7 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO2:
                return 0x002C;
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x0000;
        default:
                BUG();
@@ -670,6 +692,8 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
                return 0x0560;
        case OMAP_DSS_VIDEO3:
                return 0x0428;
+       case OMAP_DSS_WB:
+               return 0x0294;
        default:
                BUG();
                return 0;
@@ -686,6 +710,7 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO2:
                return 0x0030;
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x0004;
        default:
                BUG();
@@ -705,6 +730,8 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
                return 0x0564;
        case OMAP_DSS_VIDEO3:
                return 0x042C;
+       case OMAP_DSS_WB:
+               return 0x0298;
        default:
                BUG();
                return 0;
@@ -722,6 +749,7 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
        case OMAP_DSS_VIDEO2:
                return 0x0034 + i * 0x8;
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x0010 + i * 0x8;
        default:
                BUG();
@@ -742,6 +770,8 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
                return 0x0568 + i * 0x8;
        case OMAP_DSS_VIDEO3:
                return 0x0430 + i * 0x8;
+       case OMAP_DSS_WB:
+               return 0x02A0 + i * 0x8;
        default:
                BUG();
                return 0;
@@ -759,6 +789,7 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
        case OMAP_DSS_VIDEO2:
                return 0x0038 + i * 0x8;
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x0014 + i * 0x8;
        default:
                BUG();
@@ -779,6 +810,8 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
                return 0x056C + i * 0x8;
        case OMAP_DSS_VIDEO3:
                return 0x0434 + i * 0x8;
+       case OMAP_DSS_WB:
+               return 0x02A4 + i * 0x8;
        default:
                BUG();
                return 0;
@@ -795,6 +828,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x0074 + i * 0x4;
        default:
                BUG();
@@ -814,6 +848,7 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
        case OMAP_DSS_VIDEO2:
                return 0x00B4 + i * 0x4;
        case OMAP_DSS_VIDEO3:
+       case OMAP_DSS_WB:
                return 0x0050 + i * 0x4;
        default:
                BUG();
@@ -834,6 +869,8 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
                return 0x05A8 + i * 0x4;
        case OMAP_DSS_VIDEO3:
                return 0x0470 + i * 0x4;
+       case OMAP_DSS_WB:
+               return 0x02E0 + i * 0x4;
        default:
                BUG();
                return 0;
index 5bd957e85505465990301d4a78abf4dd2f8e05a4..ccf8550fafdedf5440a5fc6e585b7cf8d02f2b0d 100644 (file)
@@ -142,7 +142,11 @@ static ssize_t display_timings_store(struct device *dev,
        if (r)
                return r;
 
+       dssdev->driver->disable(dssdev);
        dssdev->driver->set_timings(dssdev, &t);
+       r = dssdev->driver->enable(dssdev);
+       if (r)
+               return r;
 
        return size;
 }
@@ -316,26 +320,117 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
 }
 EXPORT_SYMBOL(omapdss_default_get_timings);
 
-void dss_init_device(struct platform_device *pdev,
+/*
+ * Connect dssdev to a manager if the manager is free or if force is specified.
+ * Connect all overlays to that manager if they are free or if force is
+ * specified.
+ */
+static int dss_init_connections(struct omap_dss_device *dssdev, bool force)
+{
+       struct omap_dss_output *out;
+       struct omap_overlay_manager *mgr;
+       int i, r;
+
+       out = omapdss_get_output_from_dssdev(dssdev);
+
+       WARN_ON(dssdev->output);
+       WARN_ON(out->device);
+
+       r = omapdss_output_set_device(out, dssdev);
+       if (r) {
+               DSSERR("failed to connect output to new device\n");
+               return r;
+       }
+
+       mgr = omap_dss_get_overlay_manager(dssdev->channel);
+
+       if (mgr->output && !force)
+               return 0;
+
+       if (mgr->output)
+               mgr->unset_output(mgr);
+
+       r = mgr->set_output(mgr, out);
+       if (r) {
+               DSSERR("failed to connect manager to output of new device\n");
+
+               /* remove the output-device connection we just made */
+               omapdss_output_unset_device(out);
+               return r;
+       }
+
+       for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+               struct omap_overlay *ovl = omap_dss_get_overlay(i);
+
+               if (!ovl->manager || force) {
+                       if (ovl->manager)
+                               ovl->unset_manager(ovl);
+
+                       r = ovl->set_manager(ovl, mgr);
+                       if (r) {
+                               DSSERR("failed to set initial overlay\n");
+                               return r;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static void dss_uninit_connections(struct omap_dss_device *dssdev)
+{
+       if (dssdev->output) {
+               struct omap_overlay_manager *mgr = dssdev->output->manager;
+
+               if (mgr)
+                       mgr->unset_output(mgr);
+
+               omapdss_output_unset_device(dssdev->output);
+       }
+}
+
+int dss_init_device(struct platform_device *pdev,
                struct omap_dss_device *dssdev)
 {
        struct device_attribute *attr;
-       int i;
-       int r;
+       int i, r;
+       const char *def_disp_name = dss_get_default_display_name();
+       bool force;
+
+       force = def_disp_name && strcmp(def_disp_name, dssdev->name) == 0;
+       dss_init_connections(dssdev, force);
 
        /* create device sysfs files */
        i = 0;
        while ((attr = display_sysfs_attrs[i++]) != NULL) {
                r = device_create_file(&dssdev->dev, attr);
-               if (r)
+               if (r) {
+                       for (i = i - 2; i >= 0; i--) {
+                               attr = display_sysfs_attrs[i];
+                               device_remove_file(&dssdev->dev, attr);
+                       }
+
+                       dss_uninit_connections(dssdev);
+
                        DSSERR("failed to create sysfs file\n");
+                       return r;
+               }
        }
 
        /* create display? sysfs links */
        r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
                        dev_name(&dssdev->dev));
-       if (r)
+       if (r) {
+               while ((attr = display_sysfs_attrs[i++]) != NULL)
+                       device_remove_file(&dssdev->dev, attr);
+
+               dss_uninit_connections(dssdev);
+
                DSSERR("failed to create sysfs display link\n");
+               return r;
+       }
+
+       return 0;
 }
 
 void dss_uninit_device(struct platform_device *pdev,
@@ -349,8 +444,7 @@ void dss_uninit_device(struct platform_device *pdev,
        while ((attr = display_sysfs_attrs[i++]) != NULL)
                device_remove_file(&dssdev->dev, attr);
 
-       if (dssdev->manager)
-               dssdev->manager->unset_device(dssdev->manager);
+       dss_uninit_connections(dssdev);
 }
 
 static int dss_suspend_device(struct device *dev, void *data)
index 3266be23fc0dbd529e4e1b457c37462a3faef442..56748cf8760e52cce7d51245fb2f4dc1808e98c8 100644 (file)
 #include <linux/errno.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
+#include <linux/string.h>
 
 #include <video/omapdss.h>
-#include <plat/cpu.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 static struct {
        struct regulator *vdds_dsi_reg;
        struct platform_device *dsidev;
 
+       struct mutex lock;
+
+       struct omap_video_timings timings;
        struct dss_lcd_mgr_config mgr_config;
+       int data_lines;
+
+       struct omap_dss_output output;
 } dpi;
 
 static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
@@ -121,7 +128,8 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,
 
 static int dpi_set_mode(struct omap_dss_device *dssdev)
 {
-       struct omap_video_timings *t = &dssdev->panel.timings;
+       struct omap_video_timings *t = &dpi.timings;
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
        int lck_div = 0, pck_div = 0;
        unsigned long fck = 0;
        unsigned long pck;
@@ -146,37 +154,44 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
                t->pixel_clock = pck;
        }
 
-       dss_mgr_set_timings(dssdev->manager, t);
+       dss_mgr_set_timings(mgr, t);
 
        return 0;
 }
 
 static void dpi_config_lcd_manager(struct omap_dss_device *dssdev)
 {
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
+
        dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
 
        dpi.mgr_config.stallmode = false;
        dpi.mgr_config.fifohandcheck = false;
 
-       dpi.mgr_config.video_port_width = dssdev->phy.dpi.data_lines;
+       dpi.mgr_config.video_port_width = dpi.data_lines;
 
        dpi.mgr_config.lcden_sig_polarity = 0;
 
-       dss_mgr_set_lcd_config(dssdev->manager, &dpi.mgr_config);
+       dss_mgr_set_lcd_config(mgr, &dpi.mgr_config);
 }
 
 int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 {
+       struct omap_dss_output *out = dssdev->output;
        int r;
 
-       if (cpu_is_omap34xx() && !dpi.vdds_dsi_reg) {
+       mutex_lock(&dpi.lock);
+
+       if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi.vdds_dsi_reg) {
                DSSERR("no VDSS_DSI regulator\n");
-               return -ENODEV;
+               r = -ENODEV;
+               goto err_no_reg;
        }
 
-       if (dssdev->manager == NULL) {
-               DSSERR("failed to enable display: no manager\n");
-               return -ENODEV;
+       if (out == NULL || out->manager == NULL) {
+               DSSERR("failed to enable display: no output/manager\n");
+               r = -ENODEV;
+               goto err_no_out_mgr;
        }
 
        r = omap_dss_start_device(dssdev);
@@ -185,7 +200,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
                goto err_start_dev;
        }
 
-       if (cpu_is_omap34xx()) {
+       if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
                r = regulator_enable(dpi.vdds_dsi_reg);
                if (r)
                        goto err_reg_enable;
@@ -195,6 +210,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
        if (r)
                goto err_get_dispc;
 
+       r = dss_dpi_select_source(dssdev->channel);
+       if (r)
+               goto err_src_sel;
+
        if (dpi_use_dsi_pll(dssdev)) {
                r = dsi_runtime_get(dpi.dsidev);
                if (r)
@@ -213,10 +232,12 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 
        mdelay(2);
 
-       r = dss_mgr_enable(dssdev->manager);
+       r = dss_mgr_enable(out->manager);
        if (r)
                goto err_mgr_enable;
 
+       mutex_unlock(&dpi.lock);
+
        return 0;
 
 err_mgr_enable:
@@ -227,20 +248,28 @@ err_dsi_pll_init:
        if (dpi_use_dsi_pll(dssdev))
                dsi_runtime_put(dpi.dsidev);
 err_get_dsi:
+err_src_sel:
        dispc_runtime_put();
 err_get_dispc:
-       if (cpu_is_omap34xx())
+       if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
                regulator_disable(dpi.vdds_dsi_reg);
 err_reg_enable:
        omap_dss_stop_device(dssdev);
 err_start_dev:
+err_no_out_mgr:
+err_no_reg:
+       mutex_unlock(&dpi.lock);
        return r;
 }
 EXPORT_SYMBOL(omapdss_dpi_display_enable);
 
 void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 {
-       dss_mgr_disable(dssdev->manager);
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
+
+       mutex_lock(&dpi.lock);
+
+       dss_mgr_disable(mgr);
 
        if (dpi_use_dsi_pll(dssdev)) {
                dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
@@ -250,44 +279,39 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 
        dispc_runtime_put();
 
-       if (cpu_is_omap34xx())
+       if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
                regulator_disable(dpi.vdds_dsi_reg);
 
        omap_dss_stop_device(dssdev);
+
+       mutex_unlock(&dpi.lock);
 }
 EXPORT_SYMBOL(omapdss_dpi_display_disable);
 
-void dpi_set_timings(struct omap_dss_device *dssdev,
-                       struct omap_video_timings *timings)
+void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
 {
-       int r;
-
        DSSDBG("dpi_set_timings\n");
-       dssdev->panel.timings = *timings;
-       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
-               r = dispc_runtime_get();
-               if (r)
-                       return;
 
-               dpi_set_mode(dssdev);
+       mutex_lock(&dpi.lock);
 
-               dispc_runtime_put();
-       } else {
-               dss_mgr_set_timings(dssdev->manager, timings);
-       }
+       dpi.timings = *timings;
+
+       mutex_unlock(&dpi.lock);
 }
-EXPORT_SYMBOL(dpi_set_timings);
+EXPORT_SYMBOL(omapdss_dpi_set_timings);
 
 int dpi_check_timings(struct omap_dss_device *dssdev,
                        struct omap_video_timings *timings)
 {
        int r;
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
        int lck_div, pck_div;
        unsigned long fck;
        unsigned long pck;
        struct dispc_clock_info dispc_cinfo;
 
-       if (dss_mgr_check_timings(dssdev->manager, timings))
+       if (dss_mgr_check_timings(mgr, timings))
                return -EINVAL;
 
        if (timings->pixel_clock == 0)
@@ -325,11 +349,22 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
 }
 EXPORT_SYMBOL(dpi_check_timings);
 
+void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
+{
+       mutex_lock(&dpi.lock);
+
+       dpi.data_lines = data_lines;
+
+       mutex_unlock(&dpi.lock);
+}
+EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
+
 static int __init dpi_init_display(struct omap_dss_device *dssdev)
 {
        DSSDBG("init_display\n");
 
-       if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) {
+       if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
+                                       dpi.vdds_dsi_reg == NULL) {
                struct regulator *vdds_dsi;
 
                vdds_dsi = dss_get_vdds_dsi();
@@ -351,10 +386,14 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
        return 0;
 }
 
-static void __init dpi_probe_pdata(struct platform_device *pdev)
+static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
 {
        struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-       int i, r;
+       const char *def_disp_name = dss_get_default_display_name();
+       struct omap_dss_device *def_dssdev;
+       int i;
+
+       def_dssdev = NULL;
 
        for (i = 0; i < pdata->num_devices; ++i) {
                struct omap_dss_device *dssdev = pdata->devices[i];
@@ -362,21 +401,75 @@ static void __init dpi_probe_pdata(struct platform_device *pdev)
                if (dssdev->type != OMAP_DISPLAY_TYPE_DPI)
                        continue;
 
-               r = dpi_init_display(dssdev);
-               if (r) {
-                       DSSERR("device %s init failed: %d\n", dssdev->name, r);
-                       continue;
+               if (def_dssdev == NULL)
+                       def_dssdev = dssdev;
+
+               if (def_disp_name != NULL &&
+                               strcmp(dssdev->name, def_disp_name) == 0) {
+                       def_dssdev = dssdev;
+                       break;
                }
+       }
 
-               r = omap_dss_register_device(dssdev, &pdev->dev, i);
-               if (r)
-                       DSSERR("device %s register failed: %d\n",
-                                       dssdev->name, r);
+       return def_dssdev;
+}
+
+static void __init dpi_probe_pdata(struct platform_device *dpidev)
+{
+       struct omap_dss_device *plat_dssdev;
+       struct omap_dss_device *dssdev;
+       int r;
+
+       plat_dssdev = dpi_find_dssdev(dpidev);
+
+       if (!plat_dssdev)
+               return;
+
+       dssdev = dss_alloc_and_init_device(&dpidev->dev);
+       if (!dssdev)
+               return;
+
+       dss_copy_device_pdata(dssdev, plat_dssdev);
+
+       r = dpi_init_display(dssdev);
+       if (r) {
+               DSSERR("device %s init failed: %d\n", dssdev->name, r);
+               dss_put_device(dssdev);
+               return;
+       }
+
+       r = dss_add_device(dssdev);
+       if (r) {
+               DSSERR("device %s register failed: %d\n", dssdev->name, r);
+               dss_put_device(dssdev);
+               return;
        }
 }
 
+static void __init dpi_init_output(struct platform_device *pdev)
+{
+       struct omap_dss_output *out = &dpi.output;
+
+       out->pdev = pdev;
+       out->id = OMAP_DSS_OUTPUT_DPI;
+       out->type = OMAP_DISPLAY_TYPE_DPI;
+
+       dss_register_output(out);
+}
+
+static void __exit dpi_uninit_output(struct platform_device *pdev)
+{
+       struct omap_dss_output *out = &dpi.output;
+
+       dss_unregister_output(out);
+}
+
 static int __init omap_dpi_probe(struct platform_device *pdev)
 {
+       mutex_init(&dpi.lock);
+
+       dpi_init_output(pdev);
+
        dpi_probe_pdata(pdev);
 
        return 0;
@@ -384,7 +477,9 @@ static int __init omap_dpi_probe(struct platform_device *pdev)
 
 static int __exit omap_dpi_remove(struct platform_device *pdev)
 {
-       omap_dss_unregister_child_devices(&pdev->dev);
+       dss_unregister_child_devices(&pdev->dev);
+
+       dpi_uninit_output(pdev);
 
        return 0;
 }
index 05ee04667af1bdca019c8d4be15b78ce3d421b0f..d64ac3842884f4e9eac994dd03fdc311646d27b9 100644 (file)
@@ -41,7 +41,6 @@
 
 #include <video/omapdss.h>
 #include <video/mipi_display.h>
-#include <plat/clock.h>
 
 #include "dss.h"
 #include "dss_features.h"
@@ -333,6 +332,12 @@ struct dsi_data {
        unsigned scp_clk_refcount;
 
        struct dss_lcd_mgr_config mgr_config;
+       struct omap_video_timings timings;
+       enum omap_dss_dsi_pixel_format pix_fmt;
+       enum omap_dss_dsi_mode mode;
+       struct omap_dss_dsi_videomode_timings vm_timings;
+
+       struct omap_dss_output output;
 };
 
 struct dsi_packet_sent_handler_data {
@@ -340,8 +345,6 @@ struct dsi_packet_sent_handler_data {
        struct completion *completion;
 };
 
-static struct platform_device *dsi_pdev_map[MAX_NUM_DSI];
-
 #ifdef DEBUG
 static bool dsi_perf;
 module_param(dsi_perf, bool, 0644);
@@ -354,12 +357,19 @@ static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dside
 
 static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev)
 {
-       return dsi_pdev_map[dssdev->phy.dsi.module];
+       return dssdev->output->pdev;
 }
 
 struct platform_device *dsi_get_dsidev_from_id(int module)
 {
-       return dsi_pdev_map[module];
+       struct omap_dss_output *out;
+       enum omap_dss_output_id id;
+
+       id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
+
+       out = omap_dss_get_output(id);
+
+       return out->pdev;
 }
 
 static inline void dsi_write_reg(struct platform_device *dsidev,
@@ -1450,6 +1460,148 @@ found:
        return 0;
 }
 
+static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
+               unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo)
+{
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct dsi_clock_info cur, best;
+
+       DSSDBG("dsi_pll_calc_ddrfreq\n");
+
+       memset(&best, 0, sizeof(best));
+       memset(&cur, 0, sizeof(cur));
+
+       cur.clkin = clk_get_rate(dsi->sys_clk);
+
+       for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
+               cur.fint = cur.clkin / cur.regn;
+
+               if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
+                       continue;
+
+               /* DSIPHY(MHz) = (2 * regm / regn) * clkin */
+               for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
+                       unsigned long a, b;
+
+                       a = 2 * cur.regm * (cur.clkin/1000);
+                       b = cur.regn;
+                       cur.clkin4ddr = a / b * 1000;
+
+                       if (cur.clkin4ddr > 1800 * 1000 * 1000)
+                               break;
+
+                       if (abs(cur.clkin4ddr - req_clkin4ddr) <
+                                       abs(best.clkin4ddr - req_clkin4ddr)) {
+                               best = cur;
+                               DSSDBG("best %ld\n", best.clkin4ddr);
+                       }
+
+                       if (cur.clkin4ddr == req_clkin4ddr)
+                               goto found;
+               }
+       }
+found:
+       if (cinfo)
+               *cinfo = best;
+
+       return 0;
+}
+
+static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev,
+               struct dsi_clock_info *cinfo)
+{
+       unsigned long max_dsi_fck;
+
+       max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);
+
+       cinfo->regm_dsi = DIV_ROUND_UP(cinfo->clkin4ddr, max_dsi_fck);
+       cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
+}
+
+static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev,
+               unsigned long req_pck, struct dsi_clock_info *cinfo,
+               struct dispc_clock_info *dispc_cinfo)
+{
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       unsigned regm_dispc, best_regm_dispc;
+       unsigned long dispc_clk, best_dispc_clk;
+       int min_fck_per_pck;
+       unsigned long max_dss_fck;
+       struct dispc_clock_info best_dispc;
+       bool match;
+
+       max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
+       min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
+
+       if (min_fck_per_pck &&
+                       req_pck * min_fck_per_pck > max_dss_fck) {
+               DSSERR("Requested pixel clock not possible with the current "
+                               "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
+                               "the constraint off.\n");
+               min_fck_per_pck = 0;
+       }
+
+retry:
+       best_regm_dispc = 0;
+       best_dispc_clk = 0;
+       memset(&best_dispc, 0, sizeof(best_dispc));
+       match = false;
+
+       for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) {
+               struct dispc_clock_info cur_dispc;
+
+               dispc_clk = cinfo->clkin4ddr / regm_dispc;
+
+               /* this will narrow down the search a bit,
+                * but still give pixclocks below what was
+                * requested */
+               if (dispc_clk  < req_pck)
+                       break;
+
+               if (dispc_clk > max_dss_fck)
+                       continue;
+
+               if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck)
+                       continue;
+
+               match = true;
+
+               dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc);
+
+               if (abs(cur_dispc.pck - req_pck) <
+                               abs(best_dispc.pck - req_pck)) {
+                       best_regm_dispc = regm_dispc;
+                       best_dispc_clk = dispc_clk;
+                       best_dispc = cur_dispc;
+
+                       if (cur_dispc.pck == req_pck)
+                               goto found;
+               }
+       }
+
+       if (!match) {
+               if (min_fck_per_pck) {
+                       DSSERR("Could not find suitable clock settings.\n"
+                                       "Turning FCK/PCK constraint off and"
+                                       "trying again.\n");
+                       min_fck_per_pck = 0;
+                       goto retry;
+               }
+
+               DSSERR("Could not find suitable clock settings.\n");
+
+               return -EINVAL;
+       }
+found:
+       cinfo->regm_dispc = best_regm_dispc;
+       cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk;
+
+       *dispc_cinfo = best_dispc;
+
+       return 0;
+}
+
 int dsi_pll_set_clock_div(struct platform_device *dsidev,
                struct dsi_clock_info *cinfo)
 {
@@ -1526,21 +1678,27 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
 
        BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max);
 
+       l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
+
        if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {
                f = cinfo->fint < 1000000 ? 0x3 :
                        cinfo->fint < 1250000 ? 0x4 :
                        cinfo->fint < 1500000 ? 0x5 :
                        cinfo->fint < 1750000 ? 0x6 :
                        0x7;
-       }
 
-       l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
-
-       if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))
                l = FLD_MOD(l, f, 4, 1);        /* DSI_PLL_FREQSEL */
+       } else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) {
+               f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4;
+
+               l = FLD_MOD(l, f, 4, 1);        /* PLL_SELFREQDCO */
+       }
+
        l = FLD_MOD(l, 1, 13, 13);              /* DSI_PLL_REFEN */
        l = FLD_MOD(l, 0, 14, 14);              /* DSIPHY_CLKINEN */
        l = FLD_MOD(l, 1, 20, 20);              /* DSI_HSDIVBYPASS */
+       if (dss_has_feature(FEAT_DSI_PLL_REFSEL))
+               l = FLD_MOD(l, 3, 22, 21);      /* REF_SYSCLK = sysclk */
        dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
 
        REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0);       /* DSI_PLL_GO */
@@ -2004,15 +2162,16 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
                return 1194 * 3;        /* 1194x24 bits */
        case 6:
                return 1365 * 3;        /* 1365x24 bits */
+       case 7:
+               return 1920 * 3;        /* 1920x24 bits */
        default:
                BUG();
                return 0;
        }
 }
 
-static int dsi_set_lane_config(struct omap_dss_device *dssdev)
+static int dsi_set_lane_config(struct platform_device *dsidev)
 {
-       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        static const u8 offsets[] = { 0, 4, 8, 12, 16 };
        static const enum dsi_lane_function functions[] = {
@@ -2136,9 +2295,16 @@ static void dsi_cio_timings(struct platform_device *dsidev)
        dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r);
 
        r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
-       r = FLD_MOD(r, tlpx_half, 22, 16);
+       r = FLD_MOD(r, tlpx_half, 20, 16);
        r = FLD_MOD(r, tclk_trail, 15, 8);
        r = FLD_MOD(r, tclk_zero, 7, 0);
+
+       if (dss_has_feature(FEAT_DSI_PHY_DCC)) {
+               r = FLD_MOD(r, 0, 21, 21);      /* DCCEN = disable */
+               r = FLD_MOD(r, 1, 22, 22);      /* CLKINP_DIVBY2EN = enable */
+               r = FLD_MOD(r, 1, 23, 23);      /* CLKINP_SEL = enable */
+       }
+
        dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r);
 
        r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2);
@@ -2147,10 +2313,9 @@ static void dsi_cio_timings(struct platform_device *dsidev)
 }
 
 /* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */
-static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev,
+static void dsi_cio_enable_lane_override(struct platform_device *dsidev,
                unsigned mask_p, unsigned mask_n)
 {
-       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        int i;
        u32 l;
@@ -2197,9 +2362,8 @@ static void dsi_cio_disable_lane_override(struct platform_device *dsidev)
        REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17);
 }
 
-static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
+static int dsi_cio_wait_tx_clk_esc_reset(struct platform_device *dsidev)
 {
-       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        int t, i;
        bool in_use[DSI_MAX_NR_LANES];
@@ -2247,9 +2411,8 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
 }
 
 /* return bitmask of enabled lanes, lane0 being the lsb */
-static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev)
+static unsigned dsi_get_lane_mask(struct platform_device *dsidev)
 {
-       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        unsigned mask = 0;
        int i;
@@ -2262,16 +2425,15 @@ static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev)
        return mask;
 }
 
-static int dsi_cio_init(struct omap_dss_device *dssdev)
+static int dsi_cio_init(struct platform_device *dsidev)
 {
-       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        int r;
        u32 l;
 
        DSSDBGF();
 
-       r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dssdev));
+       r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
        if (r)
                return r;
 
@@ -2288,7 +2450,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
                goto err_scp_clk_dom;
        }
 
-       r = dsi_set_lane_config(dssdev);
+       r = dsi_set_lane_config(dsidev);
        if (r)
                goto err_scp_clk_dom;
 
@@ -2323,7 +2485,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
                        mask_p |= 1 << i;
                }
 
-               dsi_cio_enable_lane_override(dssdev, mask_p, 0);
+               dsi_cio_enable_lane_override(dsidev, mask_p, 0);
        }
 
        r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON);
@@ -2340,7 +2502,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
        dsi_if_enable(dsidev, false);
        REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
 
-       r = dsi_cio_wait_tx_clk_esc_reset(dssdev);
+       r = dsi_cio_wait_tx_clk_esc_reset(dsidev);
        if (r)
                goto err_tx_clk_esc_rst;
 
@@ -2360,10 +2522,10 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
 
        dsi_cio_timings(dsidev);
 
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+       if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
                /* DDR_CLK_ALWAYS_ON */
                REG_FLD_MOD(dsidev, DSI_CLK_CTRL,
-                       dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13);
+                       dsi->vm_timings.ddr_clk_always_on, 13, 13);
        }
 
        dsi->ulps_enabled = false;
@@ -2381,13 +2543,12 @@ err_cio_pwr:
                dsi_cio_disable_lane_override(dsidev);
 err_scp_clk_dom:
        dsi_disable_scp_clk(dsidev);
-       dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev));
+       dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
        return r;
 }
 
-static void dsi_cio_uninit(struct omap_dss_device *dssdev)
+static void dsi_cio_uninit(struct platform_device *dsidev)
 {
-       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
        /* DDR_CLK_ALWAYS_ON */
@@ -2395,7 +2556,7 @@ static void dsi_cio_uninit(struct omap_dss_device *dssdev)
 
        dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
        dsi_disable_scp_clk(dsidev);
-       dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev));
+       dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
 }
 
 static void dsi_config_tx_fifo(struct platform_device *dsidev,
@@ -2685,6 +2846,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
                bool enable)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
        DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
 
@@ -2701,7 +2863,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
        dsi_force_tx_stop_mode_io(dsidev);
 
        /* start the DDR clock by sending a NULL packet */
-       if (dssdev->panel.dsi_vm_data.ddr_clk_always_on && enable)
+       if (dsi->vm_timings.ddr_clk_always_on && enable)
                dsi_vc_send_null(dssdev, channel);
 }
 EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs);
@@ -2987,10 +3149,9 @@ int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)
 }
 EXPORT_SYMBOL(dsi_vc_send_null);
 
-static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev,
+static int dsi_vc_write_nosync_common(struct platform_device *dsidev,
                int channel, u8 *data, int len, enum dss_dsi_content_type type)
 {
-       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        int r;
 
        if (len == 0) {
@@ -3021,7 +3182,9 @@ static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev,
 int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
                u8 *data, int len)
 {
-       return dsi_vc_write_nosync_common(dssdev, channel, data, len,
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+
+       return dsi_vc_write_nosync_common(dsidev, channel, data, len,
                        DSS_DSI_CONTENT_DCS);
 }
 EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
@@ -3029,7 +3192,9 @@ EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
 int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,
                u8 *data, int len)
 {
-       return dsi_vc_write_nosync_common(dssdev, channel, data, len,
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+
+       return dsi_vc_write_nosync_common(dsidev, channel, data, len,
                        DSS_DSI_CONTENT_GENERIC);
 }
 EXPORT_SYMBOL(dsi_vc_generic_write_nosync);
@@ -3040,7 +3205,7 @@ static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel,
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        int r;
 
-       r = dsi_vc_write_nosync_common(dssdev, channel, data, len, type);
+       r = dsi_vc_write_nosync_common(dsidev, channel, data, len, type);
        if (r)
                goto err;
 
@@ -3118,10 +3283,9 @@ int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel,
 }
 EXPORT_SYMBOL(dsi_vc_generic_write_2);
 
-static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev,
+static int dsi_vc_dcs_send_read_request(struct platform_device *dsidev,
                int channel, u8 dcs_cmd)
 {
-       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        int r;
 
@@ -3139,10 +3303,9 @@ static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev,
        return 0;
 }
 
-static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev,
+static int dsi_vc_generic_send_read_request(struct platform_device *dsidev,
                int channel, u8 *reqdata, int reqlen)
 {
-       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        u16 data;
        u8 data_type;
@@ -3291,7 +3454,7 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        int r;
 
-       r = dsi_vc_dcs_send_read_request(dssdev, channel, dcs_cmd);
+       r = dsi_vc_dcs_send_read_request(dsidev, channel, dcs_cmd);
        if (r)
                goto err;
 
@@ -3322,7 +3485,7 @@ static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel,
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        int r;
 
-       r = dsi_vc_generic_send_read_request(dssdev, channel, reqdata, reqlen);
+       r = dsi_vc_generic_send_read_request(dsidev, channel, reqdata, reqlen);
        if (r)
                return r;
 
@@ -3604,15 +3767,15 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,
                        (total_ticks * 1000) / (fck / 1000 / 1000));
 }
 
-static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev)
+static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
 {
-       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        int num_line_buffers;
 
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
-               int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+       if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
+               int bpp = dsi_get_pixel_size(dsi->pix_fmt);
                unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
-               struct omap_video_timings *timings = &dssdev->panel.timings;
+               struct omap_video_timings *timings = &dsi->timings;
                /*
                 * Don't use line buffers if width is greater than the video
                 * port's line buffer size
@@ -3630,11 +3793,11 @@ static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev)
        REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12);
 }
 
-static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev)
+static void dsi_config_vp_sync_events(struct platform_device *dsidev)
 {
-       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-       bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end;
-       bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end;
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       bool vsync_end = dsi->vm_timings.vp_vsync_end;
+       bool hsync_end = dsi->vm_timings.vp_hsync_end;
        u32 r;
 
        r = dsi_read_reg(dsidev, DSI_CTRL);
@@ -3648,13 +3811,13 @@ static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev)
        dsi_write_reg(dsidev, DSI_CTRL, r);
 }
 
-static void dsi_config_blanking_modes(struct omap_dss_device *dssdev)
+static void dsi_config_blanking_modes(struct platform_device *dsidev)
 {
-       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-       int blanking_mode = dssdev->panel.dsi_vm_data.blanking_mode;
-       int hfp_blanking_mode = dssdev->panel.dsi_vm_data.hfp_blanking_mode;
-       int hbp_blanking_mode = dssdev->panel.dsi_vm_data.hbp_blanking_mode;
-       int hsa_blanking_mode = dssdev->panel.dsi_vm_data.hsa_blanking_mode;
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       int blanking_mode = dsi->vm_timings.blanking_mode;
+       int hfp_blanking_mode = dsi->vm_timings.hfp_blanking_mode;
+       int hbp_blanking_mode = dsi->vm_timings.hbp_blanking_mode;
+       int hsa_blanking_mode = dsi->vm_timings.hsa_blanking_mode;
        u32 r;
 
        /*
@@ -3741,8 +3904,8 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
        int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
        int tclk_trail, ths_exit, exiths_clk;
        bool ddr_alwon;
-       struct omap_video_timings *timings = &dssdev->panel.timings;
-       int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+       struct omap_video_timings *timings = &dsi->timings;
+       int bpp = dsi_get_pixel_size(dsi->pix_fmt);
        int ndl = dsi->num_lanes_used - 1;
        int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1;
        int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
@@ -3852,6 +4015,7 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
 static int dsi_proto_config(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        u32 r;
        int buswidth = 0;
 
@@ -3871,7 +4035,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
        dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);
        dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true);
 
-       switch (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)) {
+       switch (dsi_get_pixel_size(dsi->pix_fmt)) {
        case 16:
                buswidth = 0;
                break;
@@ -3903,11 +4067,11 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
 
        dsi_write_reg(dsidev, DSI_CTRL, r);
 
-       dsi_config_vp_num_line_buffers(dssdev);
+       dsi_config_vp_num_line_buffers(dsidev);
 
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
-               dsi_config_vp_sync_events(dssdev);
-               dsi_config_blanking_modes(dssdev);
+       if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
+               dsi_config_vp_sync_events(dsidev);
+               dsi_config_blanking_modes(dsidev);
                dsi_config_cmd_mode_interleaving(dssdev);
        }
 
@@ -3919,9 +4083,8 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
        return 0;
 }
 
-static void dsi_proto_timings(struct omap_dss_device *dssdev)
+static void dsi_proto_timings(struct platform_device *dsidev)
 {
-       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
        unsigned tclk_pre, tclk_post;
@@ -3941,7 +4104,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
        ths_exit = FLD_GET(r, 7, 0);
 
        r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
-       tlpx = FLD_GET(r, 22, 16) * 2;
+       tlpx = FLD_GET(r, 20, 16) * 2;
        tclk_trail = FLD_GET(r, 15, 8);
        tclk_zero = FLD_GET(r, 7, 0);
 
@@ -3984,18 +4147,18 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
        DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
                        enter_hs_mode_lat, exit_hs_mode_lat);
 
-        if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+        if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
                /* TODO: Implement a video mode check_timings function */
-               int hsa = dssdev->panel.dsi_vm_data.hsa;
-               int hfp = dssdev->panel.dsi_vm_data.hfp;
-               int hbp = dssdev->panel.dsi_vm_data.hbp;
-               int vsa = dssdev->panel.dsi_vm_data.vsa;
-               int vfp = dssdev->panel.dsi_vm_data.vfp;
-               int vbp = dssdev->panel.dsi_vm_data.vbp;
-               int window_sync = dssdev->panel.dsi_vm_data.window_sync;
-               bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end;
-               struct omap_video_timings *timings = &dssdev->panel.timings;
-               int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+               int hsa = dsi->vm_timings.hsa;
+               int hfp = dsi->vm_timings.hfp;
+               int hbp = dsi->vm_timings.hbp;
+               int vsa = dsi->vm_timings.vsa;
+               int vfp = dsi->vm_timings.vfp;
+               int vbp = dsi->vm_timings.vbp;
+               int window_sync = dsi->vm_timings.window_sync;
+               bool hsync_end = dsi->vm_timings.vp_hsync_end;
+               struct omap_video_timings *timings = &dsi->timings;
+               int bpp = dsi_get_pixel_size(dsi->pix_fmt);
                int tl, t_he, width_bytes;
 
                t_he = hsync_end ?
@@ -4100,16 +4263,84 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
 }
 EXPORT_SYMBOL(omapdss_dsi_configure_pins);
 
-int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
+int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
+               unsigned long ddr_clk, unsigned long lp_clk)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct dsi_clock_info cinfo;
+       struct dispc_clock_info dispc_cinfo;
+       unsigned lp_clk_div;
+       unsigned long dsi_fclk;
        int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+       unsigned long pck;
+       int r;
+
+       DSSDBGF("ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
+
+       mutex_lock(&dsi->lock);
+
+       /* Calculate PLL output clock */
+       r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo);
+       if (r)
+               goto err;
+
+       /* Calculate PLL's DSI clock */
+       dsi_pll_calc_dsi_fck(dsidev, &cinfo);
+
+       /* Calculate PLL's DISPC clock and pck & lck divs */
+       pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
+       DSSDBG("finding dispc dividers for pck %lu\n", pck);
+       r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo);
+       if (r)
+               goto err;
+
+       /* Calculate LP clock */
+       dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk;
+       lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2);
+
+       dssdev->clocks.dsi.regn = cinfo.regn;
+       dssdev->clocks.dsi.regm = cinfo.regm;
+       dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc;
+       dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi;
+
+       dssdev->clocks.dsi.lp_clk_div = lp_clk_div;
+
+       dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div;
+       dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div;
+
+       dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK;
+
+       dssdev->clocks.dispc.channel.lcd_clk_src =
+               dsi->module_id == 0 ?
+               OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
+               OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
+
+       dssdev->clocks.dsi.dsi_fclk_src =
+               dsi->module_id == 0 ?
+               OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
+               OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI;
+
+       mutex_unlock(&dsi->lock);
+       return 0;
+err:
+       mutex_unlock(&dsi->lock);
+       return r;
+}
+EXPORT_SYMBOL(omapdss_dsi_set_clocks);
+
+int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
+       int bpp = dsi_get_pixel_size(dsi->pix_fmt);
        u8 data_type;
        u16 word_count;
        int r;
 
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
-               switch (dssdev->panel.dsi_pix_fmt) {
+       if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
+               switch (dsi->pix_fmt) {
                case OMAP_DSS_DSI_FMT_RGB888:
                        data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
                        break;
@@ -4133,7 +4364,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
                /* MODE, 1 = video mode */
                REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
 
-               word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8);
+               word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8);
 
                dsi_vc_write_long_header(dsidev, channel, data_type,
                                word_count, 0);
@@ -4142,9 +4373,9 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
                dsi_if_enable(dsidev, true);
        }
 
-       r = dss_mgr_enable(dssdev->manager);
+       r = dss_mgr_enable(mgr);
        if (r) {
-               if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+               if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
                        dsi_if_enable(dsidev, false);
                        dsi_vc_enable(dsidev, channel, false);
                }
@@ -4159,8 +4390,10 @@ EXPORT_SYMBOL(dsi_enable_video_output);
 void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
 
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+       if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
                dsi_if_enable(dsidev, false);
                dsi_vc_enable(dsidev, channel, false);
 
@@ -4171,15 +4404,15 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
                dsi_if_enable(dsidev, true);
        }
 
-       dss_mgr_disable(dssdev->manager);
+       dss_mgr_disable(mgr);
 }
 EXPORT_SYMBOL(dsi_disable_video_output);
 
-static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
-               u16 w, u16 h)
+static void dsi_update_screen_dispc(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
        unsigned bytespp;
        unsigned bytespl;
        unsigned bytespf;
@@ -4190,12 +4423,14 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
        int r;
        const unsigned channel = dsi->update_channel;
        const unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
+       u16 w = dsi->timings.x_res;
+       u16 h = dsi->timings.y_res;
 
        DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);
 
        dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP);
 
-       bytespp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
+       bytespp = dsi_get_pixel_size(dsi->pix_fmt) / 8;
        bytespl = w * bytespp;
        bytespf = bytespl * h;
 
@@ -4239,7 +4474,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
                msecs_to_jiffies(250));
        BUG_ON(r == 0);
 
-       dss_mgr_start_update(dssdev->manager);
+       dss_mgr_set_timings(mgr, &dsi->timings);
+
+       dss_mgr_start_update(mgr);
 
        if (dsi->te_enabled) {
                /* disable LP_RX_TO, so that we can receive TE.  Time to wait
@@ -4297,8 +4534,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
 
 static void dsi_framedone_irq_callback(void *data, u32 mask)
 {
-       struct omap_dss_device *dssdev = (struct omap_dss_device *) data;
-       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct platform_device *dsidev = (struct platform_device *) data;
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
        /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
@@ -4325,13 +4561,14 @@ int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
        dsi->framedone_callback = callback;
        dsi->framedone_data = data;
 
-       dssdev->driver->get_resolution(dssdev, &dw, &dh);
+       dw = dsi->timings.x_res;
+       dh = dsi->timings.y_res;
 
 #ifdef DEBUG
        dsi->update_bytes = dw * dh *
-               dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
+               dsi_get_pixel_size(dsi->pix_fmt) / 8;
 #endif
-       dsi_update_screen_dispc(dssdev, dw, dh);
+       dsi_update_screen_dispc(dssdev);
 
        return 0;
 }
@@ -4367,28 +4604,22 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-       struct omap_video_timings timings;
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
        int r;
        u32 irq = 0;
 
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
-               u16 dw, dh;
-
-               dssdev->driver->get_resolution(dssdev, &dw, &dh);
-
-               timings.x_res = dw;
-               timings.y_res = dh;
-               timings.hsw = 1;
-               timings.hfp = 1;
-               timings.hbp = 1;
-               timings.vsw = 1;
-               timings.vfp = 0;
-               timings.vbp = 0;
+       if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
+               dsi->timings.hsw = 1;
+               dsi->timings.hfp = 1;
+               dsi->timings.hbp = 1;
+               dsi->timings.vsw = 1;
+               dsi->timings.vfp = 0;
+               dsi->timings.vbp = 0;
 
-               irq = dispc_mgr_get_framedone_irq(dssdev->manager->id);
+               irq = dispc_mgr_get_framedone_irq(mgr->id);
 
                r = omap_dispc_register_isr(dsi_framedone_irq_callback,
-                       (void *) dssdev, irq);
+                       (void *) dsidev, irq);
                if (r) {
                        DSSERR("can't get FRAMEDONE irq\n");
                        goto err;
@@ -4397,8 +4628,6 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
                dsi->mgr_config.stallmode = true;
                dsi->mgr_config.fifohandcheck = true;
        } else {
-               timings = dssdev->panel.timings;
-
                dsi->mgr_config.stallmode = false;
                dsi->mgr_config.fifohandcheck = false;
        }
@@ -4407,14 +4636,14 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
         * override interlace, logic level and edge related parameters in
         * omap_video_timings with default values
         */
-       timings.interlace = false;
-       timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
-       timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
-       timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-       timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
-       timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
+       dsi->timings.interlace = false;
+       dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+       dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
 
-       dss_mgr_set_timings(dssdev->manager, &timings);
+       dss_mgr_set_timings(mgr, &dsi->timings);
 
        r = dsi_configure_dispc_clocks(dssdev);
        if (r)
@@ -4422,29 +4651,33 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
 
        dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
        dsi->mgr_config.video_port_width =
-                       dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+                       dsi_get_pixel_size(dsi->pix_fmt);
        dsi->mgr_config.lcden_sig_polarity = 0;
 
-       dss_mgr_set_lcd_config(dssdev->manager, &dsi->mgr_config);
+       dss_mgr_set_lcd_config(mgr, &dsi->mgr_config);
 
        return 0;
 err1:
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE)
+       if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
                omap_dispc_unregister_isr(dsi_framedone_irq_callback,
-                       (void *) dssdev, irq);
+                       (void *) dsidev, irq);
 err:
        return r;
 }
 
 static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
 {
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
+
+       if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
                u32 irq;
 
-               irq = dispc_mgr_get_framedone_irq(dssdev->manager->id);
+               irq = dispc_mgr_get_framedone_irq(mgr->id);
 
                omap_dispc_unregister_isr(dsi_framedone_irq_callback,
-                       (void *) dssdev, irq);
+                       (void *) dsidev, irq);
        }
 }
 
@@ -4477,6 +4710,7 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
        int r;
 
        r = dsi_pll_init(dsidev, true, true);
@@ -4489,18 +4723,18 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
 
        dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
        dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src);
-       dss_select_lcd_clk_source(dssdev->manager->id,
+       dss_select_lcd_clk_source(mgr->id,
                        dssdev->clocks.dispc.channel.lcd_clk_src);
 
        DSSDBG("PLL OK\n");
 
-       r = dsi_cio_init(dssdev);
+       r = dsi_cio_init(dsidev);
        if (r)
                goto err2;
 
        _dsi_print_reset_status(dsidev);
 
-       dsi_proto_timings(dssdev);
+       dsi_proto_timings(dsidev);
        dsi_set_lp_clk_divisor(dssdev);
 
        if (1)
@@ -4520,11 +4754,11 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
 
        return 0;
 err3:
-       dsi_cio_uninit(dssdev);
+       dsi_cio_uninit(dsidev);
 err2:
        dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
        dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
-       dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);
+       dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
 
 err1:
        dsi_pll_uninit(dsidev, true);
@@ -4537,6 +4771,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
 
        if (enter_ulps && !dsi->ulps_enabled)
                dsi_enter_ulps(dsidev);
@@ -4550,8 +4785,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
 
        dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
        dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
-       dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);
-       dsi_cio_uninit(dssdev);
+       dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
+       dsi_cio_uninit(dsidev);
        dsi_pll_uninit(dsidev, disconnect_lanes);
 }
 
@@ -4559,6 +4794,7 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct omap_dss_output *out = dssdev->output;
        int r = 0;
 
        DSSDBG("dsi_display_enable\n");
@@ -4567,8 +4803,8 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
 
        mutex_lock(&dsi->lock);
 
-       if (dssdev->manager == NULL) {
-               DSSERR("failed to enable display: no manager\n");
+       if (out == NULL || out->manager == NULL) {
+               DSSERR("failed to enable display: no output/manager\n");
                r = -ENODEV;
                goto err_start_dev;
        }
@@ -4653,17 +4889,83 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
 }
 EXPORT_SYMBOL(omapdss_dsi_enable_te);
 
-static int __init dsi_init_display(struct omap_dss_device *dssdev)
+void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
-       DSSDBG("DSI init\n");
+       mutex_lock(&dsi->lock);
 
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
-               dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
-                       OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
-       }
+       dsi->timings = *timings;
+
+       mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_timings);
+
+void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+       mutex_lock(&dsi->lock);
+
+       dsi->timings.x_res = w;
+       dsi->timings.y_res = h;
+
+       mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_size);
+
+void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
+               enum omap_dss_dsi_pixel_format fmt)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+       mutex_lock(&dsi->lock);
+
+       dsi->pix_fmt = fmt;
+
+       mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_pixel_format);
+
+void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
+               enum omap_dss_dsi_mode mode)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+       mutex_lock(&dsi->lock);
+
+       dsi->mode = mode;
+
+       mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_operation_mode);
+
+void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
+               struct omap_dss_dsi_videomode_timings *timings)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+       mutex_lock(&dsi->lock);
+
+       dsi->vm_timings = *timings;
+
+       mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings);
+
+static int __init dsi_init_display(struct omap_dss_device *dssdev)
+{
+       struct platform_device *dsidev =
+                       dsi_get_dsidev_from_id(dssdev->phy.dsi.module);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+       DSSDBG("DSI init\n");
 
        if (dsi->vdds_dsi_reg == NULL) {
                struct regulator *vdds_dsi;
@@ -4806,11 +5108,15 @@ static void dsi_put_clocks(struct platform_device *dsidev)
                clk_put(dsi->sys_clk);
 }
 
-static void __init dsi_probe_pdata(struct platform_device *dsidev)
+static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *pdev)
 {
-       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-       struct omap_dss_board_info *pdata = dsidev->dev.platform_data;
-       int i, r;
+       struct omap_dss_board_info *pdata = pdev->dev.platform_data;
+       struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
+       const char *def_disp_name = dss_get_default_display_name();
+       struct omap_dss_device *def_dssdev;
+       int i;
+
+       def_dssdev = NULL;
 
        for (i = 0; i < pdata->num_devices; ++i) {
                struct omap_dss_device *dssdev = pdata->devices[i];
@@ -4821,19 +5127,73 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
                if (dssdev->phy.dsi.module != dsi->module_id)
                        continue;
 
-               r = dsi_init_display(dssdev);
-               if (r) {
-                       DSSERR("device %s init failed: %d\n", dssdev->name, r);
-                       continue;
+               if (def_dssdev == NULL)
+                       def_dssdev = dssdev;
+
+               if (def_disp_name != NULL &&
+                               strcmp(dssdev->name, def_disp_name) == 0) {
+                       def_dssdev = dssdev;
+                       break;
                }
+       }
 
-               r = omap_dss_register_device(dssdev, &dsidev->dev, i);
-               if (r)
-                       DSSERR("device %s register failed: %d\n",
-                                       dssdev->name, r);
+       return def_dssdev;
+}
+
+static void __init dsi_probe_pdata(struct platform_device *dsidev)
+{
+       struct omap_dss_device *plat_dssdev;
+       struct omap_dss_device *dssdev;
+       int r;
+
+       plat_dssdev = dsi_find_dssdev(dsidev);
+
+       if (!plat_dssdev)
+               return;
+
+       dssdev = dss_alloc_and_init_device(&dsidev->dev);
+       if (!dssdev)
+               return;
+
+       dss_copy_device_pdata(dssdev, plat_dssdev);
+
+       r = dsi_init_display(dssdev);
+       if (r) {
+               DSSERR("device %s init failed: %d\n", dssdev->name, r);
+               dss_put_device(dssdev);
+               return;
+       }
+
+       r = dss_add_device(dssdev);
+       if (r) {
+               DSSERR("device %s register failed: %d\n", dssdev->name, r);
+               dss_put_device(dssdev);
+               return;
        }
 }
 
+static void __init dsi_init_output(struct platform_device *dsidev)
+{
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct omap_dss_output *out = &dsi->output;
+
+       out->pdev = dsidev;
+       out->id = dsi->module_id == 0 ?
+                       OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
+
+       out->type = OMAP_DISPLAY_TYPE_DSI;
+
+       dss_register_output(out);
+}
+
+static void __exit dsi_uninit_output(struct platform_device *dsidev)
+{
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct omap_dss_output *out = &dsi->output;
+
+       dss_unregister_output(out);
+}
+
 /* DSI1 HW IP initialisation */
 static int __init omap_dsihw_probe(struct platform_device *dsidev)
 {
@@ -4848,7 +5208,6 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
 
        dsi->module_id = dsidev->id;
        dsi->pdev = dsidev;
-       dsi_pdev_map[dsi->module_id] = dsidev;
        dev_set_drvdata(&dsidev->dev, dsi);
 
        spin_lock_init(&dsi->irq_lock);
@@ -4928,6 +5287,8 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
        else
                dsi->num_lanes_supported = 3;
 
+       dsi_init_output(dsidev);
+
        dsi_probe_pdata(dsidev);
 
        dsi_runtime_put(dsidev);
@@ -4957,7 +5318,9 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
 
        WARN_ON(dsi->scp_clk_refcount > 0);
 
-       omap_dss_unregister_child_devices(&dsidev->dev);
+       dss_unregister_child_devices(&dsidev->dev);
+
+       dsi_uninit_output(dsidev);
 
        pm_runtime_disable(&dsidev->dev);
 
index 04b4586113e34928e1784e22c844da287d5750ed..2ab1c3e96553d81297ad5f942eed2cfb76a5064b 100644 (file)
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/gfp.h>
 
 #include <video/omapdss.h>
 
 #include <plat/cpu.h>
-#include <plat/clock.h>
 
 #include "dss.h"
 #include "dss_features.h"
@@ -65,6 +65,13 @@ struct dss_reg {
 static int dss_runtime_get(void);
 static void dss_runtime_put(void);
 
+struct dss_features {
+       u8 fck_div_max;
+       u8 dss_fck_multiplier;
+       const char *clk_name;
+       int (*dpi_select_source)(enum omap_channel channel);
+};
+
 static struct {
        struct platform_device *pdev;
        void __iomem    *base;
@@ -83,6 +90,8 @@ static struct {
 
        bool            ctx_valid;
        u32             ctx[DSS_SZ_REGS / sizeof(u32)];
+
+       const struct dss_features *feat;
 } dss;
 
 static const char * const dss_generic_clk_source_names[] = {
@@ -144,7 +153,7 @@ static void dss_restore_context(void)
 #undef SR
 #undef RR
 
-void dss_sdi_init(u8 datapairs)
+void dss_sdi_init(int datapairs)
 {
        u32 l;
 
@@ -236,7 +245,6 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
        return dss_generic_clk_source_names[clk_src];
 }
 
-
 void dss_dump_clocks(struct seq_file *s)
 {
        unsigned long dpll4_ck_rate;
@@ -259,18 +267,10 @@ void dss_dump_clocks(struct seq_file *s)
 
                seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
 
-               if (cpu_is_omap3630() || cpu_is_omap44xx())
-                       seq_printf(s, "%s (%s) = %lu / %lu  = %lu\n",
-                                       fclk_name, fclk_real_name,
-                                       dpll4_ck_rate,
-                                       dpll4_ck_rate / dpll4_m4_ck_rate,
-                                       fclk_rate);
-               else
-                       seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
-                                       fclk_name, fclk_real_name,
-                                       dpll4_ck_rate,
-                                       dpll4_ck_rate / dpll4_m4_ck_rate,
-                                       fclk_rate);
+               seq_printf(s, "%s (%s) = %lu / %lu * %d  = %lu\n",
+                               fclk_name, fclk_real_name, dpll4_ck_rate,
+                               dpll4_ck_rate / dpll4_m4_ck_rate,
+                               dss.feat->dss_fck_multiplier, fclk_rate);
        } else {
                seq_printf(s, "%s (%s) = %lu\n",
                                fclk_name, fclk_real_name,
@@ -431,31 +431,6 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
        }
 }
 
-/* calculate clock rates using dividers in cinfo */
-int dss_calc_clock_rates(struct dss_clock_info *cinfo)
-{
-       if (dss.dpll4_m4_ck) {
-               unsigned long prate;
-               u16 fck_div_max = 16;
-
-               if (cpu_is_omap3630() || cpu_is_omap44xx())
-                       fck_div_max = 32;
-
-               if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0)
-                       return -EINVAL;
-
-               prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
-
-               cinfo->fck = prate / cinfo->fck_div;
-       } else {
-               if (cinfo->fck_div != 0)
-                       return -EINVAL;
-               cinfo->fck = clk_get_rate(dss.dss_clk);
-       }
-
-       return 0;
-}
-
 int dss_set_clock_div(struct dss_clock_info *cinfo)
 {
        if (dss.dpll4_m4_ck) {
@@ -478,26 +453,6 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
        return 0;
 }
 
-int dss_get_clock_div(struct dss_clock_info *cinfo)
-{
-       cinfo->fck = clk_get_rate(dss.dss_clk);
-
-       if (dss.dpll4_m4_ck) {
-               unsigned long prate;
-
-               prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
-
-               if (cpu_is_omap3630() || cpu_is_omap44xx())
-                       cinfo->fck_div = prate / (cinfo->fck);
-               else
-                       cinfo->fck_div = prate / (cinfo->fck / 2);
-       } else {
-               cinfo->fck_div = 0;
-       }
-
-       return 0;
-}
-
 unsigned long dss_get_dpll4_rate(void)
 {
        if (dss.dpll4_m4_ck)
@@ -515,7 +470,7 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
 
        unsigned long fck, max_dss_fck;
 
-       u16 fck_div, fck_div_max = 16;
+       u16 fck_div;
 
        int match = 0;
        int min_fck_per_pck;
@@ -525,9 +480,8 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
        max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
 
        fck = clk_get_rate(dss.dss_clk);
-       if (req_pck == dss.cache_req_pck &&
-                       ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
-                        dss.cache_dss_cinfo.fck == fck)) {
+       if (req_pck == dss.cache_req_pck && prate == dss.cache_prate &&
+               dss.cache_dss_cinfo.fck == fck) {
                DSSDBG("dispc clock info found from cache.\n");
                *dss_cinfo = dss.cache_dss_cinfo;
                *dispc_cinfo = dss.cache_dispc_cinfo;
@@ -564,16 +518,10 @@ retry:
 
                goto found;
        } else {
-               if (cpu_is_omap3630() || cpu_is_omap44xx())
-                       fck_div_max = 32;
-
-               for (fck_div = fck_div_max; fck_div > 0; --fck_div) {
+               for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) {
                        struct dispc_clock_info cur_dispc;
 
-                       if (fck_div_max == 32)
-                               fck = prate / fck_div;
-                       else
-                               fck = prate / fck_div * 2;
+                       fck = prate / fck_div * dss.feat->dss_fck_multiplier;
 
                        if (fck > max_dss_fck)
                                continue;
@@ -648,9 +596,18 @@ void dss_set_dac_pwrdn_bgz(bool enable)
        REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
 }
 
-void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
+void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
 {
-       REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
+       enum omap_display_type dp;
+       dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
+
+       /* Complain about invalid selections */
+       WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC));
+       WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI));
+
+       /* Select only if we have options */
+       if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI))
+               REG_FLD_MOD(DSS_CONTROL, src, 15, 15);  /* VENC_HDMI_SWITCH */
 }
 
 enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
@@ -661,9 +618,71 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
        if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
                return DSS_VENC_TV_CLK;
 
+       if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0)
+               return DSS_HDMI_M_PCLK;
+
        return REG_GET(DSS_CONTROL, 15, 15);
 }
 
+static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel)
+{
+       if (channel != OMAP_DSS_CHANNEL_LCD)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int dss_dpi_select_source_omap4(enum omap_channel channel)
+{
+       int val;
+
+       switch (channel) {
+       case OMAP_DSS_CHANNEL_LCD2:
+               val = 0;
+               break;
+       case OMAP_DSS_CHANNEL_DIGIT:
+               val = 1;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       REG_FLD_MOD(DSS_CONTROL, val, 17, 17);
+
+       return 0;
+}
+
+static int dss_dpi_select_source_omap5(enum omap_channel channel)
+{
+       int val;
+
+       switch (channel) {
+       case OMAP_DSS_CHANNEL_LCD:
+               val = 1;
+               break;
+       case OMAP_DSS_CHANNEL_LCD2:
+               val = 2;
+               break;
+       case OMAP_DSS_CHANNEL_LCD3:
+               val = 3;
+               break;
+       case OMAP_DSS_CHANNEL_DIGIT:
+               val = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       REG_FLD_MOD(DSS_CONTROL, val, 17, 16);
+
+       return 0;
+}
+
+int dss_dpi_select_source(enum omap_channel channel)
+{
+       return dss.feat->dpi_select_source(channel);
+}
+
 static int dss_get_clocks(void)
 {
        struct clk *clk;
@@ -678,22 +697,11 @@ static int dss_get_clocks(void)
 
        dss.dss_clk = clk;
 
-       if (cpu_is_omap34xx()) {
-               clk = clk_get(NULL, "dpll4_m4_ck");
-               if (IS_ERR(clk)) {
-                       DSSERR("Failed to get dpll4_m4_ck\n");
-                       r = PTR_ERR(clk);
-                       goto err;
-               }
-       } else if (cpu_is_omap44xx()) {
-               clk = clk_get(NULL, "dpll_per_m5x2_ck");
-               if (IS_ERR(clk)) {
-                       DSSERR("Failed to get dpll_per_m5x2_ck\n");
-                       r = PTR_ERR(clk);
-                       goto err;
-               }
-       } else { /* omap24xx */
-               clk = NULL;
+       clk = clk_get(NULL, dss.feat->clk_name);
+       if (IS_ERR(clk)) {
+               DSSERR("Failed to get %s\n", dss.feat->clk_name);
+               r = PTR_ERR(clk);
+               goto err;
        }
 
        dss.dpll4_m4_ck = clk;
@@ -749,6 +757,71 @@ void dss_debug_dump_clocks(struct seq_file *s)
 }
 #endif
 
+static const struct dss_features omap24xx_dss_feats __initconst = {
+       .fck_div_max            =       16,
+       .dss_fck_multiplier     =       2,
+       .clk_name               =       NULL,
+       .dpi_select_source      =       &dss_dpi_select_source_omap2_omap3,
+};
+
+static const struct dss_features omap34xx_dss_feats __initconst = {
+       .fck_div_max            =       16,
+       .dss_fck_multiplier     =       2,
+       .clk_name               =       "dpll4_m4_ck",
+       .dpi_select_source      =       &dss_dpi_select_source_omap2_omap3,
+};
+
+static const struct dss_features omap3630_dss_feats __initconst = {
+       .fck_div_max            =       32,
+       .dss_fck_multiplier     =       1,
+       .clk_name               =       "dpll4_m4_ck",
+       .dpi_select_source      =       &dss_dpi_select_source_omap2_omap3,
+};
+
+static const struct dss_features omap44xx_dss_feats __initconst = {
+       .fck_div_max            =       32,
+       .dss_fck_multiplier     =       1,
+       .clk_name               =       "dpll_per_m5x2_ck",
+       .dpi_select_source      =       &dss_dpi_select_source_omap4,
+};
+
+static const struct dss_features omap54xx_dss_feats __initconst = {
+       .fck_div_max            =       64,
+       .dss_fck_multiplier     =       1,
+       .clk_name               =       "dpll_per_h12x2_ck",
+       .dpi_select_source      =       &dss_dpi_select_source_omap5,
+};
+
+static int __init dss_init_features(struct device *dev)
+{
+       const struct dss_features *src;
+       struct dss_features *dst;
+
+       dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+       if (!dst) {
+               dev_err(dev, "Failed to allocate local DSS Features\n");
+               return -ENOMEM;
+       }
+
+       if (cpu_is_omap24xx())
+               src = &omap24xx_dss_feats;
+       else if (cpu_is_omap34xx())
+               src = &omap34xx_dss_feats;
+       else if (cpu_is_omap3630())
+               src = &omap3630_dss_feats;
+       else if (cpu_is_omap44xx())
+               src = &omap44xx_dss_feats;
+       else if (soc_is_omap54xx())
+               src = &omap54xx_dss_feats;
+       else
+               return -ENODEV;
+
+       memcpy(dst, src, sizeof(*dst));
+       dss.feat = dst;
+
+       return 0;
+}
+
 /* DSS HW IP initialisation */
 static int __init omap_dsshw_probe(struct platform_device *pdev)
 {
@@ -758,6 +831,10 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
 
        dss.pdev = pdev;
 
+       r = dss_init_features(&dss.pdev->dev);
+       if (r)
+               return r;
+
        dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
        if (!dss_mem) {
                DSSERR("can't get IORESOURCE_MEM DSS\n");
index f67afe76f217f01c1aea097b49e26fefd0af0ce2..6728892f9dad596040c8c5ae0c270036f4ba5975 100644 (file)
@@ -113,6 +113,17 @@ enum dss_dsi_content_type {
        DSS_DSI_CONTENT_GENERIC,
 };
 
+enum dss_writeback_channel {
+       DSS_WB_LCD1_MGR =       0,
+       DSS_WB_LCD2_MGR =       1,
+       DSS_WB_TV_MGR =         2,
+       DSS_WB_OVL0 =           3,
+       DSS_WB_OVL1 =           4,
+       DSS_WB_OVL2 =           5,
+       DSS_WB_OVL3 =           6,
+       DSS_WB_LCD3_MGR =       7,
+};
+
 struct dss_clock_info {
        /* rates that we get with dividers below */
        unsigned long fck;
@@ -175,6 +186,7 @@ struct seq_file;
 struct platform_device;
 
 /* core */
+const char *dss_get_default_display_name(void);
 struct bus_type *dss_get_bus(void);
 struct regulator *dss_get_vdds_dsi(void);
 struct regulator *dss_get_vdds_sdi(void);
@@ -184,10 +196,13 @@ void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
 int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
 int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
 
-int omap_dss_register_device(struct omap_dss_device *dssdev,
-               struct device *parent, int disp_num);
-void omap_dss_unregister_device(struct omap_dss_device *dssdev);
-void omap_dss_unregister_child_devices(struct device *parent);
+struct omap_dss_device *dss_alloc_and_init_device(struct device *parent);
+int dss_add_device(struct omap_dss_device *dssdev);
+void dss_unregister_device(struct omap_dss_device *dssdev);
+void dss_unregister_child_devices(struct device *parent);
+void dss_put_device(struct omap_dss_device *dssdev);
+void dss_copy_device_pdata(struct omap_dss_device *dst,
+               const struct omap_dss_device *src);
 
 /* apply */
 void dss_apply_init(void);
@@ -205,8 +220,11 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
 int dss_mgr_set_device(struct omap_overlay_manager *mgr,
                struct omap_dss_device *dssdev);
 int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
+int dss_mgr_set_output(struct omap_overlay_manager *mgr,
+               struct omap_dss_output *output);
+int dss_mgr_unset_output(struct omap_overlay_manager *mgr);
 void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
-               struct omap_video_timings *timings);
+               const struct omap_video_timings *timings);
 void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
                const struct dss_lcd_mgr_config *config);
 const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr);
@@ -222,12 +240,17 @@ int dss_ovl_set_manager(struct omap_overlay *ovl,
                struct omap_overlay_manager *mgr);
 int dss_ovl_unset_manager(struct omap_overlay *ovl);
 
+/* output */
+void dss_register_output(struct omap_dss_output *out);
+void dss_unregister_output(struct omap_dss_output *out);
+struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev);
+
 /* display */
 int dss_suspend_all_devices(void);
 int dss_resume_all_devices(void);
 void dss_disable_all_devices(void);
 
-void dss_init_device(struct platform_device *pdev,
+int dss_init_device(struct platform_device *pdev,
                struct omap_dss_device *dssdev);
 void dss_uninit_device(struct platform_device *pdev,
                struct omap_dss_device *dssdev);
@@ -254,22 +277,29 @@ static inline bool dss_mgr_is_lcd(enum omap_channel id)
                return false;
 }
 
+int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
+               struct platform_device *pdev);
+void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr);
+
 /* overlay */
 void dss_init_overlays(struct platform_device *pdev);
 void dss_uninit_overlays(struct platform_device *pdev);
 void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
-void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
 int dss_ovl_simple_check(struct omap_overlay *ovl,
                const struct omap_overlay_info *info);
 int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
                const struct omap_video_timings *mgr_timings);
 bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
                enum omap_color_mode mode);
+int dss_overlay_kobj_init(struct omap_overlay *ovl,
+               struct platform_device *pdev);
+void dss_overlay_kobj_uninit(struct omap_overlay *ovl);
 
 /* DSS */
 int dss_init_platform_driver(void) __init;
 void dss_uninit_platform_driver(void);
 
+int dss_dpi_select_source(enum omap_channel channel);
 void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
 enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
 const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
@@ -279,7 +309,7 @@ void dss_dump_clocks(struct seq_file *s);
 void dss_debug_dump_clocks(struct seq_file *s);
 #endif
 
-void dss_sdi_init(u8 datapairs);
+void dss_sdi_init(int datapairs);
 int dss_sdi_enable(void);
 void dss_sdi_disable(void);
 
@@ -296,9 +326,7 @@ void dss_set_venc_output(enum omap_dss_venc_type type);
 void dss_set_dac_pwrdn_bgz(bool enable);
 
 unsigned long dss_get_dpll4_rate(void);
-int dss_calc_clock_rates(struct dss_clock_info *cinfo);
 int dss_set_clock_div(struct dss_clock_info *cinfo);
-int dss_get_clock_div(struct dss_clock_info *cinfo);
 int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
                struct dispc_clock_info *dispc_cinfo);
 
@@ -427,8 +455,9 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
 void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
                u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
                bool manual_update);
-int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
-               bool replication, const struct omap_video_timings *mgr_timings);
+int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
+               bool replication, const struct omap_video_timings *mgr_timings,
+               bool mem_to_mem);
 int dispc_ovl_enable(enum omap_plane plane, bool enable);
 void dispc_ovl_set_channel_out(enum omap_plane plane,
                enum omap_channel channel);
@@ -457,6 +486,15 @@ int dispc_mgr_get_clock_div(enum omap_channel channel,
 void dispc_mgr_setup(enum omap_channel channel,
                struct omap_overlay_manager_info *info);
 
+u32 dispc_wb_get_framedone_irq(void);
+bool dispc_wb_go_busy(void);
+void dispc_wb_go(void);
+void dispc_wb_enable(bool enable);
+bool dispc_wb_is_enabled(void);
+void dispc_wb_set_channel_in(enum dss_writeback_channel channel);
+int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
+               bool mem_to_mem, const struct omap_video_timings *timings);
+
 /* VENC */
 #ifdef CONFIG_OMAP2_DSS_VENC
 int venc_init_platform_driver(void) __init;
@@ -469,6 +507,20 @@ static inline unsigned long venc_get_pixel_clock(void)
        return 0;
 }
 #endif
+int omapdss_venc_display_enable(struct omap_dss_device *dssdev);
+void omapdss_venc_display_disable(struct omap_dss_device *dssdev);
+void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings);
+int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings);
+u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev);
+int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss);
+void omapdss_venc_set_type(struct omap_dss_device *dssdev,
+               enum omap_dss_venc_type type);
+void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
+               bool invert_polarity);
+int venc_panel_init(void);
+void venc_panel_exit(void);
 
 /* HDMI */
 #ifdef CONFIG_OMAP4_DSS_HDMI
@@ -484,7 +536,8 @@ static inline unsigned long hdmi_get_pixel_clock(void)
 #endif
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
-void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
+void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings);
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
                                        struct omap_video_timings *timings);
 int omapdss_hdmi_read_edid(u8 *buf, int len);
index 938709724f0cda2f6201c52b9548410e449eab49..acbc1e1efba3650aaccba2d86b000816973d23ba 100644 (file)
@@ -46,7 +46,9 @@ struct omap_dss_features {
 
        const int num_mgrs;
        const int num_ovls;
+       const int num_wbs;
        const enum omap_display_type *supported_displays;
+       const enum omap_dss_output_id *supported_outputs;
        const enum omap_color_mode *supported_color_modes;
        const enum omap_overlay_caps *overlay_caps;
        const char * const *clksrc_names;
@@ -106,6 +108,21 @@ static const struct dss_reg_field omap4_dss_reg_fields[] = {
        [FEAT_REG_DSIPLL_REGM_DSI]              = { 30, 26 },
 };
 
+static const struct dss_reg_field omap5_dss_reg_fields[] = {
+       [FEAT_REG_FIRHINC]                      = { 12, 0 },
+       [FEAT_REG_FIRVINC]                      = { 28, 16 },
+       [FEAT_REG_FIFOLOWTHRESHOLD]             = { 15, 0 },
+       [FEAT_REG_FIFOHIGHTHRESHOLD]            = { 31, 16 },
+       [FEAT_REG_FIFOSIZE]                     = { 15, 0 },
+       [FEAT_REG_HORIZONTALACCU]               = { 10, 0 },
+       [FEAT_REG_VERTICALACCU]                 = { 26, 16 },
+       [FEAT_REG_DISPC_CLK_SWITCH]             = { 9, 7 },
+       [FEAT_REG_DSIPLL_REGN]                  = { 8, 1 },
+       [FEAT_REG_DSIPLL_REGM]                  = { 20, 9 },
+       [FEAT_REG_DSIPLL_REGM_DISPC]            = { 25, 21 },
+       [FEAT_REG_DSIPLL_REGM_DSI]              = { 30, 26 },
+};
+
 static const enum omap_display_type omap2_dss_supported_displays[] = {
        /* OMAP_DSS_CHANNEL_LCD */
        OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI,
@@ -144,6 +161,76 @@ static const enum omap_display_type omap4_dss_supported_displays[] = {
        OMAP_DISPLAY_TYPE_DSI,
 };
 
+static const enum omap_display_type omap5_dss_supported_displays[] = {
+       /* OMAP_DSS_CHANNEL_LCD */
+       OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
+       OMAP_DISPLAY_TYPE_DSI,
+
+       /* OMAP_DSS_CHANNEL_DIGIT */
+       OMAP_DISPLAY_TYPE_HDMI | OMAP_DISPLAY_TYPE_DPI,
+
+       /* OMAP_DSS_CHANNEL_LCD2 */
+       OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
+       OMAP_DISPLAY_TYPE_DSI,
+};
+
+static const enum omap_dss_output_id omap2_dss_supported_outputs[] = {
+       /* OMAP_DSS_CHANNEL_LCD */
+       OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
+
+       /* OMAP_DSS_CHANNEL_DIGIT */
+       OMAP_DSS_OUTPUT_VENC,
+};
+
+static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = {
+       /* OMAP_DSS_CHANNEL_LCD */
+       OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
+       OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1,
+
+       /* OMAP_DSS_CHANNEL_DIGIT */
+       OMAP_DSS_OUTPUT_VENC,
+};
+
+static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
+       /* OMAP_DSS_CHANNEL_LCD */
+       OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
+       OMAP_DSS_OUTPUT_DSI1,
+
+       /* OMAP_DSS_CHANNEL_DIGIT */
+       OMAP_DSS_OUTPUT_VENC,
+};
+
+static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
+       /* OMAP_DSS_CHANNEL_LCD */
+       OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
+       OMAP_DSS_OUTPUT_DSI1,
+
+       /* OMAP_DSS_CHANNEL_DIGIT */
+       OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI |
+       OMAP_DSS_OUTPUT_DPI,
+
+       /* OMAP_DSS_CHANNEL_LCD2 */
+       OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
+       OMAP_DSS_OUTPUT_DSI2,
+};
+
+static const enum omap_dss_output_id omap5_dss_supported_outputs[] = {
+       /* OMAP_DSS_CHANNEL_LCD */
+       OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
+       OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2,
+
+       /* OMAP_DSS_CHANNEL_DIGIT */
+       OMAP_DSS_OUTPUT_HDMI | OMAP_DSS_OUTPUT_DPI,
+
+       /* OMAP_DSS_CHANNEL_LCD2 */
+       OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
+       OMAP_DSS_OUTPUT_DSI1,
+
+       /* OMAP_DSS_CHANNEL_LCD3 */
+       OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
+       OMAP_DSS_OUTPUT_DSI2,
+};
+
 static const enum omap_color_mode omap2_dss_supported_color_modes[] = {
        /* OMAP_DSS_GFX */
        OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
@@ -224,58 +311,80 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
        OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
        OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
        OMAP_DSS_COLOR_RGBX32,
+
+       /* OMAP_DSS_WB */
+       OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
+       OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
+       OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
+       OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
+       OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
+       OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
+       OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
+       OMAP_DSS_COLOR_RGBX32,
 };
 
 static const enum omap_overlay_caps omap2_dss_overlay_caps[] = {
        /* OMAP_DSS_GFX */
-       0,
+       OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
 
        /* OMAP_DSS_VIDEO1 */
-       OMAP_DSS_OVL_CAP_SCALE,
+       OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
+               OMAP_DSS_OVL_CAP_REPLICATION,
 
        /* OMAP_DSS_VIDEO2 */
-       OMAP_DSS_OVL_CAP_SCALE,
+       OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
+               OMAP_DSS_OVL_CAP_REPLICATION,
 };
 
 static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {
        /* OMAP_DSS_GFX */
-       OMAP_DSS_OVL_CAP_GLOBAL_ALPHA,
+       OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_POS |
+               OMAP_DSS_OVL_CAP_REPLICATION,
 
        /* OMAP_DSS_VIDEO1 */
-       OMAP_DSS_OVL_CAP_SCALE,
+       OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
+               OMAP_DSS_OVL_CAP_REPLICATION,
 
        /* OMAP_DSS_VIDEO2 */
-       OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA,
+       OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
+               OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
 };
 
 static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = {
        /* OMAP_DSS_GFX */
-       OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA,
+       OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
+               OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
 
        /* OMAP_DSS_VIDEO1 */
-       OMAP_DSS_OVL_CAP_SCALE,
+       OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
+               OMAP_DSS_OVL_CAP_REPLICATION,
 
        /* OMAP_DSS_VIDEO2 */
        OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
-               OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA,
+               OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS |
+               OMAP_DSS_OVL_CAP_REPLICATION,
 };
 
 static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
        /* OMAP_DSS_GFX */
        OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
-               OMAP_DSS_OVL_CAP_ZORDER,
+               OMAP_DSS_OVL_CAP_ZORDER | OMAP_DSS_OVL_CAP_POS |
+               OMAP_DSS_OVL_CAP_REPLICATION,
 
        /* OMAP_DSS_VIDEO1 */
        OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
-               OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
+               OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
+               OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
 
        /* OMAP_DSS_VIDEO2 */
        OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
-               OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
+               OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
+               OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
 
        /* OMAP_DSS_VIDEO3 */
        OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
-               OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
+               OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
+               OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
 };
 
 static const char * const omap2_dss_clk_source_names[] = {
@@ -298,6 +407,14 @@ static const char * const omap4_dss_clk_source_names[] = {
        [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI]   = "PLL2_CLK2",
 };
 
+static const char * const omap5_dss_clk_source_names[] = {
+       [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]  = "DPLL_DSI1_A_CLK1",
+       [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]    = "DPLL_DSI1_A_CLK2",
+       [OMAP_DSS_CLK_SRC_FCK]                  = "DSS_CLK",
+       [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DPLL_DSI1_C_CLK1",
+       [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI]   = "DPLL_DSI1_C_CLK2",
+};
+
 static const struct dss_param_range omap2_dss_param_range[] = {
        [FEAT_PARAM_DSS_FCK]                    = { 0, 173000000 },
        [FEAT_PARAM_DSS_PCD]                    = { 2, 255 },
@@ -326,6 +443,7 @@ static const struct dss_param_range omap3_dss_param_range[] = {
        [FEAT_PARAM_DSIPLL_REGM_DSI]            = { 0, (1 << 4) - 1 },
        [FEAT_PARAM_DSIPLL_FINT]                = { 750000, 2100000 },
        [FEAT_PARAM_DSIPLL_LPDIV]               = { 1, (1 << 13) - 1},
+       [FEAT_PARAM_DSI_FCK]                    = { 0, 173000000 },
        [FEAT_PARAM_DOWNSCALE]                  = { 1, 4 },
        [FEAT_PARAM_LINEWIDTH]                  = { 1, 1024 },
        [FEAT_PARAM_MGR_WIDTH]                  = { 1, 2048 },
@@ -341,6 +459,23 @@ static const struct dss_param_range omap4_dss_param_range[] = {
        [FEAT_PARAM_DSIPLL_REGM_DSI]            = { 0, (1 << 5) - 1 },
        [FEAT_PARAM_DSIPLL_FINT]                = { 500000, 2500000 },
        [FEAT_PARAM_DSIPLL_LPDIV]               = { 0, (1 << 13) - 1 },
+       [FEAT_PARAM_DSI_FCK]                    = { 0, 170000000 },
+       [FEAT_PARAM_DOWNSCALE]                  = { 1, 4 },
+       [FEAT_PARAM_LINEWIDTH]                  = { 1, 2048 },
+       [FEAT_PARAM_MGR_WIDTH]                  = { 1, 2048 },
+       [FEAT_PARAM_MGR_HEIGHT]                 = { 1, 2048 },
+};
+
+static const struct dss_param_range omap5_dss_param_range[] = {
+       [FEAT_PARAM_DSS_FCK]                    = { 0, 200000000 },
+       [FEAT_PARAM_DSS_PCD]                    = { 1, 255 },
+       [FEAT_PARAM_DSIPLL_REGN]                = { 0, (1 << 8) - 1 },
+       [FEAT_PARAM_DSIPLL_REGM]                = { 0, (1 << 12) - 1 },
+       [FEAT_PARAM_DSIPLL_REGM_DISPC]          = { 0, (1 << 5) - 1 },
+       [FEAT_PARAM_DSIPLL_REGM_DSI]            = { 0, (1 << 5) - 1 },
+       [FEAT_PARAM_DSIPLL_FINT]                = { 500000, 2500000 },
+       [FEAT_PARAM_DSIPLL_LPDIV]               = { 0, (1 << 13) - 1 },
+       [FEAT_PARAM_DSI_FCK]                    = { 0, 170000000 },
        [FEAT_PARAM_DOWNSCALE]                  = { 1, 4 },
        [FEAT_PARAM_LINEWIDTH]                  = { 1, 2048 },
        [FEAT_PARAM_MGR_WIDTH]                  = { 1, 2048 },
@@ -373,6 +508,26 @@ static const enum dss_feat_id omap3430_dss_feat_list[] = {
        FEAT_ALPHA_FIXED_ZORDER,
        FEAT_FIFO_MERGE,
        FEAT_OMAP3_DSI_FIFO_BUG,
+       FEAT_DPI_USES_VDDS_DSI,
+};
+
+static const enum dss_feat_id am35xx_dss_feat_list[] = {
+       FEAT_LCDENABLEPOL,
+       FEAT_LCDENABLESIGNAL,
+       FEAT_PCKFREEENABLE,
+       FEAT_FUNCGATED,
+       FEAT_LINEBUFFERSPLIT,
+       FEAT_ROWREPEATENABLE,
+       FEAT_RESIZECONF,
+       FEAT_DSI_PLL_FREQSEL,
+       FEAT_DSI_REVERSE_TXCLKESC,
+       FEAT_VENC_REQUIRES_TV_DAC_CLK,
+       FEAT_CPR,
+       FEAT_PRELOAD,
+       FEAT_FIR_COEF_V,
+       FEAT_ALPHA_FIXED_ZORDER,
+       FEAT_FIFO_MERGE,
+       FEAT_OMAP3_DSI_FIFO_BUG,
 };
 
 static const enum dss_feat_id omap3630_dss_feat_list[] = {
@@ -447,6 +602,28 @@ static const enum dss_feat_id omap4_dss_feat_list[] = {
        FEAT_BURST_2D,
 };
 
+static const enum dss_feat_id omap5_dss_feat_list[] = {
+       FEAT_MGR_LCD2,
+       FEAT_CORE_CLK_DIV,
+       FEAT_LCD_CLK_SRC,
+       FEAT_DSI_DCS_CMD_CONFIG_VC,
+       FEAT_DSI_VC_OCP_WIDTH,
+       FEAT_DSI_GNQ,
+       FEAT_HDMI_CTS_SWMODE,
+       FEAT_HDMI_AUDIO_USE_MCLK,
+       FEAT_HANDLE_UV_SEPARATE,
+       FEAT_ATTR2,
+       FEAT_CPR,
+       FEAT_PRELOAD,
+       FEAT_FIR_COEF_V,
+       FEAT_ALPHA_FREE_ZORDER,
+       FEAT_FIFO_MERGE,
+       FEAT_BURST_2D,
+       FEAT_DSI_PLL_SELFREQDCO,
+       FEAT_DSI_PLL_REFSEL,
+       FEAT_DSI_PHY_DCC,
+};
+
 /* OMAP2 DSS Features */
 static const struct omap_dss_features omap2_dss_features = {
        .reg_fields = omap2_dss_reg_fields,
@@ -458,6 +635,7 @@ static const struct omap_dss_features omap2_dss_features = {
        .num_mgrs = 2,
        .num_ovls = 3,
        .supported_displays = omap2_dss_supported_displays,
+       .supported_outputs = omap2_dss_supported_outputs,
        .supported_color_modes = omap2_dss_supported_color_modes,
        .overlay_caps = omap2_dss_overlay_caps,
        .clksrc_names = omap2_dss_clk_source_names,
@@ -478,6 +656,31 @@ static const struct omap_dss_features omap3430_dss_features = {
        .num_mgrs = 2,
        .num_ovls = 3,
        .supported_displays = omap3430_dss_supported_displays,
+       .supported_outputs = omap3430_dss_supported_outputs,
+       .supported_color_modes = omap3_dss_supported_color_modes,
+       .overlay_caps = omap3430_dss_overlay_caps,
+       .clksrc_names = omap3_dss_clk_source_names,
+       .dss_params = omap3_dss_param_range,
+       .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
+       .buffer_size_unit = 1,
+       .burst_size_unit = 8,
+};
+
+/*
+ * AM35xx DSS Features. This is basically OMAP3 DSS Features without the
+ * vdds_dsi regulator.
+ */
+static const struct omap_dss_features am35xx_dss_features = {
+       .reg_fields = omap3_dss_reg_fields,
+       .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
+
+       .features = am35xx_dss_feat_list,
+       .num_features = ARRAY_SIZE(am35xx_dss_feat_list),
+
+       .num_mgrs = 2,
+       .num_ovls = 3,
+       .supported_displays = omap3430_dss_supported_displays,
+       .supported_outputs = omap3430_dss_supported_outputs,
        .supported_color_modes = omap3_dss_supported_color_modes,
        .overlay_caps = omap3430_dss_overlay_caps,
        .clksrc_names = omap3_dss_clk_source_names,
@@ -497,6 +700,7 @@ static const struct omap_dss_features omap3630_dss_features = {
        .num_mgrs = 2,
        .num_ovls = 3,
        .supported_displays = omap3630_dss_supported_displays,
+       .supported_outputs = omap3630_dss_supported_outputs,
        .supported_color_modes = omap3_dss_supported_color_modes,
        .overlay_caps = omap3630_dss_overlay_caps,
        .clksrc_names = omap3_dss_clk_source_names,
@@ -517,7 +721,9 @@ static const struct omap_dss_features omap4430_es1_0_dss_features  = {
 
        .num_mgrs = 3,
        .num_ovls = 4,
+       .num_wbs = 1,
        .supported_displays = omap4_dss_supported_displays,
+       .supported_outputs = omap4_dss_supported_outputs,
        .supported_color_modes = omap4_dss_supported_color_modes,
        .overlay_caps = omap4_dss_overlay_caps,
        .clksrc_names = omap4_dss_clk_source_names,
@@ -537,7 +743,9 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
 
        .num_mgrs = 3,
        .num_ovls = 4,
+       .num_wbs = 1,
        .supported_displays = omap4_dss_supported_displays,
+       .supported_outputs = omap4_dss_supported_outputs,
        .supported_color_modes = omap4_dss_supported_color_modes,
        .overlay_caps = omap4_dss_overlay_caps,
        .clksrc_names = omap4_dss_clk_source_names,
@@ -557,7 +765,9 @@ static const struct omap_dss_features omap4_dss_features = {
 
        .num_mgrs = 3,
        .num_ovls = 4,
+       .num_wbs = 1,
        .supported_displays = omap4_dss_supported_displays,
+       .supported_outputs = omap4_dss_supported_outputs,
        .supported_color_modes = omap4_dss_supported_color_modes,
        .overlay_caps = omap4_dss_overlay_caps,
        .clksrc_names = omap4_dss_clk_source_names,
@@ -567,6 +777,27 @@ static const struct omap_dss_features omap4_dss_features = {
        .burst_size_unit = 16,
 };
 
+/* OMAP5 DSS Features */
+static const struct omap_dss_features omap5_dss_features = {
+       .reg_fields = omap5_dss_reg_fields,
+       .num_reg_fields = ARRAY_SIZE(omap5_dss_reg_fields),
+
+       .features = omap5_dss_feat_list,
+       .num_features = ARRAY_SIZE(omap5_dss_feat_list),
+
+       .num_mgrs = 3,
+       .num_ovls = 4,
+       .supported_displays = omap5_dss_supported_displays,
+       .supported_outputs = omap5_dss_supported_outputs,
+       .supported_color_modes = omap4_dss_supported_color_modes,
+       .overlay_caps = omap4_dss_overlay_caps,
+       .clksrc_names = omap5_dss_clk_source_names,
+       .dss_params = omap5_dss_param_range,
+       .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
+       .buffer_size_unit = 16,
+       .burst_size_unit = 16,
+};
+
 #if defined(CONFIG_OMAP4_DSS_HDMI)
 /* HDMI OMAP4 Functions*/
 static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
@@ -612,6 +843,11 @@ int dss_feat_get_num_ovls(void)
        return omap_current_dss_features->num_ovls;
 }
 
+int dss_feat_get_num_wbs(void)
+{
+       return omap_current_dss_features->num_wbs;
+}
+
 unsigned long dss_feat_get_param_min(enum dss_range_param param)
 {
        return omap_current_dss_features->dss_params[param].min;
@@ -627,6 +863,11 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel
        return omap_current_dss_features->supported_displays[channel];
 }
 
+enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
+{
+       return omap_current_dss_features->supported_outputs[channel];
+}
+
 enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
 {
        return omap_current_dss_features->supported_color_modes[plane];
@@ -694,8 +935,13 @@ void dss_features_init(void)
                omap_current_dss_features = &omap2_dss_features;
        else if (cpu_is_omap3630())
                omap_current_dss_features = &omap3630_dss_features;
-       else if (cpu_is_omap34xx())
-               omap_current_dss_features = &omap3430_dss_features;
+       else if (cpu_is_omap34xx()) {
+               if (soc_is_am35xx()) {
+                       omap_current_dss_features = &am35xx_dss_features;
+               } else {
+                       omap_current_dss_features = &omap3430_dss_features;
+               }
+       }
        else if (omap_rev() == OMAP4430_REV_ES1_0)
                omap_current_dss_features = &omap4430_es1_0_dss_features;
        else if (omap_rev() == OMAP4430_REV_ES2_0 ||
@@ -704,6 +950,8 @@ void dss_features_init(void)
                omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
        else if (cpu_is_omap44xx())
                omap_current_dss_features = &omap4_dss_features;
+       else if (soc_is_omap54xx())
+               omap_current_dss_features = &omap5_dss_features;
        else
                DSSWARN("Unsupported OMAP version");
 }
index 996ffcbfed58f4991b98ce7c34971dd0a400dba2..9218113b5e88c2c5488acb2f989e06ff080cfe06 100644 (file)
@@ -50,6 +50,7 @@ enum dss_feat_id {
        FEAT_DSI_VC_OCP_WIDTH,
        FEAT_DSI_REVERSE_TXCLKESC,
        FEAT_DSI_GNQ,
+       FEAT_DPI_USES_VDDS_DSI,
        FEAT_HDMI_CTS_SWMODE,
        FEAT_HDMI_AUDIO_USE_MCLK,
        FEAT_HANDLE_UV_SEPARATE,
@@ -64,6 +65,9 @@ enum dss_feat_id {
        /* An unknown HW bug causing the normal FIFO thresholds not to work */
        FEAT_OMAP3_DSI_FIFO_BUG,
        FEAT_BURST_2D,
+       FEAT_DSI_PLL_SELFREQDCO,
+       FEAT_DSI_PLL_REFSEL,
+       FEAT_DSI_PHY_DCC,
 };
 
 /* DSS register field id */
@@ -91,6 +95,7 @@ enum dss_range_param {
        FEAT_PARAM_DSIPLL_REGM_DSI,
        FEAT_PARAM_DSIPLL_FINT,
        FEAT_PARAM_DSIPLL_LPDIV,
+       FEAT_PARAM_DSI_FCK,
        FEAT_PARAM_DOWNSCALE,
        FEAT_PARAM_LINEWIDTH,
        FEAT_PARAM_MGR_WIDTH,
@@ -100,9 +105,11 @@ enum dss_range_param {
 /* DSS Feature Functions */
 int dss_feat_get_num_mgrs(void);
 int dss_feat_get_num_ovls(void);
+int dss_feat_get_num_wbs(void);
 unsigned long dss_feat_get_param_min(enum dss_range_param param);
 unsigned long dss_feat_get_param_max(enum dss_range_param param);
 enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
+enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel);
 enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
 enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
 bool dss_feat_color_mode_supported(enum omap_plane plane,
index 060216fdc5783da6675ebddb32f5ef3aa7cdfa70..a48a7dd75b3303a3bba28e10b01e4c1f133c00d3 100644 (file)
@@ -32,6 +32,8 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
 #include <video/omapdss.h>
 
 #include "ti_hdmi.h"
@@ -61,6 +63,13 @@ static struct {
        struct hdmi_ip_data ip_data;
 
        struct clk *sys_clk;
+       struct regulator *vdda_hdmi_dac_reg;
+
+       int ct_cp_hpd_gpio;
+       int ls_oe_gpio;
+       int hpd_gpio;
+
+       struct omap_dss_output output;
 } hdmi;
 
 /*
@@ -314,12 +323,47 @@ static void hdmi_runtime_put(void)
 
 static int __init hdmi_init_display(struct omap_dss_device *dssdev)
 {
+       int r;
+
+       struct gpio gpios[] = {
+               { hdmi.ct_cp_hpd_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd" },
+               { hdmi.ls_oe_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ls_oe" },
+               { hdmi.hpd_gpio, GPIOF_DIR_IN, "hdmi_hpd" },
+       };
+
        DSSDBG("init_display\n");
 
        dss_init_hdmi_ip_ops(&hdmi.ip_data);
+
+       if (hdmi.vdda_hdmi_dac_reg == NULL) {
+               struct regulator *reg;
+
+               reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
+
+               if (IS_ERR(reg)) {
+                       DSSERR("can't get VDDA_HDMI_DAC regulator\n");
+                       return PTR_ERR(reg);
+               }
+
+               hdmi.vdda_hdmi_dac_reg = reg;
+       }
+
+       r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
+       if (r)
+               return r;
+
        return 0;
 }
 
+static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev)
+{
+       DSSDBG("uninit_display\n");
+
+       gpio_free(hdmi.ct_cp_hpd_gpio);
+       gpio_free(hdmi.ls_oe_gpio);
+       gpio_free(hdmi.hpd_gpio);
+}
+
 static const struct hdmi_config *hdmi_find_timing(
                                        const struct hdmi_config *timings_arr,
                                        int len)
@@ -459,32 +503,30 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
 static int hdmi_power_on(struct omap_dss_device *dssdev)
 {
        int r;
-       const struct hdmi_config *timing;
        struct omap_video_timings *p;
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
        unsigned long phy;
 
+       gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
+       gpio_set_value(hdmi.ls_oe_gpio, 1);
+
+       /* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */
+       udelay(300);
+
+       r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
+       if (r)
+               goto err_vdac_enable;
+
        r = hdmi_runtime_get();
        if (r)
-               return r;
+               goto err_runtime_get;
 
-       dss_mgr_disable(dssdev->manager);
+       dss_mgr_disable(mgr);
 
-       p = &dssdev->panel.timings;
+       p = &hdmi.ip_data.cfg.timings;
 
-       DSSDBG("hdmi_power_on x_res= %d y_res = %d\n",
-               dssdev->panel.timings.x_res,
-               dssdev->panel.timings.y_res);
+       DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
 
-       timing = hdmi_get_timings();
-       if (timing == NULL) {
-               /* HDMI code 4 corresponds to 640 * 480 VGA */
-               hdmi.ip_data.cfg.cm.code = 4;
-               /* DVI mode 1 corresponds to HDMI 0 to DVI */
-               hdmi.ip_data.cfg.cm.mode = HDMI_DVI;
-               hdmi.ip_data.cfg = vesa_timings[0];
-       } else {
-               hdmi.ip_data.cfg = *timing;
-       }
        phy = p->pixel_clock;
 
        hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
@@ -495,13 +537,13 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
        r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
        if (r) {
                DSSDBG("Failed to lock PLL\n");
-               goto err;
+               goto err_pll_enable;
        }
 
        r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
        if (r) {
                DSSDBG("Failed to start PHY\n");
-               goto err;
+               goto err_phy_enable;
        }
 
        hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
@@ -521,13 +563,13 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
        dispc_enable_gamma_table(0);
 
        /* tv size */
-       dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
+       dss_mgr_set_timings(mgr, p);
 
        r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
        if (r)
                goto err_vid_enable;
 
-       r = dss_mgr_enable(dssdev->manager);
+       r = dss_mgr_enable(mgr);
        if (r)
                goto err_mgr_enable;
 
@@ -537,20 +579,33 @@ err_mgr_enable:
        hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
 err_vid_enable:
        hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
+err_phy_enable:
        hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
-err:
+err_pll_enable:
        hdmi_runtime_put();
+err_runtime_get:
+       regulator_disable(hdmi.vdda_hdmi_dac_reg);
+err_vdac_enable:
+       gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
+       gpio_set_value(hdmi.ls_oe_gpio, 0);
        return -EIO;
 }
 
 static void hdmi_power_off(struct omap_dss_device *dssdev)
 {
-       dss_mgr_disable(dssdev->manager);
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
+
+       dss_mgr_disable(mgr);
 
        hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
        hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
        hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
        hdmi_runtime_put();
+
+       regulator_disable(hdmi.vdda_hdmi_dac_reg);
+
+       gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
+       gpio_set_value(hdmi.ls_oe_gpio, 0);
 }
 
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -567,25 +622,22 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 
 }
 
-void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
+void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
 {
        struct hdmi_cm cm;
+       const struct hdmi_config *t;
 
-       cm = hdmi_get_code(&dssdev->panel.timings);
-       hdmi.ip_data.cfg.cm.code = cm.code;
-       hdmi.ip_data.cfg.cm.mode = cm.mode;
+       mutex_lock(&hdmi.lock);
 
-       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
-               int r;
+       cm = hdmi_get_code(timings);
+       hdmi.ip_data.cfg.cm = cm;
 
-               hdmi_power_off(dssdev);
+       t = hdmi_get_timings();
+       if (t != NULL)
+               hdmi.ip_data.cfg = *t;
 
-               r = hdmi_power_on(dssdev);
-               if (r)
-                       DSSERR("failed to power on device\n");
-       } else {
-               dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
-       }
+       mutex_unlock(&hdmi.lock);
 }
 
 static void hdmi_dump_regs(struct seq_file *s)
@@ -640,20 +692,20 @@ bool omapdss_hdmi_detect(void)
 
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
 {
-       struct omap_dss_hdmi_data *priv = dssdev->data;
+       struct omap_dss_output *out = dssdev->output;
        int r = 0;
 
        DSSDBG("ENTER hdmi_display_enable\n");
 
        mutex_lock(&hdmi.lock);
 
-       if (dssdev->manager == NULL) {
-               DSSERR("failed to enable display: no manager\n");
+       if (out == NULL || out->manager == NULL) {
+               DSSERR("failed to enable display: no output/manager\n");
                r = -ENODEV;
                goto err0;
        }
 
-       hdmi.ip_data.hpd_gpio = priv->hpd_gpio;
+       hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
 
        r = omap_dss_start_device(dssdev);
        if (r) {
@@ -661,26 +713,15 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
                goto err0;
        }
 
-       if (dssdev->platform_enable) {
-               r = dssdev->platform_enable(dssdev);
-               if (r) {
-                       DSSERR("failed to enable GPIO's\n");
-                       goto err1;
-               }
-       }
-
        r = hdmi_power_on(dssdev);
        if (r) {
                DSSERR("failed to power on device\n");
-               goto err2;
+               goto err1;
        }
 
        mutex_unlock(&hdmi.lock);
        return 0;
 
-err2:
-       if (dssdev->platform_disable)
-               dssdev->platform_disable(dssdev);
 err1:
        omap_dss_stop_device(dssdev);
 err0:
@@ -696,9 +737,6 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
 
        hdmi_power_off(dssdev);
 
-       if (dssdev->platform_disable)
-               dssdev->platform_disable(dssdev);
-
        omap_dss_stop_device(dssdev);
 
        mutex_unlock(&hdmi.lock);
@@ -869,10 +907,14 @@ int hdmi_audio_config(struct omap_dss_audio *audio)
 
 #endif
 
-static void __init hdmi_probe_pdata(struct platform_device *pdev)
+static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
 {
        struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-       int r, i;
+       const char *def_disp_name = dss_get_default_display_name();
+       struct omap_dss_device *def_dssdev;
+       int i;
+
+       def_dssdev = NULL;
 
        for (i = 0; i < pdata->num_devices; ++i) {
                struct omap_dss_device *dssdev = pdata->devices[i];
@@ -880,17 +922,76 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
                if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
                        continue;
 
-               r = hdmi_init_display(dssdev);
-               if (r) {
-                       DSSERR("device %s init failed: %d\n", dssdev->name, r);
-                       continue;
+               if (def_dssdev == NULL)
+                       def_dssdev = dssdev;
+
+               if (def_disp_name != NULL &&
+                               strcmp(dssdev->name, def_disp_name) == 0) {
+                       def_dssdev = dssdev;
+                       break;
                }
+       }
 
-               r = omap_dss_register_device(dssdev, &pdev->dev, i);
-               if (r)
-                       DSSERR("device %s register failed: %d\n",
-                                       dssdev->name, r);
+       return def_dssdev;
+}
+
+static void __init hdmi_probe_pdata(struct platform_device *pdev)
+{
+       struct omap_dss_device *plat_dssdev;
+       struct omap_dss_device *dssdev;
+       struct omap_dss_hdmi_data *priv;
+       int r;
+
+       plat_dssdev = hdmi_find_dssdev(pdev);
+
+       if (!plat_dssdev)
+               return;
+
+       dssdev = dss_alloc_and_init_device(&pdev->dev);
+       if (!dssdev)
+               return;
+
+       dss_copy_device_pdata(dssdev, plat_dssdev);
+
+       priv = dssdev->data;
+
+       hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio;
+       hdmi.ls_oe_gpio = priv->ls_oe_gpio;
+       hdmi.hpd_gpio = priv->hpd_gpio;
+
+       dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
+
+       r = hdmi_init_display(dssdev);
+       if (r) {
+               DSSERR("device %s init failed: %d\n", dssdev->name, r);
+               dss_put_device(dssdev);
+               return;
        }
+
+       r = dss_add_device(dssdev);
+       if (r) {
+               DSSERR("device %s register failed: %d\n", dssdev->name, r);
+               dss_put_device(dssdev);
+               return;
+       }
+}
+
+static void __init hdmi_init_output(struct platform_device *pdev)
+{
+       struct omap_dss_output *out = &hdmi.output;
+
+       out->pdev = pdev;
+       out->id = OMAP_DSS_OUTPUT_HDMI;
+       out->type = OMAP_DISPLAY_TYPE_HDMI;
+
+       dss_register_output(out);
+}
+
+static void __exit hdmi_uninit_output(struct platform_device *pdev)
+{
+       struct omap_dss_output *out = &hdmi.output;
+
+       dss_unregister_output(out);
 }
 
 /* HDMI HW IP initialisation */
@@ -929,23 +1030,37 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
        hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
        hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
        hdmi.ip_data.phy_offset = HDMI_PHY;
+
        mutex_init(&hdmi.ip_data.lock);
 
        hdmi_panel_init();
 
        dss_debugfs_create_file("hdmi", hdmi_dump_regs);
 
+       hdmi_init_output(pdev);
+
        hdmi_probe_pdata(pdev);
 
        return 0;
 }
 
+static int __exit hdmi_remove_child(struct device *dev, void *data)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       hdmi_uninit_display(dssdev);
+       return 0;
+}
+
 static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
 {
-       omap_dss_unregister_child_devices(&pdev->dev);
+       device_for_each_child(&pdev->dev, NULL, hdmi_remove_child);
+
+       dss_unregister_child_devices(&pdev->dev);
 
        hdmi_panel_exit();
 
+       hdmi_uninit_output(pdev);
+
        pm_runtime_disable(&pdev->dev);
 
        hdmi_put_clocks();
index e10844faadf91434df1c096aaf0e3dd5cc5e88d0..69fb115bab32928d7ce58574cb0120020b5720fe 100644 (file)
@@ -41,17 +41,34 @@ static struct {
 
 static int hdmi_panel_probe(struct omap_dss_device *dssdev)
 {
+       /* Initialize default timings to VGA in DVI mode */
+       const struct omap_video_timings default_timings = {
+               .x_res          = 640,
+               .y_res          = 480,
+               .pixel_clock    = 25175,
+               .hsw            = 96,
+               .hfp            = 16,
+               .hbp            = 48,
+               .vsw            = 2,
+               .vfp            = 11,
+               .vbp            = 31,
+
+               .vsync_level    = OMAPDSS_SIG_ACTIVE_LOW,
+               .hsync_level    = OMAPDSS_SIG_ACTIVE_LOW,
+
+               .interlace      = false,
+       };
+
        DSSDBG("ENTER hdmi_panel_probe\n");
 
-       dssdev->panel.timings = (struct omap_video_timings)
-                       { 640, 480, 25175, 96, 16, 48, 2, 11, 31,
-                               OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-                               false,
-                       };
+       dssdev->panel.timings = default_timings;
 
        DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
                dssdev->panel.timings.x_res,
                dssdev->panel.timings.y_res);
+
+       omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
+
        return 0;
 }
 
@@ -228,6 +245,8 @@ static int hdmi_panel_enable(struct omap_dss_device *dssdev)
                goto err;
        }
 
+       omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
+
        r = omapdss_hdmi_display_enable(dssdev);
        if (r) {
                DSSERR("failed to power on\n");
@@ -336,8 +355,8 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
         */
        hdmi_panel_audio_disable(dssdev);
 
+       omapdss_hdmi_display_set_timing(dssdev, timings);
        dssdev->panel.timings = *timings;
-       omapdss_hdmi_display_set_timing(dssdev);
 
        mutex_unlock(&hdmi.lock);
 }
diff --git a/drivers/video/omap2/dss/manager-sysfs.c b/drivers/video/omap2/dss/manager-sysfs.c
new file mode 100644 (file)
index 0000000..9a2fb59
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "MANAGER"
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/jiffies.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
+}
+
+static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
+{
+       struct omap_dss_device *dssdev = mgr->get_device(mgr);
+
+       return snprintf(buf, PAGE_SIZE, "%s\n", dssdev ?
+                       dssdev->name : "<none>");
+}
+
+static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
+               const char *buf, size_t size)
+{
+       int r = 0;
+       size_t len = size;
+       struct omap_dss_device *dssdev = NULL;
+
+       int match(struct omap_dss_device *dssdev, void *data)
+       {
+               const char *str = data;
+               return sysfs_streq(dssdev->name, str);
+       }
+
+       if (buf[size-1] == '\n')
+               --len;
+
+       if (len > 0)
+               dssdev = omap_dss_find_device((void *)buf, match);
+
+       if (len > 0 && dssdev == NULL)
+               return -EINVAL;
+
+       if (dssdev)
+               DSSDBG("display %s found\n", dssdev->name);
+
+       if (mgr->output) {
+               r = mgr->unset_output(mgr);
+               if (r) {
+                       DSSERR("failed to unset current output\n");
+                       goto put_device;
+               }
+       }
+
+       if (dssdev) {
+               struct omap_dss_output *out = dssdev->output;
+
+               /*
+                * a registered device should have an output connected to it
+                * already
+                */
+               if (!out) {
+                       DSSERR("device has no output connected to it\n");
+                       goto put_device;
+               }
+
+               r = mgr->set_output(mgr, out);
+               if (r) {
+                       DSSERR("failed to set manager output\n");
+                       goto put_device;
+               }
+
+               r = mgr->apply(mgr);
+               if (r) {
+                       DSSERR("failed to apply dispc config\n");
+                       goto put_device;
+               }
+       }
+
+put_device:
+       if (dssdev)
+               omap_dss_put_device(dssdev);
+
+       return r ? r : size;
+}
+
+static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
+                                         char *buf)
+{
+       struct omap_overlay_manager_info info;
+
+       mgr->get_manager_info(mgr, &info);
+
+       return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
+}
+
+static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
+                                          const char *buf, size_t size)
+{
+       struct omap_overlay_manager_info info;
+       u32 color;
+       int r;
+
+       r = kstrtouint(buf, 0, &color);
+       if (r)
+               return r;
+
+       mgr->get_manager_info(mgr, &info);
+
+       info.default_color = color;
+
+       r = mgr->set_manager_info(mgr, &info);
+       if (r)
+               return r;
+
+       r = mgr->apply(mgr);
+       if (r)
+               return r;
+
+       return size;
+}
+
+static const char *trans_key_type_str[] = {
+       "gfx-destination",
+       "video-source",
+};
+
+static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
+                                          char *buf)
+{
+       enum omap_dss_trans_key_type key_type;
+       struct omap_overlay_manager_info info;
+
+       mgr->get_manager_info(mgr, &info);
+
+       key_type = info.trans_key_type;
+       BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
+
+       return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
+}
+
+static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
+                                           const char *buf, size_t size)
+{
+       enum omap_dss_trans_key_type key_type;
+       struct omap_overlay_manager_info info;
+       int r;
+
+       for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
+                       key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
+               if (sysfs_streq(buf, trans_key_type_str[key_type]))
+                       break;
+       }
+
+       if (key_type == ARRAY_SIZE(trans_key_type_str))
+               return -EINVAL;
+
+       mgr->get_manager_info(mgr, &info);
+
+       info.trans_key_type = key_type;
+
+       r = mgr->set_manager_info(mgr, &info);
+       if (r)
+               return r;
+
+       r = mgr->apply(mgr);
+       if (r)
+               return r;
+
+       return size;
+}
+
+static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
+                                           char *buf)
+{
+       struct omap_overlay_manager_info info;
+
+       mgr->get_manager_info(mgr, &info);
+
+       return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
+}
+
+static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
+                                            const char *buf, size_t size)
+{
+       struct omap_overlay_manager_info info;
+       u32 key_value;
+       int r;
+
+       r = kstrtouint(buf, 0, &key_value);
+       if (r)
+               return r;
+
+       mgr->get_manager_info(mgr, &info);
+
+       info.trans_key = key_value;
+
+       r = mgr->set_manager_info(mgr, &info);
+       if (r)
+               return r;
+
+       r = mgr->apply(mgr);
+       if (r)
+               return r;
+
+       return size;
+}
+
+static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
+                                             char *buf)
+{
+       struct omap_overlay_manager_info info;
+
+       mgr->get_manager_info(mgr, &info);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
+}
+
+static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
+                                              const char *buf, size_t size)
+{
+       struct omap_overlay_manager_info info;
+       bool enable;
+       int r;
+
+       r = strtobool(buf, &enable);
+       if (r)
+               return r;
+
+       mgr->get_manager_info(mgr, &info);
+
+       info.trans_enabled = enable;
+
+       r = mgr->set_manager_info(mgr, &info);
+       if (r)
+               return r;
+
+       r = mgr->apply(mgr);
+       if (r)
+               return r;
+
+       return size;
+}
+
+static ssize_t manager_alpha_blending_enabled_show(
+               struct omap_overlay_manager *mgr, char *buf)
+{
+       struct omap_overlay_manager_info info;
+
+       mgr->get_manager_info(mgr, &info);
+
+       WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+               info.partial_alpha_enabled);
+}
+
+static ssize_t manager_alpha_blending_enabled_store(
+               struct omap_overlay_manager *mgr,
+               const char *buf, size_t size)
+{
+       struct omap_overlay_manager_info info;
+       bool enable;
+       int r;
+
+       WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
+
+       r = strtobool(buf, &enable);
+       if (r)
+               return r;
+
+       mgr->get_manager_info(mgr, &info);
+
+       info.partial_alpha_enabled = enable;
+
+       r = mgr->set_manager_info(mgr, &info);
+       if (r)
+               return r;
+
+       r = mgr->apply(mgr);
+       if (r)
+               return r;
+
+       return size;
+}
+
+static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
+               char *buf)
+{
+       struct omap_overlay_manager_info info;
+
+       mgr->get_manager_info(mgr, &info);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
+}
+
+static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
+               const char *buf, size_t size)
+{
+       struct omap_overlay_manager_info info;
+       int r;
+       bool enable;
+
+       if (!dss_has_feature(FEAT_CPR))
+               return -ENODEV;
+
+       r = strtobool(buf, &enable);
+       if (r)
+               return r;
+
+       mgr->get_manager_info(mgr, &info);
+
+       if (info.cpr_enable == enable)
+               return size;
+
+       info.cpr_enable = enable;
+
+       r = mgr->set_manager_info(mgr, &info);
+       if (r)
+               return r;
+
+       r = mgr->apply(mgr);
+       if (r)
+               return r;
+
+       return size;
+}
+
+static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
+               char *buf)
+{
+       struct omap_overlay_manager_info info;
+
+       mgr->get_manager_info(mgr, &info);
+
+       return snprintf(buf, PAGE_SIZE,
+                       "%d %d %d %d %d %d %d %d %d\n",
+                       info.cpr_coefs.rr,
+                       info.cpr_coefs.rg,
+                       info.cpr_coefs.rb,
+                       info.cpr_coefs.gr,
+                       info.cpr_coefs.gg,
+                       info.cpr_coefs.gb,
+                       info.cpr_coefs.br,
+                       info.cpr_coefs.bg,
+                       info.cpr_coefs.bb);
+}
+
+static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
+               const char *buf, size_t size)
+{
+       struct omap_overlay_manager_info info;
+       struct omap_dss_cpr_coefs coefs;
+       int r, i;
+       s16 *arr;
+
+       if (!dss_has_feature(FEAT_CPR))
+               return -ENODEV;
+
+       if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
+                               &coefs.rr, &coefs.rg, &coefs.rb,
+                               &coefs.gr, &coefs.gg, &coefs.gb,
+                               &coefs.br, &coefs.bg, &coefs.bb) != 9)
+               return -EINVAL;
+
+       arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
+               coefs.gr, coefs.gg, coefs.gb,
+               coefs.br, coefs.bg, coefs.bb };
+
+       for (i = 0; i < 9; ++i) {
+               if (arr[i] < -512 || arr[i] > 511)
+                       return -EINVAL;
+       }
+
+       mgr->get_manager_info(mgr, &info);
+
+       info.cpr_coefs = coefs;
+
+       r = mgr->set_manager_info(mgr, &info);
+       if (r)
+               return r;
+
+       r = mgr->apply(mgr);
+       if (r)
+               return r;
+
+       return size;
+}
+
+struct manager_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct omap_overlay_manager *, char *);
+       ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
+};
+
+#define MANAGER_ATTR(_name, _mode, _show, _store) \
+       struct manager_attribute manager_attr_##_name = \
+       __ATTR(_name, _mode, _show, _store)
+
+static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
+static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
+               manager_display_show, manager_display_store);
+static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
+               manager_default_color_show, manager_default_color_store);
+static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
+               manager_trans_key_type_show, manager_trans_key_type_store);
+static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
+               manager_trans_key_value_show, manager_trans_key_value_store);
+static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
+               manager_trans_key_enabled_show,
+               manager_trans_key_enabled_store);
+static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
+               manager_alpha_blending_enabled_show,
+               manager_alpha_blending_enabled_store);
+static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
+               manager_cpr_enable_show,
+               manager_cpr_enable_store);
+static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
+               manager_cpr_coef_show,
+               manager_cpr_coef_store);
+
+
+static struct attribute *manager_sysfs_attrs[] = {
+       &manager_attr_name.attr,
+       &manager_attr_display.attr,
+       &manager_attr_default_color.attr,
+       &manager_attr_trans_key_type.attr,
+       &manager_attr_trans_key_value.attr,
+       &manager_attr_trans_key_enabled.attr,
+       &manager_attr_alpha_blending_enabled.attr,
+       &manager_attr_cpr_enable.attr,
+       &manager_attr_cpr_coef.attr,
+       NULL
+};
+
+static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
+               char *buf)
+{
+       struct omap_overlay_manager *manager;
+       struct manager_attribute *manager_attr;
+
+       manager = container_of(kobj, struct omap_overlay_manager, kobj);
+       manager_attr = container_of(attr, struct manager_attribute, attr);
+
+       if (!manager_attr->show)
+               return -ENOENT;
+
+       return manager_attr->show(manager, buf);
+}
+
+static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
+               const char *buf, size_t size)
+{
+       struct omap_overlay_manager *manager;
+       struct manager_attribute *manager_attr;
+
+       manager = container_of(kobj, struct omap_overlay_manager, kobj);
+       manager_attr = container_of(attr, struct manager_attribute, attr);
+
+       if (!manager_attr->store)
+               return -ENOENT;
+
+       return manager_attr->store(manager, buf, size);
+}
+
+static const struct sysfs_ops manager_sysfs_ops = {
+       .show = manager_attr_show,
+       .store = manager_attr_store,
+};
+
+static struct kobj_type manager_ktype = {
+       .sysfs_ops = &manager_sysfs_ops,
+       .default_attrs = manager_sysfs_attrs,
+};
+
+int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
+               struct platform_device *pdev)
+{
+       return kobject_init_and_add(&mgr->kobj, &manager_ktype,
+                       &pdev->dev.kobj, "manager%d", mgr->id);
+}
+
+void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
+{
+       kobject_del(&mgr->kobj);
+       kobject_put(&mgr->kobj);
+}
index 53710fadc82de4f2a8f3802dbd2f2215e59dfd14..c54d2f620ce3e5d94c4fb65ef39fb4fd150c44ab 100644 (file)
 static int num_managers;
 static struct omap_overlay_manager *managers;
 
-static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
+static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
 {
-       return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
+       return mgr->output ? mgr->output->device : NULL;
 }
 
-static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%s\n",
-                       mgr->device ? mgr->device->name : "<none>");
-}
-
-static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
-               const char *buf, size_t size)
-{
-       int r = 0;
-       size_t len = size;
-       struct omap_dss_device *dssdev = NULL;
-
-       int match(struct omap_dss_device *dssdev, void *data)
-       {
-               const char *str = data;
-               return sysfs_streq(dssdev->name, str);
-       }
-
-       if (buf[size-1] == '\n')
-               --len;
-
-       if (len > 0)
-               dssdev = omap_dss_find_device((void *)buf, match);
-
-       if (len > 0 && dssdev == NULL)
-               return -EINVAL;
-
-       if (dssdev)
-               DSSDBG("display %s found\n", dssdev->name);
-
-       if (mgr->device) {
-               r = mgr->unset_device(mgr);
-               if (r) {
-                       DSSERR("failed to unset display\n");
-                       goto put_device;
-               }
-       }
-
-       if (dssdev) {
-               r = mgr->set_device(mgr, dssdev);
-               if (r) {
-                       DSSERR("failed to set manager\n");
-                       goto put_device;
-               }
-
-               r = mgr->apply(mgr);
-               if (r) {
-                       DSSERR("failed to apply dispc config\n");
-                       goto put_device;
-               }
-       }
-
-put_device:
-       if (dssdev)
-               omap_dss_put_device(dssdev);
-
-       return r ? r : size;
-}
-
-static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
-                                         char *buf)
-{
-       struct omap_overlay_manager_info info;
-
-       mgr->get_manager_info(mgr, &info);
-
-       return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
-}
-
-static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
-                                          const char *buf, size_t size)
-{
-       struct omap_overlay_manager_info info;
-       u32 color;
-       int r;
-
-       r = kstrtouint(buf, 0, &color);
-       if (r)
-               return r;
-
-       mgr->get_manager_info(mgr, &info);
-
-       info.default_color = color;
-
-       r = mgr->set_manager_info(mgr, &info);
-       if (r)
-               return r;
-
-       r = mgr->apply(mgr);
-       if (r)
-               return r;
-
-       return size;
-}
-
-static const char *trans_key_type_str[] = {
-       "gfx-destination",
-       "video-source",
-};
-
-static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
-                                          char *buf)
-{
-       enum omap_dss_trans_key_type key_type;
-       struct omap_overlay_manager_info info;
-
-       mgr->get_manager_info(mgr, &info);
-
-       key_type = info.trans_key_type;
-       BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
-
-       return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
-}
-
-static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
-                                           const char *buf, size_t size)
-{
-       enum omap_dss_trans_key_type key_type;
-       struct omap_overlay_manager_info info;
-       int r;
-
-       for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
-                       key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
-               if (sysfs_streq(buf, trans_key_type_str[key_type]))
-                       break;
-       }
-
-       if (key_type == ARRAY_SIZE(trans_key_type_str))
-               return -EINVAL;
-
-       mgr->get_manager_info(mgr, &info);
-
-       info.trans_key_type = key_type;
-
-       r = mgr->set_manager_info(mgr, &info);
-       if (r)
-               return r;
-
-       r = mgr->apply(mgr);
-       if (r)
-               return r;
-
-       return size;
-}
-
-static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
-                                           char *buf)
-{
-       struct omap_overlay_manager_info info;
-
-       mgr->get_manager_info(mgr, &info);
-
-       return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
-}
-
-static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
-                                            const char *buf, size_t size)
-{
-       struct omap_overlay_manager_info info;
-       u32 key_value;
-       int r;
-
-       r = kstrtouint(buf, 0, &key_value);
-       if (r)
-               return r;
-
-       mgr->get_manager_info(mgr, &info);
-
-       info.trans_key = key_value;
-
-       r = mgr->set_manager_info(mgr, &info);
-       if (r)
-               return r;
-
-       r = mgr->apply(mgr);
-       if (r)
-               return r;
-
-       return size;
-}
-
-static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
-                                             char *buf)
-{
-       struct omap_overlay_manager_info info;
-
-       mgr->get_manager_info(mgr, &info);
-
-       return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
-}
-
-static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
-                                              const char *buf, size_t size)
-{
-       struct omap_overlay_manager_info info;
-       bool enable;
-       int r;
-
-       r = strtobool(buf, &enable);
-       if (r)
-               return r;
-
-       mgr->get_manager_info(mgr, &info);
-
-       info.trans_enabled = enable;
-
-       r = mgr->set_manager_info(mgr, &info);
-       if (r)
-               return r;
-
-       r = mgr->apply(mgr);
-       if (r)
-               return r;
-
-       return size;
-}
-
-static ssize_t manager_alpha_blending_enabled_show(
-               struct omap_overlay_manager *mgr, char *buf)
-{
-       struct omap_overlay_manager_info info;
-
-       mgr->get_manager_info(mgr, &info);
-
-       WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
-
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-               info.partial_alpha_enabled);
-}
-
-static ssize_t manager_alpha_blending_enabled_store(
-               struct omap_overlay_manager *mgr,
-               const char *buf, size_t size)
-{
-       struct omap_overlay_manager_info info;
-       bool enable;
-       int r;
-
-       WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
-
-       r = strtobool(buf, &enable);
-       if (r)
-               return r;
-
-       mgr->get_manager_info(mgr, &info);
-
-       info.partial_alpha_enabled = enable;
-
-       r = mgr->set_manager_info(mgr, &info);
-       if (r)
-               return r;
-
-       r = mgr->apply(mgr);
-       if (r)
-               return r;
-
-       return size;
-}
-
-static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
-               char *buf)
-{
-       struct omap_overlay_manager_info info;
-
-       mgr->get_manager_info(mgr, &info);
-
-       return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
-}
-
-static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
-               const char *buf, size_t size)
-{
-       struct omap_overlay_manager_info info;
-       int r;
-       bool enable;
-
-       if (!dss_has_feature(FEAT_CPR))
-               return -ENODEV;
-
-       r = strtobool(buf, &enable);
-       if (r)
-               return r;
-
-       mgr->get_manager_info(mgr, &info);
-
-       if (info.cpr_enable == enable)
-               return size;
-
-       info.cpr_enable = enable;
-
-       r = mgr->set_manager_info(mgr, &info);
-       if (r)
-               return r;
-
-       r = mgr->apply(mgr);
-       if (r)
-               return r;
-
-       return size;
-}
-
-static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
-               char *buf)
-{
-       struct omap_overlay_manager_info info;
-
-       mgr->get_manager_info(mgr, &info);
-
-       return snprintf(buf, PAGE_SIZE,
-                       "%d %d %d %d %d %d %d %d %d\n",
-                       info.cpr_coefs.rr,
-                       info.cpr_coefs.rg,
-                       info.cpr_coefs.rb,
-                       info.cpr_coefs.gr,
-                       info.cpr_coefs.gg,
-                       info.cpr_coefs.gb,
-                       info.cpr_coefs.br,
-                       info.cpr_coefs.bg,
-                       info.cpr_coefs.bb);
-}
-
-static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
-               const char *buf, size_t size)
-{
-       struct omap_overlay_manager_info info;
-       struct omap_dss_cpr_coefs coefs;
-       int r, i;
-       s16 *arr;
-
-       if (!dss_has_feature(FEAT_CPR))
-               return -ENODEV;
-
-       if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
-                               &coefs.rr, &coefs.rg, &coefs.rb,
-                               &coefs.gr, &coefs.gg, &coefs.gb,
-                               &coefs.br, &coefs.bg, &coefs.bb) != 9)
-               return -EINVAL;
-
-       arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
-               coefs.gr, coefs.gg, coefs.gb,
-               coefs.br, coefs.bg, coefs.bb };
-
-       for (i = 0; i < 9; ++i) {
-               if (arr[i] < -512 || arr[i] > 511)
-                       return -EINVAL;
-       }
-
-       mgr->get_manager_info(mgr, &info);
-
-       info.cpr_coefs = coefs;
-
-       r = mgr->set_manager_info(mgr, &info);
-       if (r)
-               return r;
-
-       r = mgr->apply(mgr);
-       if (r)
-               return r;
-
-       return size;
-}
-
-struct manager_attribute {
-       struct attribute attr;
-       ssize_t (*show)(struct omap_overlay_manager *, char *);
-       ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
-};
-
-#define MANAGER_ATTR(_name, _mode, _show, _store) \
-       struct manager_attribute manager_attr_##_name = \
-       __ATTR(_name, _mode, _show, _store)
-
-static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
-static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
-               manager_display_show, manager_display_store);
-static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
-               manager_default_color_show, manager_default_color_store);
-static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
-               manager_trans_key_type_show, manager_trans_key_type_store);
-static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
-               manager_trans_key_value_show, manager_trans_key_value_store);
-static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
-               manager_trans_key_enabled_show,
-               manager_trans_key_enabled_store);
-static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
-               manager_alpha_blending_enabled_show,
-               manager_alpha_blending_enabled_store);
-static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
-               manager_cpr_enable_show,
-               manager_cpr_enable_store);
-static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
-               manager_cpr_coef_show,
-               manager_cpr_coef_store);
-
-
-static struct attribute *manager_sysfs_attrs[] = {
-       &manager_attr_name.attr,
-       &manager_attr_display.attr,
-       &manager_attr_default_color.attr,
-       &manager_attr_trans_key_type.attr,
-       &manager_attr_trans_key_value.attr,
-       &manager_attr_trans_key_enabled.attr,
-       &manager_attr_alpha_blending_enabled.attr,
-       &manager_attr_cpr_enable.attr,
-       &manager_attr_cpr_coef.attr,
-       NULL
-};
-
-static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
-               char *buf)
-{
-       struct omap_overlay_manager *manager;
-       struct manager_attribute *manager_attr;
-
-       manager = container_of(kobj, struct omap_overlay_manager, kobj);
-       manager_attr = container_of(attr, struct manager_attribute, attr);
-
-       if (!manager_attr->show)
-               return -ENOENT;
-
-       return manager_attr->show(manager, buf);
-}
-
-static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
-               const char *buf, size_t size)
-{
-       struct omap_overlay_manager *manager;
-       struct manager_attribute *manager_attr;
-
-       manager = container_of(kobj, struct omap_overlay_manager, kobj);
-       manager_attr = container_of(attr, struct manager_attribute, attr);
-
-       if (!manager_attr->store)
-               return -ENOENT;
-
-       return manager_attr->store(manager, buf, size);
-}
-
-static const struct sysfs_ops manager_sysfs_ops = {
-       .show = manager_attr_show,
-       .store = manager_attr_store,
-};
-
-static struct kobj_type manager_ktype = {
-       .sysfs_ops = &manager_sysfs_ops,
-       .default_attrs = manager_sysfs_attrs,
-};
-
 static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
 {
        unsigned long timeout = msecs_to_jiffies(500);
+       struct omap_dss_device *dssdev = mgr->get_device(mgr);
        u32 irq;
        int r;
 
@@ -500,9 +52,9 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
        if (r)
                return r;
 
-       if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC)
+       if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
                irq = DISPC_IRQ_EVSYNC_ODD;
-       else if (mgr->device->type == OMAP_DISPLAY_TYPE_HDMI)
+       else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
                irq = DISPC_IRQ_EVSYNC_EVEN;
        else
                irq = dispc_mgr_get_vsync_irq(mgr->id);
@@ -547,23 +99,24 @@ int dss_init_overlay_managers(struct platform_device *pdev)
                        break;
                }
 
-               mgr->set_device = &dss_mgr_set_device;
-               mgr->unset_device = &dss_mgr_unset_device;
+               mgr->set_output = &dss_mgr_set_output;
+               mgr->unset_output = &dss_mgr_unset_output;
                mgr->apply = &omap_dss_mgr_apply;
                mgr->set_manager_info = &dss_mgr_set_info;
                mgr->get_manager_info = &dss_mgr_get_info;
                mgr->wait_for_go = &dss_mgr_wait_for_go;
                mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
+               mgr->get_device = &dss_mgr_get_device;
 
                mgr->caps = 0;
                mgr->supported_displays =
                        dss_feat_get_supported_displays(mgr->id);
+               mgr->supported_outputs =
+                       dss_feat_get_supported_outputs(mgr->id);
 
                INIT_LIST_HEAD(&mgr->overlays);
 
-               r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
-                               &pdev->dev.kobj, "manager%d", i);
-
+               r = dss_manager_kobj_init(mgr, pdev);
                if (r)
                        DSSERR("failed to create sysfs file\n");
        }
@@ -577,9 +130,7 @@ void dss_uninit_overlay_managers(struct platform_device *pdev)
 
        for (i = 0; i < num_managers; ++i) {
                struct omap_overlay_manager *mgr = &managers[i];
-
-               kobject_del(&mgr->kobj);
-               kobject_put(&mgr->kobj);
+               dss_manager_kobj_uninit(mgr);
        }
 
        kfree(managers);
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c
new file mode 100644 (file)
index 0000000..813f266
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Ltd
+ * Author: Archit Taneja <archit@ti.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.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+
+static LIST_HEAD(output_list);
+static DEFINE_MUTEX(output_lock);
+
+int omapdss_output_set_device(struct omap_dss_output *out,
+               struct omap_dss_device *dssdev)
+{
+       int r;
+
+       mutex_lock(&output_lock);
+
+       if (out->device) {
+               DSSERR("output already has device %s connected to it\n",
+                       out->device->name);
+               r = -EINVAL;
+               goto err;
+       }
+
+       if (out->type != dssdev->type) {
+               DSSERR("output type and display type don't match\n");
+               r = -EINVAL;
+               goto err;
+       }
+
+       out->device = dssdev;
+       dssdev->output = out;
+
+       mutex_unlock(&output_lock);
+
+       return 0;
+err:
+       mutex_unlock(&output_lock);
+
+       return r;
+}
+EXPORT_SYMBOL(omapdss_output_set_device);
+
+int omapdss_output_unset_device(struct omap_dss_output *out)
+{
+       int r;
+
+       mutex_lock(&output_lock);
+
+       if (!out->device) {
+               DSSERR("output doesn't have a device connected to it\n");
+               r = -EINVAL;
+               goto err;
+       }
+
+       if (out->device->state != OMAP_DSS_DISPLAY_DISABLED) {
+               DSSERR("device %s is not disabled, cannot unset device\n",
+                               out->device->name);
+               r = -EINVAL;
+               goto err;
+       }
+
+       out->device->output = NULL;
+       out->device = NULL;
+
+       mutex_unlock(&output_lock);
+
+       return 0;
+err:
+       mutex_unlock(&output_lock);
+
+       return r;
+}
+EXPORT_SYMBOL(omapdss_output_unset_device);
+
+void dss_register_output(struct omap_dss_output *out)
+{
+       list_add_tail(&out->list, &output_list);
+}
+
+void dss_unregister_output(struct omap_dss_output *out)
+{
+       list_del(&out->list);
+}
+
+struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
+{
+       struct omap_dss_output *out;
+
+       list_for_each_entry(out, &output_list, list) {
+               if (out->id == id)
+                       return out;
+       }
+
+       return NULL;
+}
+
+struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev)
+{
+       struct omap_dss_output *out = NULL;
+       enum omap_dss_output_id id;
+
+       switch (dssdev->type) {
+       case OMAP_DISPLAY_TYPE_DPI:
+               out = omap_dss_get_output(OMAP_DSS_OUTPUT_DPI);
+               break;
+       case OMAP_DISPLAY_TYPE_DBI:
+               out = omap_dss_get_output(OMAP_DSS_OUTPUT_DBI);
+               break;
+       case OMAP_DISPLAY_TYPE_SDI:
+               out = omap_dss_get_output(OMAP_DSS_OUTPUT_SDI);
+               break;
+       case OMAP_DISPLAY_TYPE_VENC:
+               out = omap_dss_get_output(OMAP_DSS_OUTPUT_VENC);
+               break;
+       case OMAP_DISPLAY_TYPE_HDMI:
+               out = omap_dss_get_output(OMAP_DSS_OUTPUT_HDMI);
+               break;
+       case OMAP_DISPLAY_TYPE_DSI:
+               id = dssdev->phy.dsi.module == 0 ? OMAP_DSS_OUTPUT_DSI1 :
+                                       OMAP_DSS_OUTPUT_DSI2;
+               out = omap_dss_get_output(id);
+               break;
+       default:
+               break;
+       }
+
+       return out;
+}
diff --git a/drivers/video/omap2/dss/overlay-sysfs.c b/drivers/video/omap2/dss/overlay-sysfs.c
new file mode 100644 (file)
index 0000000..4cc5dde
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "OVERLAY"
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <linux/platform_device.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
+}
+
+static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%s\n",
+                       ovl->manager ? ovl->manager->name : "<none>");
+}
+
+static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
+               size_t size)
+{
+       int i, r;
+       struct omap_overlay_manager *mgr = NULL;
+       struct omap_overlay_manager *old_mgr;
+       int len = size;
+
+       if (buf[size-1] == '\n')
+               --len;
+
+       if (len > 0) {
+               for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+                       mgr = omap_dss_get_overlay_manager(i);
+
+                       if (sysfs_streq(buf, mgr->name))
+                               break;
+
+                       mgr = NULL;
+               }
+       }
+
+       if (len > 0 && mgr == NULL)
+               return -EINVAL;
+
+       if (mgr)
+               DSSDBG("manager %s found\n", mgr->name);
+
+       if (mgr == ovl->manager)
+               return size;
+
+       old_mgr = ovl->manager;
+
+       r = dispc_runtime_get();
+       if (r)
+               return r;
+
+       /* detach old manager */
+       if (old_mgr) {
+               r = ovl->unset_manager(ovl);
+               if (r) {
+                       DSSERR("detach failed\n");
+                       goto err;
+               }
+
+               r = old_mgr->apply(old_mgr);
+               if (r)
+                       goto err;
+       }
+
+       if (mgr) {
+               r = ovl->set_manager(ovl, mgr);
+               if (r) {
+                       DSSERR("Failed to attach overlay\n");
+                       goto err;
+               }
+
+               r = mgr->apply(mgr);
+               if (r)
+                       goto err;
+       }
+
+       dispc_runtime_put();
+
+       return size;
+
+err:
+       dispc_runtime_put();
+       return r;
+}
+
+static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
+{
+       struct omap_overlay_info info;
+
+       ovl->get_overlay_info(ovl, &info);
+
+       return snprintf(buf, PAGE_SIZE, "%d,%d\n",
+                       info.width, info.height);
+}
+
+static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
+{
+       struct omap_overlay_info info;
+
+       ovl->get_overlay_info(ovl, &info);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
+}
+
+static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
+{
+       struct omap_overlay_info info;
+
+       ovl->get_overlay_info(ovl, &info);
+
+       return snprintf(buf, PAGE_SIZE, "%d,%d\n",
+                       info.pos_x, info.pos_y);
+}
+
+static ssize_t overlay_position_store(struct omap_overlay *ovl,
+               const char *buf, size_t size)
+{
+       int r;
+       char *last;
+       struct omap_overlay_info info;
+
+       ovl->get_overlay_info(ovl, &info);
+
+       info.pos_x = simple_strtoul(buf, &last, 10);
+       ++last;
+       if (last - buf >= size)
+               return -EINVAL;
+
+       info.pos_y = simple_strtoul(last, &last, 10);
+
+       r = ovl->set_overlay_info(ovl, &info);
+       if (r)
+               return r;
+
+       if (ovl->manager) {
+               r = ovl->manager->apply(ovl->manager);
+               if (r)
+                       return r;
+       }
+
+       return size;
+}
+
+static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
+{
+       struct omap_overlay_info info;
+
+       ovl->get_overlay_info(ovl, &info);
+
+       return snprintf(buf, PAGE_SIZE, "%d,%d\n",
+                       info.out_width, info.out_height);
+}
+
+static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
+               const char *buf, size_t size)
+{
+       int r;
+       char *last;
+       struct omap_overlay_info info;
+
+       ovl->get_overlay_info(ovl, &info);
+
+       info.out_width = simple_strtoul(buf, &last, 10);
+       ++last;
+       if (last - buf >= size)
+               return -EINVAL;
+
+       info.out_height = simple_strtoul(last, &last, 10);
+
+       r = ovl->set_overlay_info(ovl, &info);
+       if (r)
+               return r;
+
+       if (ovl->manager) {
+               r = ovl->manager->apply(ovl->manager);
+               if (r)
+                       return r;
+       }
+
+       return size;
+}
+
+static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
+}
+
+static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
+               size_t size)
+{
+       int r;
+       bool enable;
+
+       r = strtobool(buf, &enable);
+       if (r)
+               return r;
+
+       if (enable)
+               r = ovl->enable(ovl);
+       else
+               r = ovl->disable(ovl);
+
+       if (r)
+               return r;
+
+       return size;
+}
+
+static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
+{
+       struct omap_overlay_info info;
+
+       ovl->get_overlay_info(ovl, &info);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       info.global_alpha);
+}
+
+static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
+               const char *buf, size_t size)
+{
+       int r;
+       u8 alpha;
+       struct omap_overlay_info info;
+
+       if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
+               return -ENODEV;
+
+       r = kstrtou8(buf, 0, &alpha);
+       if (r)
+               return r;
+
+       ovl->get_overlay_info(ovl, &info);
+
+       info.global_alpha = alpha;
+
+       r = ovl->set_overlay_info(ovl, &info);
+       if (r)
+               return r;
+
+       if (ovl->manager) {
+               r = ovl->manager->apply(ovl->manager);
+               if (r)
+                       return r;
+       }
+
+       return size;
+}
+
+static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
+               char *buf)
+{
+       struct omap_overlay_info info;
+
+       ovl->get_overlay_info(ovl, &info);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       info.pre_mult_alpha);
+}
+
+static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
+               const char *buf, size_t size)
+{
+       int r;
+       u8 alpha;
+       struct omap_overlay_info info;
+
+       if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
+               return -ENODEV;
+
+       r = kstrtou8(buf, 0, &alpha);
+       if (r)
+               return r;
+
+       ovl->get_overlay_info(ovl, &info);
+
+       info.pre_mult_alpha = alpha;
+
+       r = ovl->set_overlay_info(ovl, &info);
+       if (r)
+               return r;
+
+       if (ovl->manager) {
+               r = ovl->manager->apply(ovl->manager);
+               if (r)
+                       return r;
+       }
+
+       return size;
+}
+
+static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
+{
+       struct omap_overlay_info info;
+
+       ovl->get_overlay_info(ovl, &info);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
+}
+
+static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
+               const char *buf, size_t size)
+{
+       int r;
+       u8 zorder;
+       struct omap_overlay_info info;
+
+       if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
+               return -ENODEV;
+
+       r = kstrtou8(buf, 0, &zorder);
+       if (r)
+               return r;
+
+       ovl->get_overlay_info(ovl, &info);
+
+       info.zorder = zorder;
+
+       r = ovl->set_overlay_info(ovl, &info);
+       if (r)
+               return r;
+
+       if (ovl->manager) {
+               r = ovl->manager->apply(ovl->manager);
+               if (r)
+                       return r;
+       }
+
+       return size;
+}
+
+struct overlay_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct omap_overlay *, char *);
+       ssize_t (*store)(struct omap_overlay *, const char *, size_t);
+};
+
+#define OVERLAY_ATTR(_name, _mode, _show, _store) \
+       struct overlay_attribute overlay_attr_##_name = \
+       __ATTR(_name, _mode, _show, _store)
+
+static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
+static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
+               overlay_manager_show, overlay_manager_store);
+static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
+static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
+static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
+               overlay_position_show, overlay_position_store);
+static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
+               overlay_output_size_show, overlay_output_size_store);
+static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
+               overlay_enabled_show, overlay_enabled_store);
+static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
+               overlay_global_alpha_show, overlay_global_alpha_store);
+static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
+               overlay_pre_mult_alpha_show,
+               overlay_pre_mult_alpha_store);
+static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
+               overlay_zorder_show, overlay_zorder_store);
+
+static struct attribute *overlay_sysfs_attrs[] = {
+       &overlay_attr_name.attr,
+       &overlay_attr_manager.attr,
+       &overlay_attr_input_size.attr,
+       &overlay_attr_screen_width.attr,
+       &overlay_attr_position.attr,
+       &overlay_attr_output_size.attr,
+       &overlay_attr_enabled.attr,
+       &overlay_attr_global_alpha.attr,
+       &overlay_attr_pre_mult_alpha.attr,
+       &overlay_attr_zorder.attr,
+       NULL
+};
+
+static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
+               char *buf)
+{
+       struct omap_overlay *overlay;
+       struct overlay_attribute *overlay_attr;
+
+       overlay = container_of(kobj, struct omap_overlay, kobj);
+       overlay_attr = container_of(attr, struct overlay_attribute, attr);
+
+       if (!overlay_attr->show)
+               return -ENOENT;
+
+       return overlay_attr->show(overlay, buf);
+}
+
+static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
+               const char *buf, size_t size)
+{
+       struct omap_overlay *overlay;
+       struct overlay_attribute *overlay_attr;
+
+       overlay = container_of(kobj, struct omap_overlay, kobj);
+       overlay_attr = container_of(attr, struct overlay_attribute, attr);
+
+       if (!overlay_attr->store)
+               return -ENOENT;
+
+       return overlay_attr->store(overlay, buf, size);
+}
+
+static const struct sysfs_ops overlay_sysfs_ops = {
+       .show = overlay_attr_show,
+       .store = overlay_attr_store,
+};
+
+static struct kobj_type overlay_ktype = {
+       .sysfs_ops = &overlay_sysfs_ops,
+       .default_attrs = overlay_sysfs_attrs,
+};
+
+int dss_overlay_kobj_init(struct omap_overlay *ovl,
+               struct platform_device *pdev)
+{
+       return kobject_init_and_add(&ovl->kobj, &overlay_ktype,
+                       &pdev->dev.kobj, "overlay%d", ovl->id);
+}
+
+void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
+{
+       kobject_del(&ovl->kobj);
+       kobject_put(&ovl->kobj);
+}
index 952c6fad9a8110393a3c2bdc15064aa4590e5367..45f4994bc6b06b64056db0cc9a7075532757bdc3 100644 (file)
 #include <linux/module.h>
 #include <linux/err.h>
 #include <linux/sysfs.h>
-#include <linux/kobject.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 
 #include <video/omapdss.h>
-#include <plat/cpu.h>
 
 #include "dss.h"
 #include "dss_features.h"
 static int num_overlays;
 static struct omap_overlay *overlays;
 
-static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
+static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
 {
-       return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
+       return ovl->manager ?
+               (ovl->manager->output ? ovl->manager->output->device : NULL) :
+               NULL;
 }
 
-static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%s\n",
-                       ovl->manager ? ovl->manager->name : "<none>");
-}
-
-static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
-               size_t size)
-{
-       int i, r;
-       struct omap_overlay_manager *mgr = NULL;
-       struct omap_overlay_manager *old_mgr;
-       int len = size;
-
-       if (buf[size-1] == '\n')
-               --len;
-
-       if (len > 0) {
-               for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
-                       mgr = omap_dss_get_overlay_manager(i);
-
-                       if (sysfs_streq(buf, mgr->name))
-                               break;
-
-                       mgr = NULL;
-               }
-       }
-
-       if (len > 0 && mgr == NULL)
-               return -EINVAL;
-
-       if (mgr)
-               DSSDBG("manager %s found\n", mgr->name);
-
-       if (mgr == ovl->manager)
-               return size;
-
-       old_mgr = ovl->manager;
-
-       r = dispc_runtime_get();
-       if (r)
-               return r;
-
-       /* detach old manager */
-       if (old_mgr) {
-               r = ovl->unset_manager(ovl);
-               if (r) {
-                       DSSERR("detach failed\n");
-                       goto err;
-               }
-
-               r = old_mgr->apply(old_mgr);
-               if (r)
-                       goto err;
-       }
-
-       if (mgr) {
-               r = ovl->set_manager(ovl, mgr);
-               if (r) {
-                       DSSERR("Failed to attach overlay\n");
-                       goto err;
-               }
-
-               r = mgr->apply(mgr);
-               if (r)
-                       goto err;
-       }
-
-       dispc_runtime_put();
-
-       return size;
-
-err:
-       dispc_runtime_put();
-       return r;
-}
-
-static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
-{
-       struct omap_overlay_info info;
-
-       ovl->get_overlay_info(ovl, &info);
-
-       return snprintf(buf, PAGE_SIZE, "%d,%d\n",
-                       info.width, info.height);
-}
-
-static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
-{
-       struct omap_overlay_info info;
-
-       ovl->get_overlay_info(ovl, &info);
-
-       return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
-}
-
-static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
-{
-       struct omap_overlay_info info;
-
-       ovl->get_overlay_info(ovl, &info);
-
-       return snprintf(buf, PAGE_SIZE, "%d,%d\n",
-                       info.pos_x, info.pos_y);
-}
-
-static ssize_t overlay_position_store(struct omap_overlay *ovl,
-               const char *buf, size_t size)
-{
-       int r;
-       char *last;
-       struct omap_overlay_info info;
-
-       ovl->get_overlay_info(ovl, &info);
-
-       info.pos_x = simple_strtoul(buf, &last, 10);
-       ++last;
-       if (last - buf >= size)
-               return -EINVAL;
-
-       info.pos_y = simple_strtoul(last, &last, 10);
-
-       r = ovl->set_overlay_info(ovl, &info);
-       if (r)
-               return r;
-
-       if (ovl->manager) {
-               r = ovl->manager->apply(ovl->manager);
-               if (r)
-                       return r;
-       }
-
-       return size;
-}
-
-static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
-{
-       struct omap_overlay_info info;
-
-       ovl->get_overlay_info(ovl, &info);
-
-       return snprintf(buf, PAGE_SIZE, "%d,%d\n",
-                       info.out_width, info.out_height);
-}
-
-static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
-               const char *buf, size_t size)
-{
-       int r;
-       char *last;
-       struct omap_overlay_info info;
-
-       ovl->get_overlay_info(ovl, &info);
-
-       info.out_width = simple_strtoul(buf, &last, 10);
-       ++last;
-       if (last - buf >= size)
-               return -EINVAL;
-
-       info.out_height = simple_strtoul(last, &last, 10);
-
-       r = ovl->set_overlay_info(ovl, &info);
-       if (r)
-               return r;
-
-       if (ovl->manager) {
-               r = ovl->manager->apply(ovl->manager);
-               if (r)
-                       return r;
-       }
-
-       return size;
-}
-
-static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
-}
-
-static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
-               size_t size)
-{
-       int r;
-       bool enable;
-
-       r = strtobool(buf, &enable);
-       if (r)
-               return r;
-
-       if (enable)
-               r = ovl->enable(ovl);
-       else
-               r = ovl->disable(ovl);
-
-       if (r)
-               return r;
-
-       return size;
-}
-
-static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
-{
-       struct omap_overlay_info info;
-
-       ovl->get_overlay_info(ovl, &info);
-
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-                       info.global_alpha);
-}
-
-static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
-               const char *buf, size_t size)
-{
-       int r;
-       u8 alpha;
-       struct omap_overlay_info info;
-
-       if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
-               return -ENODEV;
-
-       r = kstrtou8(buf, 0, &alpha);
-       if (r)
-               return r;
-
-       ovl->get_overlay_info(ovl, &info);
-
-       info.global_alpha = alpha;
-
-       r = ovl->set_overlay_info(ovl, &info);
-       if (r)
-               return r;
-
-       if (ovl->manager) {
-               r = ovl->manager->apply(ovl->manager);
-               if (r)
-                       return r;
-       }
-
-       return size;
-}
-
-static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
-               char *buf)
-{
-       struct omap_overlay_info info;
-
-       ovl->get_overlay_info(ovl, &info);
-
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-                       info.pre_mult_alpha);
-}
-
-static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
-               const char *buf, size_t size)
-{
-       int r;
-       u8 alpha;
-       struct omap_overlay_info info;
-
-       if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
-               return -ENODEV;
-
-       r = kstrtou8(buf, 0, &alpha);
-       if (r)
-               return r;
-
-       ovl->get_overlay_info(ovl, &info);
-
-       info.pre_mult_alpha = alpha;
-
-       r = ovl->set_overlay_info(ovl, &info);
-       if (r)
-               return r;
-
-       if (ovl->manager) {
-               r = ovl->manager->apply(ovl->manager);
-               if (r)
-                       return r;
-       }
-
-       return size;
-}
-
-static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
-{
-       struct omap_overlay_info info;
-
-       ovl->get_overlay_info(ovl, &info);
-
-       return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
-}
-
-static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
-               const char *buf, size_t size)
-{
-       int r;
-       u8 zorder;
-       struct omap_overlay_info info;
-
-       if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
-               return -ENODEV;
-
-       r = kstrtou8(buf, 0, &zorder);
-       if (r)
-               return r;
-
-       ovl->get_overlay_info(ovl, &info);
-
-       info.zorder = zorder;
-
-       r = ovl->set_overlay_info(ovl, &info);
-       if (r)
-               return r;
-
-       if (ovl->manager) {
-               r = ovl->manager->apply(ovl->manager);
-               if (r)
-                       return r;
-       }
-
-       return size;
-}
-
-struct overlay_attribute {
-       struct attribute attr;
-       ssize_t (*show)(struct omap_overlay *, char *);
-       ssize_t (*store)(struct omap_overlay *, const char *, size_t);
-};
-
-#define OVERLAY_ATTR(_name, _mode, _show, _store) \
-       struct overlay_attribute overlay_attr_##_name = \
-       __ATTR(_name, _mode, _show, _store)
-
-static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
-static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
-               overlay_manager_show, overlay_manager_store);
-static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
-static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
-static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
-               overlay_position_show, overlay_position_store);
-static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
-               overlay_output_size_show, overlay_output_size_store);
-static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
-               overlay_enabled_show, overlay_enabled_store);
-static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
-               overlay_global_alpha_show, overlay_global_alpha_store);
-static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
-               overlay_pre_mult_alpha_show,
-               overlay_pre_mult_alpha_store);
-static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
-               overlay_zorder_show, overlay_zorder_store);
-
-static struct attribute *overlay_sysfs_attrs[] = {
-       &overlay_attr_name.attr,
-       &overlay_attr_manager.attr,
-       &overlay_attr_input_size.attr,
-       &overlay_attr_screen_width.attr,
-       &overlay_attr_position.attr,
-       &overlay_attr_output_size.attr,
-       &overlay_attr_enabled.attr,
-       &overlay_attr_global_alpha.attr,
-       &overlay_attr_pre_mult_alpha.attr,
-       &overlay_attr_zorder.attr,
-       NULL
-};
-
-static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
-               char *buf)
-{
-       struct omap_overlay *overlay;
-       struct overlay_attribute *overlay_attr;
-
-       overlay = container_of(kobj, struct omap_overlay, kobj);
-       overlay_attr = container_of(attr, struct overlay_attribute, attr);
-
-       if (!overlay_attr->show)
-               return -ENOENT;
-
-       return overlay_attr->show(overlay, buf);
-}
-
-static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
-               const char *buf, size_t size)
-{
-       struct omap_overlay *overlay;
-       struct overlay_attribute *overlay_attr;
-
-       overlay = container_of(kobj, struct omap_overlay, kobj);
-       overlay_attr = container_of(attr, struct overlay_attribute, attr);
-
-       if (!overlay_attr->store)
-               return -ENOENT;
-
-       return overlay_attr->store(overlay, buf, size);
-}
-
-static const struct sysfs_ops overlay_sysfs_ops = {
-       .show = overlay_attr_show,
-       .store = overlay_attr_store,
-};
-
-static struct kobj_type overlay_ktype = {
-       .sysfs_ops = &overlay_sysfs_ops,
-       .default_attrs = overlay_sysfs_attrs,
-};
-
 int omap_dss_get_num_overlays(void)
 {
        return num_overlays;
@@ -507,97 +101,25 @@ void dss_init_overlays(struct platform_device *pdev)
                ovl->set_overlay_info = &dss_ovl_set_info;
                ovl->get_overlay_info = &dss_ovl_get_info;
                ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
+               ovl->get_device = &dss_ovl_get_device;
 
                ovl->caps = dss_feat_get_overlay_caps(ovl->id);
                ovl->supported_modes =
                        dss_feat_get_supported_color_modes(ovl->id);
 
-               r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
-                               &pdev->dev.kobj, "overlay%d", i);
-
+               r = dss_overlay_kobj_init(ovl, pdev);
                if (r)
                        DSSERR("failed to create sysfs file\n");
        }
 }
 
-/* connect overlays to the new device, if not already connected. if force
- * selected, connect always. */
-void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
-{
-       int i;
-       struct omap_overlay_manager *lcd_mgr;
-       struct omap_overlay_manager *tv_mgr;
-       struct omap_overlay_manager *lcd2_mgr = NULL;
-       struct omap_overlay_manager *lcd3_mgr = NULL;
-       struct omap_overlay_manager *mgr = NULL;
-
-       lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD);
-       tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_DIGIT);
-       if (dss_has_feature(FEAT_MGR_LCD3))
-               lcd3_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD3);
-       if (dss_has_feature(FEAT_MGR_LCD2))
-               lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD2);
-
-       if (dssdev->channel == OMAP_DSS_CHANNEL_LCD3) {
-               if (!lcd3_mgr->device || force) {
-                       if (lcd3_mgr->device)
-                               lcd3_mgr->unset_device(lcd3_mgr);
-                       lcd3_mgr->set_device(lcd3_mgr, dssdev);
-                       mgr = lcd3_mgr;
-               }
-       } else if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) {
-               if (!lcd2_mgr->device || force) {
-                       if (lcd2_mgr->device)
-                               lcd2_mgr->unset_device(lcd2_mgr);
-                       lcd2_mgr->set_device(lcd2_mgr, dssdev);
-                       mgr = lcd2_mgr;
-               }
-       } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC
-                       && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) {
-               if (!lcd_mgr->device || force) {
-                       if (lcd_mgr->device)
-                               lcd_mgr->unset_device(lcd_mgr);
-                       lcd_mgr->set_device(lcd_mgr, dssdev);
-                       mgr = lcd_mgr;
-               }
-       }
-
-       if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
-                       || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
-               if (!tv_mgr->device || force) {
-                       if (tv_mgr->device)
-                               tv_mgr->unset_device(tv_mgr);
-                       tv_mgr->set_device(tv_mgr, dssdev);
-                       mgr = tv_mgr;
-               }
-       }
-
-       if (mgr) {
-               dispc_runtime_get();
-
-               for (i = 0; i < dss_feat_get_num_ovls(); i++) {
-                       struct omap_overlay *ovl;
-                       ovl = omap_dss_get_overlay(i);
-                       if (!ovl->manager || force) {
-                               if (ovl->manager)
-                                       ovl->unset_manager(ovl);
-                               ovl->set_manager(ovl, mgr);
-                       }
-               }
-
-               dispc_runtime_put();
-       }
-}
-
 void dss_uninit_overlays(struct platform_device *pdev)
 {
        int i;
 
        for (i = 0; i < num_overlays; ++i) {
                struct omap_overlay *ovl = &overlays[i];
-
-               kobject_del(&ovl->kobj);
-               kobject_put(&ovl->kobj);
+               dss_overlay_kobj_uninit(ovl);
        }
 
        kfree(overlays);
index 7c087424b63428d33cd2bbb1560cb476dfefab38..7282e5af3e1a2e2458605c5a6f76b7d371269be3 100644 (file)
@@ -111,6 +111,13 @@ static struct {
        struct omap_dss_device *dssdev[2];
 
        struct semaphore bus_lock;
+
+       struct omap_video_timings timings;
+       int pixel_size;
+       int data_lines;
+       struct rfbi_timings intf_timings;
+
+       struct omap_dss_output output;
 } rfbi;
 
 static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
@@ -300,30 +307,23 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
 }
 EXPORT_SYMBOL(omap_rfbi_write_pixels);
 
-static int rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
-               u16 height, void (*callback)(void *data), void *data)
+static int rfbi_transfer_area(struct omap_dss_device *dssdev,
+               void (*callback)(void *data), void *data)
 {
        u32 l;
        int r;
-       struct omap_video_timings timings = {
-               .hsw            = 1,
-               .hfp            = 1,
-               .hbp            = 1,
-               .vsw            = 1,
-               .vfp            = 0,
-               .vbp            = 0,
-               .x_res          = width,
-               .y_res          = height,
-       };
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
+       u16 width = rfbi.timings.x_res;
+       u16 height = rfbi.timings.y_res;
 
        /*BUG_ON(callback == 0);*/
        BUG_ON(rfbi.framedone_callback != NULL);
 
        DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
 
-       dss_mgr_set_timings(dssdev->manager, &timings);
+       dss_mgr_set_timings(mgr, &rfbi.timings);
 
-       r = dss_mgr_enable(dssdev->manager);
+       r = dss_mgr_enable(mgr);
        if (r)
                return r;
 
@@ -770,62 +770,45 @@ static int rfbi_configure(int rfbi_module, int bpp, int lines)
        return 0;
 }
 
-int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size,
-               int data_lines)
+int omap_rfbi_configure(struct omap_dss_device *dssdev)
 {
-       return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines);
+       return rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
+                       rfbi.data_lines);
 }
 EXPORT_SYMBOL(omap_rfbi_configure);
 
-int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
-               u16 *x, u16 *y, u16 *w, u16 *h)
+int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
+               void *data)
 {
-       u16 dw, dh;
-       struct omap_video_timings timings = {
-               .hsw            = 1,
-               .hfp            = 1,
-               .hbp            = 1,
-               .vsw            = 1,
-               .vfp            = 0,
-               .vbp            = 0,
-               .x_res          = *w,
-               .y_res          = *h,
-       };
-
-       dssdev->driver->get_resolution(dssdev, &dw, &dh);
-
-       if  (*x > dw || *y > dh)
-               return -EINVAL;
-
-       if (*x + *w > dw)
-               return -EINVAL;
-
-       if (*y + *h > dh)
-               return -EINVAL;
-
-       if (*w == 1)
-               return -EINVAL;
-
-       if (*w == 0 || *h == 0)
-               return -EINVAL;
-
-       dss_mgr_set_timings(dssdev->manager, &timings);
+       return rfbi_transfer_area(dssdev, callback, data);
+}
+EXPORT_SYMBOL(omap_rfbi_update);
 
-       return 0;
+void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
+{
+       rfbi.timings.x_res = w;
+       rfbi.timings.y_res = h;
 }
-EXPORT_SYMBOL(omap_rfbi_prepare_update);
+EXPORT_SYMBOL(omapdss_rfbi_set_size);
 
-int omap_rfbi_update(struct omap_dss_device *dssdev,
-               u16 x, u16 y, u16 w, u16 h,
-               void (*callback)(void *), void *data)
+void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)
 {
-       int r;
+       rfbi.pixel_size = pixel_size;
+}
+EXPORT_SYMBOL(omapdss_rfbi_set_pixel_size);
 
-       r = rfbi_transfer_area(dssdev, w, h, callback, data);
+void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
+{
+       rfbi.data_lines = data_lines;
+}
+EXPORT_SYMBOL(omapdss_rfbi_set_data_lines);
 
-       return r;
+void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
+               struct rfbi_timings *timings)
+{
+       rfbi.intf_timings = *timings;
 }
-EXPORT_SYMBOL(omap_rfbi_update);
+EXPORT_SYMBOL(omapdss_rfbi_set_interface_timings);
 
 static void rfbi_dump_regs(struct seq_file *s)
 {
@@ -869,6 +852,7 @@ static void rfbi_dump_regs(struct seq_file *s)
 
 static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
 {
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
        struct dss_lcd_mgr_config mgr_config;
 
        mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI;
@@ -877,18 +861,40 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
        /* Do we need fifohandcheck for RFBI? */
        mgr_config.fifohandcheck = false;
 
-       mgr_config.video_port_width = dssdev->ctrl.pixel_size;
+       mgr_config.video_port_width = rfbi.pixel_size;
        mgr_config.lcden_sig_polarity = 0;
 
-       dss_mgr_set_lcd_config(dssdev->manager, &mgr_config);
+       dss_mgr_set_lcd_config(mgr, &mgr_config);
+
+       /*
+        * Set rfbi.timings with default values, the x_res and y_res fields
+        * are expected to be already configured by the panel driver via
+        * omapdss_rfbi_set_size()
+        */
+       rfbi.timings.hsw = 1;
+       rfbi.timings.hfp = 1;
+       rfbi.timings.hbp = 1;
+       rfbi.timings.vsw = 1;
+       rfbi.timings.vfp = 0;
+       rfbi.timings.vbp = 0;
+
+       rfbi.timings.interlace = false;
+       rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+       rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
+
+       dss_mgr_set_timings(mgr, &rfbi.timings);
 }
 
 int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
 {
+       struct omap_dss_output *out = dssdev->output;
        int r;
 
-       if (dssdev->manager == NULL) {
-               DSSERR("failed to enable display: no manager\n");
+       if (out == NULL || out->manager == NULL) {
+               DSSERR("failed to enable display: no output/manager\n");
                return -ENODEV;
        }
 
@@ -911,13 +917,10 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
 
        rfbi_config_lcd_manager(dssdev);
 
-       rfbi_configure(dssdev->phy.rfbi.channel,
-                              dssdev->ctrl.pixel_size,
-                              dssdev->phy.rfbi.data_lines);
-
-       rfbi_set_timings(dssdev->phy.rfbi.channel,
-                        &dssdev->ctrl.rfbi_timings);
+       rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
+                       rfbi.data_lines);
 
+       rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings);
 
        return 0;
 err1:
@@ -941,14 +944,17 @@ EXPORT_SYMBOL(omapdss_rfbi_display_disable);
 static int __init rfbi_init_display(struct omap_dss_device *dssdev)
 {
        rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
-       dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
        return 0;
 }
 
-static void __init rfbi_probe_pdata(struct platform_device *pdev)
+static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
 {
        struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-       int i, r;
+       const char *def_disp_name = dss_get_default_display_name();
+       struct omap_dss_device *def_dssdev;
+       int i;
+
+       def_dssdev = NULL;
 
        for (i = 0; i < pdata->num_devices; ++i) {
                struct omap_dss_device *dssdev = pdata->devices[i];
@@ -956,17 +962,67 @@ static void __init rfbi_probe_pdata(struct platform_device *pdev)
                if (dssdev->type != OMAP_DISPLAY_TYPE_DBI)
                        continue;
 
-               r = rfbi_init_display(dssdev);
-               if (r) {
-                       DSSERR("device %s init failed: %d\n", dssdev->name, r);
-                       continue;
+               if (def_dssdev == NULL)
+                       def_dssdev = dssdev;
+
+               if (def_disp_name != NULL &&
+                               strcmp(dssdev->name, def_disp_name) == 0) {
+                       def_dssdev = dssdev;
+                       break;
                }
+       }
+
+       return def_dssdev;
+}
+
+static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
+{
+       struct omap_dss_device *plat_dssdev;
+       struct omap_dss_device *dssdev;
+       int r;
+
+       plat_dssdev = rfbi_find_dssdev(rfbidev);
+
+       if (!plat_dssdev)
+               return;
+
+       dssdev = dss_alloc_and_init_device(&rfbidev->dev);
+       if (!dssdev)
+               return;
+
+       dss_copy_device_pdata(dssdev, plat_dssdev);
 
-               r = omap_dss_register_device(dssdev, &pdev->dev, i);
-               if (r)
-                       DSSERR("device %s register failed: %d\n",
-                               dssdev->name, r);
+       r = rfbi_init_display(dssdev);
+       if (r) {
+               DSSERR("device %s init failed: %d\n", dssdev->name, r);
+               dss_put_device(dssdev);
+               return;
        }
+
+       r = dss_add_device(dssdev);
+       if (r) {
+               DSSERR("device %s register failed: %d\n", dssdev->name, r);
+               dss_put_device(dssdev);
+               return;
+       }
+}
+
+static void __init rfbi_init_output(struct platform_device *pdev)
+{
+       struct omap_dss_output *out = &rfbi.output;
+
+       out->pdev = pdev;
+       out->id = OMAP_DSS_OUTPUT_DBI;
+       out->type = OMAP_DISPLAY_TYPE_DBI;
+
+       dss_register_output(out);
+}
+
+static void __exit rfbi_uninit_output(struct platform_device *pdev)
+{
+       struct omap_dss_output *out = &rfbi.output;
+
+       dss_unregister_output(out);
 }
 
 /* RFBI HW IP initialisation */
@@ -1020,6 +1076,8 @@ static int __init omap_rfbihw_probe(struct platform_device *pdev)
 
        dss_debugfs_create_file("rfbi", rfbi_dump_regs);
 
+       rfbi_init_output(pdev);
+
        rfbi_probe_pdata(pdev);
 
        return 0;
@@ -1031,8 +1089,12 @@ err_runtime_get:
 
 static int __exit omap_rfbihw_remove(struct platform_device *pdev)
 {
-       omap_dss_unregister_child_devices(&pdev->dev);
+       dss_unregister_child_devices(&pdev->dev);
+
+       rfbi_uninit_output(pdev);
+
        pm_runtime_disable(&pdev->dev);
+
        return 0;
 }
 
index f43bfe17b3b699289152cb9ff195afcb69f137f2..7760851f6e5d5ad5dc9adcc3b540ee4f2f5301d2 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/export.h>
 #include <linux/platform_device.h>
+#include <linux/string.h>
 
 #include <video/omapdss.h>
 #include "dss.h"
@@ -34,10 +35,16 @@ static struct {
        struct regulator *vdds_sdi_reg;
 
        struct dss_lcd_mgr_config mgr_config;
+       struct omap_video_timings timings;
+       int datapairs;
+
+       struct omap_dss_output output;
 } sdi;
 
 static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
 {
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
+
        sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
 
        sdi.mgr_config.stallmode = false;
@@ -46,19 +53,20 @@ static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
        sdi.mgr_config.video_port_width = 24;
        sdi.mgr_config.lcden_sig_polarity = 1;
 
-       dss_mgr_set_lcd_config(dssdev->manager, &sdi.mgr_config);
+       dss_mgr_set_lcd_config(mgr, &sdi.mgr_config);
 }
 
 int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 {
-       struct omap_video_timings *t = &dssdev->panel.timings;
+       struct omap_dss_output *out = dssdev->output;
+       struct omap_video_timings *t = &sdi.timings;
        struct dss_clock_info dss_cinfo;
        struct dispc_clock_info dispc_cinfo;
        unsigned long pck;
        int r;
 
-       if (dssdev->manager == NULL) {
-               DSSERR("failed to enable display: no manager\n");
+       if (out == NULL || out->manager == NULL) {
+               DSSERR("failed to enable display: no output/manager\n");
                return -ENODEV;
        }
 
@@ -77,8 +85,8 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
                goto err_get_dispc;
 
        /* 15.5.9.1.2 */
-       dssdev->panel.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-       dssdev->panel.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+       t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+       t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
 
        r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
        if (r)
@@ -97,7 +105,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
        }
 
 
-       dss_mgr_set_timings(dssdev->manager, t);
+       dss_mgr_set_timings(out->manager, t);
 
        r = dss_set_clock_div(&dss_cinfo);
        if (r)
@@ -116,16 +124,15 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
         * need to care about the shadow register mechanism for pck-free. The
         * exact reason for this is unknown.
         */
-       dispc_mgr_set_clock_div(dssdev->manager->id,
-                       &sdi.mgr_config.clock_info);
+       dispc_mgr_set_clock_div(out->manager->id, &sdi.mgr_config.clock_info);
 
-       dss_sdi_init(dssdev->phy.sdi.datapairs);
+       dss_sdi_init(sdi.datapairs);
        r = dss_sdi_enable();
        if (r)
                goto err_sdi_enable;
        mdelay(2);
 
-       r = dss_mgr_enable(dssdev->manager);
+       r = dss_mgr_enable(out->manager);
        if (r)
                goto err_mgr_enable;
 
@@ -148,7 +155,9 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable);
 
 void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
 {
-       dss_mgr_disable(dssdev->manager);
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
+
+       dss_mgr_disable(mgr);
 
        dss_sdi_disable();
 
@@ -160,6 +169,19 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
 }
 EXPORT_SYMBOL(omapdss_sdi_display_disable);
 
+void omapdss_sdi_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       sdi.timings = *timings;
+}
+EXPORT_SYMBOL(omapdss_sdi_set_timings);
+
+void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
+{
+       sdi.datapairs = datapairs;
+}
+EXPORT_SYMBOL(omapdss_sdi_set_datapairs);
+
 static int __init sdi_init_display(struct omap_dss_device *dssdev)
 {
        DSSDBG("SDI init\n");
@@ -180,10 +202,14 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)
        return 0;
 }
 
-static void __init sdi_probe_pdata(struct platform_device *pdev)
+static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)
 {
        struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-       int i, r;
+       const char *def_disp_name = dss_get_default_display_name();
+       struct omap_dss_device *def_dssdev;
+       int i;
+
+       def_dssdev = NULL;
 
        for (i = 0; i < pdata->num_devices; ++i) {
                struct omap_dss_device *dssdev = pdata->devices[i];
@@ -191,21 +217,73 @@ static void __init sdi_probe_pdata(struct platform_device *pdev)
                if (dssdev->type != OMAP_DISPLAY_TYPE_SDI)
                        continue;
 
-               r = sdi_init_display(dssdev);
-               if (r) {
-                       DSSERR("device %s init failed: %d\n", dssdev->name, r);
-                       continue;
+               if (def_dssdev == NULL)
+                       def_dssdev = dssdev;
+
+               if (def_disp_name != NULL &&
+                               strcmp(dssdev->name, def_disp_name) == 0) {
+                       def_dssdev = dssdev;
+                       break;
                }
+       }
+
+       return def_dssdev;
+}
+
+static void __init sdi_probe_pdata(struct platform_device *sdidev)
+{
+       struct omap_dss_device *plat_dssdev;
+       struct omap_dss_device *dssdev;
+       int r;
+
+       plat_dssdev = sdi_find_dssdev(sdidev);
 
-               r = omap_dss_register_device(dssdev, &pdev->dev, i);
-               if (r)
-                       DSSERR("device %s register failed: %d\n",
-                                       dssdev->name, r);
+       if (!plat_dssdev)
+               return;
+
+       dssdev = dss_alloc_and_init_device(&sdidev->dev);
+       if (!dssdev)
+               return;
+
+       dss_copy_device_pdata(dssdev, plat_dssdev);
+
+       r = sdi_init_display(dssdev);
+       if (r) {
+               DSSERR("device %s init failed: %d\n", dssdev->name, r);
+               dss_put_device(dssdev);
+               return;
        }
+
+       r = dss_add_device(dssdev);
+       if (r) {
+               DSSERR("device %s register failed: %d\n", dssdev->name, r);
+               dss_put_device(dssdev);
+               return;
+       }
+}
+
+static void __init sdi_init_output(struct platform_device *pdev)
+{
+       struct omap_dss_output *out = &sdi.output;
+
+       out->pdev = pdev;
+       out->id = OMAP_DSS_OUTPUT_SDI;
+       out->type = OMAP_DISPLAY_TYPE_SDI;
+
+       dss_register_output(out);
+}
+
+static void __exit sdi_uninit_output(struct platform_device *pdev)
+{
+       struct omap_dss_output *out = &sdi.output;
+
+       dss_unregister_output(out);
 }
 
 static int __init omap_sdi_probe(struct platform_device *pdev)
 {
+       sdi_init_output(pdev);
+
        sdi_probe_pdata(pdev);
 
        return 0;
@@ -213,7 +291,9 @@ static int __init omap_sdi_probe(struct platform_device *pdev)
 
 static int __exit omap_sdi_remove(struct platform_device *pdev)
 {
-       omap_dss_unregister_child_devices(&pdev->dev);
+       dss_unregister_child_devices(&pdev->dev);
+
+       sdi_uninit_output(pdev);
 
        return 0;
 }
index 3a220877461ac9adbf3ab62369e9d10a7476a952..56efa3bb465d1ef4dd8011b89ead18ae36e41e03 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
-#include <plat/cpu.h>
 
 #include "dss.h"
 #include "dss_features.h"
@@ -300,6 +299,12 @@ static struct {
        struct regulator *vdda_dac_reg;
 
        struct clk      *tv_dac_clk;
+
+       struct omap_video_timings timings;
+       enum omap_dss_venc_type type;
+       bool invert_polarity;
+
+       struct omap_dss_output output;
 } venc;
 
 static inline void venc_write_reg(int idx, u32 val)
@@ -424,65 +429,67 @@ static const struct venc_config *venc_timings_to_config(
 
 static int venc_power_on(struct omap_dss_device *dssdev)
 {
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
        u32 l;
        int r;
 
+       r = venc_runtime_get();
+       if (r)
+               goto err0;
+
        venc_reset();
-       venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
+       venc_write_config(venc_timings_to_config(&venc.timings));
 
-       dss_set_venc_output(dssdev->phy.venc.type);
+       dss_set_venc_output(venc.type);
        dss_set_dac_pwrdn_bgz(1);
 
        l = 0;
 
-       if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
+       if (venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
                l |= 1 << 1;
        else /* S-Video */
                l |= (1 << 0) | (1 << 2);
 
-       if (dssdev->phy.venc.invert_polarity == false)
+       if (venc.invert_polarity == false)
                l |= 1 << 3;
 
        venc_write_reg(VENC_OUTPUT_CONTROL, l);
 
-       dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
+       dss_mgr_set_timings(mgr, &venc.timings);
 
        r = regulator_enable(venc.vdda_dac_reg);
        if (r)
-               goto err;
-
-       if (dssdev->platform_enable)
-               dssdev->platform_enable(dssdev);
+               goto err1;
 
-       r = dss_mgr_enable(dssdev->manager);
+       r = dss_mgr_enable(mgr);
        if (r)
-               goto err;
+               goto err2;
 
        return 0;
 
-err:
+err2:
+       regulator_disable(venc.vdda_dac_reg);
+err1:
        venc_write_reg(VENC_OUTPUT_CONTROL, 0);
        dss_set_dac_pwrdn_bgz(0);
 
-       if (dssdev->platform_disable)
-               dssdev->platform_disable(dssdev);
-
-       regulator_disable(venc.vdda_dac_reg);
-
+       venc_runtime_put();
+err0:
        return r;
 }
 
 static void venc_power_off(struct omap_dss_device *dssdev)
 {
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
+
        venc_write_reg(VENC_OUTPUT_CONTROL, 0);
        dss_set_dac_pwrdn_bgz(0);
 
-       dss_mgr_disable(dssdev->manager);
-
-       if (dssdev->platform_disable)
-               dssdev->platform_disable(dssdev);
+       dss_mgr_disable(mgr);
 
        regulator_disable(venc.vdda_dac_reg);
+
+       venc_runtime_put();
 }
 
 unsigned long venc_get_pixel_clock(void)
@@ -491,171 +498,83 @@ unsigned long venc_get_pixel_clock(void)
        return 13500000;
 }
 
-static ssize_t display_output_type_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
+int omapdss_venc_display_enable(struct omap_dss_device *dssdev)
 {
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       const char *ret;
-
-       switch (dssdev->phy.venc.type) {
-       case OMAP_DSS_VENC_TYPE_COMPOSITE:
-               ret = "composite";
-               break;
-       case OMAP_DSS_VENC_TYPE_SVIDEO:
-               ret = "svideo";
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return snprintf(buf, PAGE_SIZE, "%s\n", ret);
-}
+       struct omap_dss_output *out = dssdev->output;
+       int r;
 
-static ssize_t display_output_type_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t size)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       enum omap_dss_venc_type new_type;
-
-       if (sysfs_streq("composite", buf))
-               new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
-       else if (sysfs_streq("svideo", buf))
-               new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
-       else
-               return -EINVAL;
+       DSSDBG("venc_display_enable\n");
 
        mutex_lock(&venc.venc_lock);
 
-       if (dssdev->phy.venc.type != new_type) {
-               dssdev->phy.venc.type = new_type;
-               if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
-                       venc_power_off(dssdev);
-                       venc_power_on(dssdev);
-               }
+       if (out == NULL || out->manager == NULL) {
+               DSSERR("Failed to enable display: no output/manager\n");
+               r = -ENODEV;
+               goto err0;
        }
 
-       mutex_unlock(&venc.venc_lock);
-
-       return size;
-}
-
-static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
-               display_output_type_show, display_output_type_store);
-
-/* driver */
-static int venc_panel_probe(struct omap_dss_device *dssdev)
-{
-       dssdev->panel.timings = omap_dss_pal_timings;
-
-       return device_create_file(&dssdev->dev, &dev_attr_output_type);
-}
-
-static void venc_panel_remove(struct omap_dss_device *dssdev)
-{
-       device_remove_file(&dssdev->dev, &dev_attr_output_type);
-}
-
-static int venc_panel_enable(struct omap_dss_device *dssdev)
-{
-       int r = 0;
-
-       DSSDBG("venc_enable_display\n");
-
-       mutex_lock(&venc.venc_lock);
-
        r = omap_dss_start_device(dssdev);
        if (r) {
                DSSERR("failed to start device\n");
                goto err0;
        }
 
-       if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
-               r = -EINVAL;
-               goto err1;
-       }
+       if (dssdev->platform_enable)
+               dssdev->platform_enable(dssdev);
 
-       r = venc_runtime_get();
-       if (r)
-               goto err1;
 
        r = venc_power_on(dssdev);
        if (r)
-               goto err2;
+               goto err1;
 
        venc.wss_data = 0;
 
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
        mutex_unlock(&venc.venc_lock);
+
        return 0;
-err2:
-       venc_runtime_put();
 err1:
+       if (dssdev->platform_disable)
+               dssdev->platform_disable(dssdev);
        omap_dss_stop_device(dssdev);
 err0:
        mutex_unlock(&venc.venc_lock);
-
        return r;
 }
 
-static void venc_panel_disable(struct omap_dss_device *dssdev)
+void omapdss_venc_display_disable(struct omap_dss_device *dssdev)
 {
-       DSSDBG("venc_disable_display\n");
+       DSSDBG("venc_display_disable\n");
 
        mutex_lock(&venc.venc_lock);
 
-       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
-               goto end;
-
-       if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
-               /* suspended is the same as disabled with venc */
-               dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-               goto end;
-       }
-
        venc_power_off(dssdev);
 
-       venc_runtime_put();
-
-       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-
        omap_dss_stop_device(dssdev);
-end:
-       mutex_unlock(&venc.venc_lock);
-}
 
-static int venc_panel_suspend(struct omap_dss_device *dssdev)
-{
-       venc_panel_disable(dssdev);
-       return 0;
-}
+       if (dssdev->platform_disable)
+               dssdev->platform_disable(dssdev);
 
-static int venc_panel_resume(struct omap_dss_device *dssdev)
-{
-       return venc_panel_enable(dssdev);
+       mutex_unlock(&venc.venc_lock);
 }
 
-static void venc_set_timings(struct omap_dss_device *dssdev,
-                       struct omap_video_timings *timings)
+void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
 {
        DSSDBG("venc_set_timings\n");
 
+       mutex_lock(&venc.venc_lock);
+
        /* Reset WSS data when the TV standard changes. */
-       if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings)))
+       if (memcmp(&venc.timings, timings, sizeof(*timings)))
                venc.wss_data = 0;
 
-       dssdev->panel.timings = *timings;
-       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
-               /* turn the venc off and on to get new timings to use */
-               venc_panel_disable(dssdev);
-               venc_panel_enable(dssdev);
-       } else {
-               dss_mgr_set_timings(dssdev->manager, timings);
-       }
+       venc.timings = *timings;
+
+       mutex_unlock(&venc.venc_lock);
 }
 
-static int venc_check_timings(struct omap_dss_device *dssdev,
-                       struct omap_video_timings *timings)
+int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
 {
        DSSDBG("venc_check_timings\n");
 
@@ -668,13 +587,13 @@ static int venc_check_timings(struct omap_dss_device *dssdev,
        return -EINVAL;
 }
 
-static u32 venc_get_wss(struct omap_dss_device *dssdev)
+u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev)
 {
        /* Invert due to VENC_L21_WC_CTL:INV=1 */
        return (venc.wss_data >> 8) ^ 0xfffff;
 }
 
-static int venc_set_wss(struct omap_dss_device *dssdev,        u32 wss)
+int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
 {
        const struct venc_config *config;
        int r;
@@ -683,7 +602,7 @@ static int venc_set_wss(struct omap_dss_device *dssdev,     u32 wss)
 
        mutex_lock(&venc.venc_lock);
 
-       config = venc_timings_to_config(&dssdev->panel.timings);
+       config = venc_timings_to_config(&venc.timings);
 
        /* Invert due to VENC_L21_WC_CTL:INV=1 */
        venc.wss_data = (wss ^ 0xfffff) << 8;
@@ -703,30 +622,25 @@ err:
        return r;
 }
 
-static struct omap_dss_driver venc_driver = {
-       .probe          = venc_panel_probe,
-       .remove         = venc_panel_remove,
+void omapdss_venc_set_type(struct omap_dss_device *dssdev,
+               enum omap_dss_venc_type type)
+{
+       mutex_lock(&venc.venc_lock);
 
-       .enable         = venc_panel_enable,
-       .disable        = venc_panel_disable,
-       .suspend        = venc_panel_suspend,
-       .resume         = venc_panel_resume,
+       venc.type = type;
 
-       .get_resolution = omapdss_default_get_resolution,
-       .get_recommended_bpp = omapdss_default_get_recommended_bpp,
+       mutex_unlock(&venc.venc_lock);
+}
 
-       .set_timings    = venc_set_timings,
-       .check_timings  = venc_check_timings,
+void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
+               bool invert_polarity)
+{
+       mutex_lock(&venc.venc_lock);
 
-       .get_wss        = venc_get_wss,
-       .set_wss        = venc_set_wss,
+       venc.invert_polarity = invert_polarity;
 
-       .driver         = {
-               .name   = "venc",
-               .owner  = THIS_MODULE,
-       },
-};
-/* driver end */
+       mutex_unlock(&venc.venc_lock);
+}
 
 static int __init venc_init_display(struct omap_dss_device *dssdev)
 {
@@ -752,11 +666,6 @@ static void venc_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
 
-       if (cpu_is_omap44xx()) {
-               seq_printf(s, "VENC currently disabled on OMAP44xx\n");
-               return;
-       }
-
        if (venc_runtime_get())
                return;
 
@@ -832,10 +741,14 @@ static void venc_put_clocks(void)
                clk_put(venc.tv_dac_clk);
 }
 
-static void __init venc_probe_pdata(struct platform_device *pdev)
+static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
 {
        struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-       int r, i;
+       const char *def_disp_name = dss_get_default_display_name();
+       struct omap_dss_device *def_dssdev;
+       int i;
+
+       def_dssdev = NULL;
 
        for (i = 0; i < pdata->num_devices; ++i) {
                struct omap_dss_device *dssdev = pdata->devices[i];
@@ -843,17 +756,69 @@ static void __init venc_probe_pdata(struct platform_device *pdev)
                if (dssdev->type != OMAP_DISPLAY_TYPE_VENC)
                        continue;
 
-               r = venc_init_display(dssdev);
-               if (r) {
-                       DSSERR("device %s init failed: %d\n", dssdev->name, r);
-                       continue;
+               if (def_dssdev == NULL)
+                       def_dssdev = dssdev;
+
+               if (def_disp_name != NULL &&
+                               strcmp(dssdev->name, def_disp_name) == 0) {
+                       def_dssdev = dssdev;
+                       break;
                }
+       }
+
+       return def_dssdev;
+}
+
+static void __init venc_probe_pdata(struct platform_device *vencdev)
+{
+       struct omap_dss_device *plat_dssdev;
+       struct omap_dss_device *dssdev;
+       int r;
+
+       plat_dssdev = venc_find_dssdev(vencdev);
 
-               r = omap_dss_register_device(dssdev, &pdev->dev, i);
-               if (r)
-                       DSSERR("device %s register failed: %d\n",
-                                       dssdev->name, r);
+       if (!plat_dssdev)
+               return;
+
+       dssdev = dss_alloc_and_init_device(&vencdev->dev);
+       if (!dssdev)
+               return;
+
+       dss_copy_device_pdata(dssdev, plat_dssdev);
+
+       dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
+
+       r = venc_init_display(dssdev);
+       if (r) {
+               DSSERR("device %s init failed: %d\n", dssdev->name, r);
+               dss_put_device(dssdev);
+               return;
        }
+
+       r = dss_add_device(dssdev);
+       if (r) {
+               DSSERR("device %s register failed: %d\n", dssdev->name, r);
+               dss_put_device(dssdev);
+               return;
+       }
+}
+
+static void __init venc_init_output(struct platform_device *pdev)
+{
+       struct omap_dss_output *out = &venc.output;
+
+       out->pdev = pdev;
+       out->id = OMAP_DSS_OUTPUT_VENC;
+       out->type = OMAP_DISPLAY_TYPE_VENC;
+
+       dss_register_output(out);
+}
+
+static void __exit venc_uninit_output(struct platform_device *pdev)
+{
+       struct omap_dss_output *out = &venc.output;
+
+       dss_unregister_output(out);
 }
 
 /* VENC HW IP initialisation */
@@ -897,17 +862,19 @@ static int __init omap_venchw_probe(struct platform_device *pdev)
 
        venc_runtime_put();
 
-       r = omap_dss_register_driver(&venc_driver);
+       r = venc_panel_init();
        if (r)
-               goto err_reg_panel_driver;
+               goto err_panel_init;
 
        dss_debugfs_create_file("venc", venc_dump_regs);
 
+       venc_init_output(pdev);
+
        venc_probe_pdata(pdev);
 
        return 0;
 
-err_reg_panel_driver:
+err_panel_init:
 err_runtime_get:
        pm_runtime_disable(&pdev->dev);
        venc_put_clocks();
@@ -916,14 +883,16 @@ err_runtime_get:
 
 static int __exit omap_venchw_remove(struct platform_device *pdev)
 {
-       omap_dss_unregister_child_devices(&pdev->dev);
+       dss_unregister_child_devices(&pdev->dev);
 
        if (venc.vdda_dac_reg != NULL) {
                regulator_put(venc.vdda_dac_reg);
                venc.vdda_dac_reg = NULL;
        }
 
-       omap_dss_unregister_driver(&venc_driver);
+       venc_panel_exit();
+
+       venc_uninit_output(pdev);
 
        pm_runtime_disable(&pdev->dev);
        venc_put_clocks();
@@ -971,16 +940,10 @@ static struct platform_driver omap_venchw_driver = {
 
 int __init venc_init_platform_driver(void)
 {
-       if (cpu_is_omap44xx())
-               return 0;
-
        return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe);
 }
 
 void __exit venc_uninit_platform_driver(void)
 {
-       if (cpu_is_omap44xx())
-               return;
-
        platform_driver_unregister(&omap_venchw_driver);
 }
diff --git a/drivers/video/omap2/dss/venc_panel.c b/drivers/video/omap2/dss/venc_panel.c
new file mode 100644 (file)
index 0000000..d55b878
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * VENC panel driver
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+
+static struct {
+       struct mutex lock;
+} venc_panel;
+
+static ssize_t display_output_type_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       const char *ret;
+
+       switch (dssdev->phy.venc.type) {
+       case OMAP_DSS_VENC_TYPE_COMPOSITE:
+               ret = "composite";
+               break;
+       case OMAP_DSS_VENC_TYPE_SVIDEO:
+               ret = "svideo";
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return snprintf(buf, PAGE_SIZE, "%s\n", ret);
+}
+
+static ssize_t display_output_type_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t size)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       enum omap_dss_venc_type new_type;
+
+       if (sysfs_streq("composite", buf))
+               new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
+       else if (sysfs_streq("svideo", buf))
+               new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
+       else
+               return -EINVAL;
+
+       mutex_lock(&venc_panel.lock);
+
+       if (dssdev->phy.venc.type != new_type) {
+               dssdev->phy.venc.type = new_type;
+               omapdss_venc_set_type(dssdev, new_type);
+               if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+                       omapdss_venc_display_disable(dssdev);
+                       omapdss_venc_display_enable(dssdev);
+               }
+       }
+
+       mutex_unlock(&venc_panel.lock);
+
+       return size;
+}
+
+static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
+               display_output_type_show, display_output_type_store);
+
+static int venc_panel_probe(struct omap_dss_device *dssdev)
+{
+       /* set default timings to PAL */
+       const struct omap_video_timings default_timings = {
+               .x_res          = 720,
+               .y_res          = 574,
+               .pixel_clock    = 13500,
+               .hsw            = 64,
+               .hfp            = 12,
+               .hbp            = 68,
+               .vsw            = 5,
+               .vfp            = 5,
+               .vbp            = 41,
+
+               .vsync_level    = OMAPDSS_SIG_ACTIVE_HIGH,
+               .hsync_level    = OMAPDSS_SIG_ACTIVE_HIGH,
+
+               .interlace      = true,
+       };
+
+       mutex_init(&venc_panel.lock);
+
+       dssdev->panel.timings = default_timings;
+
+       return device_create_file(&dssdev->dev, &dev_attr_output_type);
+}
+
+static void venc_panel_remove(struct omap_dss_device *dssdev)
+{
+       device_remove_file(&dssdev->dev, &dev_attr_output_type);
+}
+
+static int venc_panel_enable(struct omap_dss_device *dssdev)
+{
+       int r;
+
+       dev_dbg(&dssdev->dev, "venc_panel_enable\n");
+
+       mutex_lock(&venc_panel.lock);
+
+       if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
+               r = -EINVAL;
+               goto err;
+       }
+
+       omapdss_venc_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_venc_set_type(dssdev, dssdev->phy.venc.type);
+       omapdss_venc_invert_vid_out_polarity(dssdev,
+               dssdev->phy.venc.invert_polarity);
+
+       r = omapdss_venc_display_enable(dssdev);
+       if (r)
+               goto err;
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       mutex_unlock(&venc_panel.lock);
+
+       return 0;
+err:
+       mutex_unlock(&venc_panel.lock);
+
+       return r;
+}
+
+static void venc_panel_disable(struct omap_dss_device *dssdev)
+{
+       dev_dbg(&dssdev->dev, "venc_panel_disable\n");
+
+       mutex_lock(&venc_panel.lock);
+
+       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
+               goto end;
+
+       if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
+               /* suspended is the same as disabled with venc */
+               dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+               goto end;
+       }
+
+       omapdss_venc_display_disable(dssdev);
+
+       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+end:
+       mutex_unlock(&venc_panel.lock);
+}
+
+static int venc_panel_suspend(struct omap_dss_device *dssdev)
+{
+       venc_panel_disable(dssdev);
+       return 0;
+}
+
+static int venc_panel_resume(struct omap_dss_device *dssdev)
+{
+       return venc_panel_enable(dssdev);
+}
+
+static void venc_panel_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       dev_dbg(&dssdev->dev, "venc_panel_set_timings\n");
+
+       mutex_lock(&venc_panel.lock);
+
+       omapdss_venc_set_timings(dssdev, timings);
+       dssdev->panel.timings = *timings;
+
+       mutex_unlock(&venc_panel.lock);
+}
+
+static int venc_panel_check_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       dev_dbg(&dssdev->dev, "venc_panel_check_timings\n");
+
+       return omapdss_venc_check_timings(dssdev, timings);
+}
+
+static u32 venc_panel_get_wss(struct omap_dss_device *dssdev)
+{
+       dev_dbg(&dssdev->dev, "venc_panel_get_wss\n");
+
+       return omapdss_venc_get_wss(dssdev);
+}
+
+static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss)
+{
+       dev_dbg(&dssdev->dev, "venc_panel_set_wss\n");
+
+       return omapdss_venc_set_wss(dssdev, wss);
+}
+
+static struct omap_dss_driver venc_driver = {
+       .probe          = venc_panel_probe,
+       .remove         = venc_panel_remove,
+
+       .enable         = venc_panel_enable,
+       .disable        = venc_panel_disable,
+       .suspend        = venc_panel_suspend,
+       .resume         = venc_panel_resume,
+
+       .get_resolution = omapdss_default_get_resolution,
+       .get_recommended_bpp = omapdss_default_get_recommended_bpp,
+
+       .set_timings    = venc_panel_set_timings,
+       .check_timings  = venc_panel_check_timings,
+
+       .get_wss        = venc_panel_get_wss,
+       .set_wss        = venc_panel_set_wss,
+
+       .driver         = {
+               .name   = "venc",
+               .owner  = THIS_MODULE,
+       },
+};
+
+int venc_panel_init(void)
+{
+       return omap_dss_register_driver(&venc_driver);
+}
+
+void venc_panel_exit(void)
+{
+       omap_dss_unregister_driver(&venc_driver);
+}
index c6cf372d22c58b9941051c67028df365e178657f..606b89f12351d4e1cc2cb234fd4e5c481bf82cda 100644 (file)
@@ -599,6 +599,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
        struct omapfb_info *ofbi = FB2OFB(fbi);
        struct omapfb2_device *fbdev = ofbi->fbdev;
        struct omap_dss_device *display = fb2display(fbi);
+       struct omap_overlay_manager *mgr;
 
        union {
                struct omapfb_update_window_old uwnd_o;
@@ -786,12 +787,14 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
 
        case OMAPFB_WAITFORVSYNC:
                DBG("ioctl WAITFORVSYNC\n");
-               if (!display) {
+               if (!display && !display->output && !display->output->manager) {
                        r = -EINVAL;
                        break;
                }
 
-               r = display->manager->wait_for_vsync(display->manager);
+               mgr = display->output->manager;
+
+               r = mgr->wait_for_vsync(mgr);
                break;
 
        case OMAPFB_WAITFORGO:
index 15373f4aee1976435b5f6d94d48b1f824ab718a2..16db1589bd9180a01920078f156b3650971b2311 100644 (file)
@@ -1593,6 +1593,20 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
        return 0;
 }
 
+static void omapfb_clear_fb(struct fb_info *fbi)
+{
+       const struct fb_fillrect rect = {
+               .dx = 0,
+               .dy = 0,
+               .width = fbi->var.xres_virtual,
+               .height = fbi->var.yres_virtual,
+               .color = 0,
+               .rop = ROP_COPY,
+       };
+
+       cfb_fillrect(fbi, &rect);
+}
+
 int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
 {
        struct omapfb_info *ofbi = FB2OFB(fbi);
@@ -1662,6 +1676,8 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
                        goto err;
        }
 
+       omapfb_clear_fb(fbi);
+
        return 0;
 err:
        omapfb_free_fbmem(fbi);
@@ -1946,6 +1962,16 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
                }
        }
 
+       for (i = 0; i < fbdev->num_fbs; i++) {
+               struct fb_info *fbi = fbdev->fbs[i];
+               struct omapfb_info *ofbi = FB2OFB(fbi);
+
+               if (ofbi->region->size == 0)
+                       continue;
+
+               omapfb_clear_fb(fbi);
+       }
+
        DBG("fb_infos initialized\n");
 
        for (i = 0; i < fbdev->num_fbs; i++) {
@@ -2354,6 +2380,7 @@ static int __init omapfb_probe(struct platform_device *pdev)
        struct omap_overlay *ovl;
        struct omap_dss_device *def_display;
        struct omap_dss_device *dssdev;
+       struct omap_dss_device *ovl_device;
 
        DBG("omapfb_probe\n");
 
@@ -2427,8 +2454,9 @@ static int __init omapfb_probe(struct platform_device *pdev)
        /* gfx overlay should be the default one. find a display
         * connected to that, and use it as default display */
        ovl = omap_dss_get_overlay(0);
-       if (ovl->manager && ovl->manager->device) {
-               def_display = ovl->manager->device;
+       ovl_device = ovl->get_device(ovl);
+       if (ovl_device) {
+               def_display = ovl_device;
        } else {
                dev_warn(&pdev->dev, "cannot find default display\n");
                def_display = NULL;
index 30361a09aecdd231c19d40241733d1aa873e1a79..5ced9b334d35e5861f8fcf3dccee914862405120 100644 (file)
@@ -148,8 +148,9 @@ static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
 
        /* XXX: returns the display connected to first attached overlay */
        for (i = 0; i < ofbi->num_overlays; i++) {
-               if (ofbi->overlays[i]->manager)
-                       return ofbi->overlays[i]->manager->device;
+               struct omap_overlay *ovl = ofbi->overlays[i];
+
+               return ovl->get_device(ovl);
        }
 
        return NULL;
index 87e421e25afe0f5a1e61c4bd9affab339ffc7640..f2b15c4a75bc778baad747db2d1510fc43ec33ea 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/setup.h>
 
 #include <plat/vram.h>
-#include <plat/dma.h>
 
 #ifdef DEBUG
 #define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
@@ -250,59 +249,6 @@ int omap_vram_reserve(unsigned long paddr, size_t size)
 }
 EXPORT_SYMBOL(omap_vram_reserve);
 
-static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data)
-{
-       struct completion *compl = data;
-       complete(compl);
-}
-
-static int _omap_vram_clear(u32 paddr, unsigned pages)
-{
-       struct completion compl;
-       unsigned elem_count;
-       unsigned frame_count;
-       int r;
-       int lch;
-
-       init_completion(&compl);
-
-       r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA",
-                       _omap_vram_dma_cb,
-                       &compl, &lch);
-       if (r) {
-               pr_err("VRAM: request_dma failed for memory clear\n");
-               return -EBUSY;
-       }
-
-       elem_count = pages * PAGE_SIZE / 4;
-       frame_count = 1;
-
-       omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32,
-                       elem_count, frame_count,
-                       OMAP_DMA_SYNC_ELEMENT,
-                       0, 0);
-
-       omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC,
-                       paddr, 0, 0);
-
-       omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000);
-
-       omap_start_dma(lch);
-
-       if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) {
-               omap_stop_dma(lch);
-               pr_err("VRAM: dma timeout while clearing memory\n");
-               r = -EIO;
-               goto err;
-       }
-
-       r = 0;
-err:
-       omap_free_dma(lch);
-
-       return r;
-}
-
 static int _omap_vram_alloc(unsigned pages, unsigned long *paddr)
 {
        struct vram_region *rm;
@@ -337,8 +283,6 @@ found:
 
                *paddr = start;
 
-               _omap_vram_clear(start, pages);
-
                return 0;
        }
 
diff --git a/drivers/video/pnx4008/Makefile b/drivers/video/pnx4008/Makefile
deleted file mode 100644 (file)
index 636aacc..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the new PNX4008 framebuffer device driver
-#
-
-obj-$(CONFIG_FB_PNX4008_DUM) += sdum.o
-obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnxrgbfb.o
-
diff --git a/drivers/video/pnx4008/dum.h b/drivers/video/pnx4008/dum.h
deleted file mode 100644 (file)
index 1234d43..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * linux/drivers/video/pnx4008/dum.h
- *
- * Internal header for SDUM
- *
- * 2005 (c) Koninklijke Philips N.V. 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 __PNX008_DUM_H__
-#define __PNX008_DUM_H__
-
-#include <mach/platform.h>
-
-#define PNX4008_DUMCONF_VA_BASE                IO_ADDRESS(PNX4008_DUMCONF_BASE)
-#define PNX4008_DUM_MAIN_VA_BASE       IO_ADDRESS(PNX4008_DUM_MAINCFG_BASE)
-
-/* DUM CFG ADDRESSES */
-#define DUM_CH_BASE_ADR                (PNX4008_DUMCONF_VA_BASE + 0x00)
-#define DUM_CH_MIN_ADR         (PNX4008_DUMCONF_VA_BASE + 0x00)
-#define DUM_CH_MAX_ADR         (PNX4008_DUMCONF_VA_BASE + 0x04)
-#define DUM_CH_CONF_ADR                (PNX4008_DUMCONF_VA_BASE + 0x08)
-#define DUM_CH_STAT_ADR                (PNX4008_DUMCONF_VA_BASE + 0x0C)
-#define DUM_CH_CTRL_ADR                (PNX4008_DUMCONF_VA_BASE + 0x10)
-
-#define CH_MARG                (0x100 / sizeof(u32))
-#define DUM_CH_MIN(i)  (*((volatile u32 *)DUM_CH_MIN_ADR + (i) * CH_MARG))
-#define DUM_CH_MAX(i)  (*((volatile u32 *)DUM_CH_MAX_ADR + (i) * CH_MARG))
-#define DUM_CH_CONF(i) (*((volatile u32 *)DUM_CH_CONF_ADR + (i) * CH_MARG))
-#define DUM_CH_STAT(i) (*((volatile u32 *)DUM_CH_STAT_ADR + (i) * CH_MARG))
-#define DUM_CH_CTRL(i) (*((volatile u32 *)DUM_CH_CTRL_ADR + (i) * CH_MARG))
-
-#define DUM_CONF_ADR          (PNX4008_DUM_MAIN_VA_BASE + 0x00)
-#define DUM_CTRL_ADR          (PNX4008_DUM_MAIN_VA_BASE + 0x04)
-#define DUM_STAT_ADR          (PNX4008_DUM_MAIN_VA_BASE + 0x08)
-#define DUM_DECODE_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x0C)
-#define DUM_COM_BASE_ADR      (PNX4008_DUM_MAIN_VA_BASE + 0x10)
-#define DUM_SYNC_C_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x14)
-#define DUM_CLK_DIV_ADR       (PNX4008_DUM_MAIN_VA_BASE + 0x18)
-#define DUM_DIRTY_LOW_ADR     (PNX4008_DUM_MAIN_VA_BASE + 0x20)
-#define DUM_DIRTY_HIGH_ADR    (PNX4008_DUM_MAIN_VA_BASE + 0x24)
-#define DUM_FORMAT_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x28)
-#define DUM_WTCFG1_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x30)
-#define DUM_RTCFG1_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x34)
-#define DUM_WTCFG2_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x38)
-#define DUM_RTCFG2_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x3C)
-#define DUM_TCFG_ADR          (PNX4008_DUM_MAIN_VA_BASE + 0x40)
-#define DUM_OUTP_FORMAT1_ADR  (PNX4008_DUM_MAIN_VA_BASE + 0x44)
-#define DUM_OUTP_FORMAT2_ADR  (PNX4008_DUM_MAIN_VA_BASE + 0x48)
-#define DUM_SYNC_MODE_ADR     (PNX4008_DUM_MAIN_VA_BASE + 0x4C)
-#define DUM_SYNC_OUT_C_ADR    (PNX4008_DUM_MAIN_VA_BASE + 0x50)
-
-#define DUM_CONF              (*(volatile u32 *)(DUM_CONF_ADR))
-#define DUM_CTRL              (*(volatile u32 *)(DUM_CTRL_ADR))
-#define DUM_STAT              (*(volatile u32 *)(DUM_STAT_ADR))
-#define DUM_DECODE            (*(volatile u32 *)(DUM_DECODE_ADR))
-#define DUM_COM_BASE          (*(volatile u32 *)(DUM_COM_BASE_ADR))
-#define DUM_SYNC_C            (*(volatile u32 *)(DUM_SYNC_C_ADR))
-#define DUM_CLK_DIV           (*(volatile u32 *)(DUM_CLK_DIV_ADR))
-#define DUM_DIRTY_LOW         (*(volatile u32 *)(DUM_DIRTY_LOW_ADR))
-#define DUM_DIRTY_HIGH        (*(volatile u32 *)(DUM_DIRTY_HIGH_ADR))
-#define DUM_FORMAT            (*(volatile u32 *)(DUM_FORMAT_ADR))
-#define DUM_WTCFG1            (*(volatile u32 *)(DUM_WTCFG1_ADR))
-#define DUM_RTCFG1            (*(volatile u32 *)(DUM_RTCFG1_ADR))
-#define DUM_WTCFG2            (*(volatile u32 *)(DUM_WTCFG2_ADR))
-#define DUM_RTCFG2            (*(volatile u32 *)(DUM_RTCFG2_ADR))
-#define DUM_TCFG              (*(volatile u32 *)(DUM_TCFG_ADR))
-#define DUM_OUTP_FORMAT1      (*(volatile u32 *)(DUM_OUTP_FORMAT1_ADR))
-#define DUM_OUTP_FORMAT2      (*(volatile u32 *)(DUM_OUTP_FORMAT2_ADR))
-#define DUM_SYNC_MODE         (*(volatile u32 *)(DUM_SYNC_MODE_ADR))
-#define DUM_SYNC_OUT_C        (*(volatile u32 *)(DUM_SYNC_OUT_C_ADR))
-
-/* DUM SLAVE ADDRESSES */
-#define DUM_SLAVE_WRITE_ADR      (PNX4008_DUM_MAINCFG_BASE + 0x0000000)
-#define DUM_SLAVE_READ1_I_ADR    (PNX4008_DUM_MAINCFG_BASE + 0x1000000)
-#define DUM_SLAVE_READ1_R_ADR    (PNX4008_DUM_MAINCFG_BASE + 0x1000004)
-#define DUM_SLAVE_READ2_I_ADR    (PNX4008_DUM_MAINCFG_BASE + 0x1000008)
-#define DUM_SLAVE_READ2_R_ADR    (PNX4008_DUM_MAINCFG_BASE + 0x100000C)
-
-#define DUM_SLAVE_WRITE_W  ((volatile u32 *)(DUM_SLAVE_WRITE_ADR))
-#define DUM_SLAVE_WRITE_HW ((volatile u16 *)(DUM_SLAVE_WRITE_ADR))
-#define DUM_SLAVE_READ1_I  ((volatile u8 *)(DUM_SLAVE_READ1_I_ADR))
-#define DUM_SLAVE_READ1_R  ((volatile u16 *)(DUM_SLAVE_READ1_R_ADR))
-#define DUM_SLAVE_READ2_I  ((volatile u8 *)(DUM_SLAVE_READ2_I_ADR))
-#define DUM_SLAVE_READ2_R  ((volatile u16 *)(DUM_SLAVE_READ2_R_ADR))
-
-/* Sony display register addresses */
-#define DISP_0_REG            (0x00)
-#define DISP_1_REG            (0x01)
-#define DISP_CAL_REG          (0x20)
-#define DISP_ID_REG           (0x2A)
-#define DISP_XMIN_L_REG       (0x30)
-#define DISP_XMIN_H_REG       (0x31)
-#define DISP_YMIN_REG         (0x32)
-#define DISP_XMAX_L_REG       (0x34)
-#define DISP_XMAX_H_REG       (0x35)
-#define DISP_YMAX_REG         (0x36)
-#define DISP_SYNC_EN_REG      (0x38)
-#define DISP_SYNC_RISE_L_REG  (0x3C)
-#define DISP_SYNC_RISE_H_REG  (0x3D)
-#define DISP_SYNC_FALL_L_REG  (0x3E)
-#define DISP_SYNC_FALL_H_REG  (0x3F)
-#define DISP_PIXEL_REG        (0x0B)
-#define DISP_DUMMY1_REG       (0x28)
-#define DISP_DUMMY2_REG       (0x29)
-#define DISP_TIMING_REG       (0x98)
-#define DISP_DUMP_REG         (0x99)
-
-/* Sony display constants */
-#define SONY_ID1              (0x22)
-#define SONY_ID2              (0x23)
-
-/* Philips display register addresses */
-#define PH_DISP_ORIENT_REG    (0x003)
-#define PH_DISP_YPOINT_REG    (0x200)
-#define PH_DISP_XPOINT_REG    (0x201)
-#define PH_DISP_PIXEL_REG     (0x202)
-#define PH_DISP_YMIN_REG      (0x406)
-#define PH_DISP_YMAX_REG      (0x407)
-#define PH_DISP_XMIN_REG      (0x408)
-#define PH_DISP_XMAX_REG      (0x409)
-
-/* Misc constants */
-#define NO_VALID_DISPLAY_FOUND      (0)
-#define DISPLAY2_IS_NOT_CONNECTED   (0)
-
-/* register values */
-#define V_BAC_ENABLE           (BIT(0))
-#define V_BAC_DISABLE_IDLE     (BIT(1))
-#define V_BAC_DISABLE_TRIG     (BIT(2))
-#define V_DUM_RESET            (BIT(3))
-#define V_MUX_RESET            (BIT(4))
-#define BAC_ENABLED            (BIT(0))
-#define BAC_DISABLED           0
-
-/* Sony LCD commands */
-#define V_LCD_STANDBY_OFF      ((BIT(25)) | (0 << 16) | DISP_0_REG)
-#define V_LCD_USE_9BIT_BUS     ((BIT(25)) | (2 << 16) | DISP_1_REG)
-#define V_LCD_SYNC_RISE_L      ((BIT(25)) | (0 << 16) | DISP_SYNC_RISE_L_REG)
-#define V_LCD_SYNC_RISE_H      ((BIT(25)) | (0 << 16) | DISP_SYNC_RISE_H_REG)
-#define V_LCD_SYNC_FALL_L      ((BIT(25)) | (160 << 16) | DISP_SYNC_FALL_L_REG)
-#define V_LCD_SYNC_FALL_H      ((BIT(25)) | (0 << 16) | DISP_SYNC_FALL_H_REG)
-#define V_LCD_SYNC_ENABLE      ((BIT(25)) | (128 << 16) | DISP_SYNC_EN_REG)
-#define V_LCD_DISPLAY_ON       ((BIT(25)) | (64 << 16) | DISP_0_REG)
-
-enum {
-       PAD_NONE,
-       PAD_512,
-       PAD_1024
-};
-
-enum {
-       RGB888,
-       RGB666,
-       RGB565,
-       BGR565,
-       ARGB1555,
-       ABGR1555,
-       ARGB4444,
-       ABGR4444
-};
-
-struct dum_setup {
-       int sync_neg_edge;
-       int round_robin;
-       int mux_int;
-       int synced_dirty_flag_int;
-       int dirty_flag_int;
-       int error_int;
-       int pf_empty_int;
-       int sf_empty_int;
-       int bac_dis_int;
-       u32 dirty_base_adr;
-       u32 command_base_adr;
-       u32 sync_clk_div;
-       int sync_output;
-       u32 sync_restart_val;
-       u32 set_sync_high;
-       u32 set_sync_low;
-};
-
-struct dum_ch_setup {
-       int disp_no;
-       u32 xmin;
-       u32 ymin;
-       u32 xmax;
-       u32 ymax;
-       int xmirror;
-       int ymirror;
-       int rotate;
-       u32 minadr;
-       u32 maxadr;
-       u32 dirtybuffer;
-       int pad;
-       int format;
-       int hwdirty;
-       int slave_trans;
-};
-
-struct disp_window {
-       u32 xmin_l;
-       u32 xmin_h;
-       u32 ymin;
-       u32 xmax_l;
-       u32 xmax_h;
-       u32 ymax;
-};
-
-#endif                         /* #ifndef __PNX008_DUM_H__ */
diff --git a/drivers/video/pnx4008/fbcommon.h b/drivers/video/pnx4008/fbcommon.h
deleted file mode 100644 (file)
index 4ebc87d..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2005 Philips 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, 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; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA, or http://www.gnu.org/licenses/gpl.html
-*/
-
-#define QCIF_W  (176)
-#define QCIF_H  (144)
-
-#define CIF_W   (352)
-#define CIF_H   (288)
-
-#define LCD_X_RES      208
-#define LCD_Y_RES      320
-#define LCD_X_PAD      256
-#define LCD_BBP                4       /* Bytes Per Pixel */
-
-#define DISP_MAX_X_SIZE     (320)
-#define DISP_MAX_Y_SIZE     (208)
-
-#define RETURNVAL_BASE (0x400)
-
-enum fb_ioctl_returntype {
-       ENORESOURCESLEFT = RETURNVAL_BASE,
-       ERESOURCESNOTFREED,
-       EPROCNOTOWNER,
-       EFBNOTOWNER,
-       ECOPYFAILED,
-       EIOREMAPFAILED,
-};
diff --git a/drivers/video/pnx4008/pnxrgbfb.c b/drivers/video/pnx4008/pnxrgbfb.c
deleted file mode 100644 (file)
index 6d30428..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * drivers/video/pnx4008/pnxrgbfb.c
- *
- * PNX4008's framebuffer support
- *
- * Author: Grigory Tolstolytkin <gtolstolytkin@ru.mvista.com>
- * Based on Philips Semiconductors's code
- *
- * Copyrght (c) 2005 MontaVista Software, Inc.
- * Copyright (c) 2005 Philips Semiconductors
- * 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/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-
-#include "sdum.h"
-#include "fbcommon.h"
-
-static u32 colreg[16];
-
-static struct fb_var_screeninfo rgbfb_var __initdata = {
-       .xres = LCD_X_RES,
-       .yres = LCD_Y_RES,
-       .xres_virtual = LCD_X_RES,
-       .yres_virtual = LCD_Y_RES,
-       .bits_per_pixel = 32,
-       .red.offset = 16,
-       .red.length = 8,
-       .green.offset = 8,
-       .green.length = 8,
-       .blue.offset = 0,
-       .blue.length = 8,
-       .left_margin = 0,
-       .right_margin = 0,
-       .upper_margin = 0,
-       .lower_margin = 0,
-       .vmode = FB_VMODE_NONINTERLACED,
-};
-static struct fb_fix_screeninfo rgbfb_fix __initdata = {
-       .id = "RGBFB",
-       .line_length = LCD_X_RES * LCD_BBP,
-       .type = FB_TYPE_PACKED_PIXELS,
-       .visual = FB_VISUAL_TRUECOLOR,
-       .xpanstep = 0,
-       .ypanstep = 0,
-       .ywrapstep = 0,
-       .accel = FB_ACCEL_NONE,
-};
-
-static int channel_owned;
-
-static int no_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-       return 0;
-}
-
-static int rgbfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-                          u_int transp, struct fb_info *info)
-{
-       if (regno > 15)
-               return 1;
-
-       colreg[regno] = ((red & 0xff00) << 8) | (green & 0xff00) |
-           ((blue & 0xff00) >> 8);
-       return 0;
-}
-
-static int rgbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-       return pnx4008_sdum_mmap(info, vma, NULL);
-}
-
-static struct fb_ops rgbfb_ops = {
-       .fb_mmap = rgbfb_mmap,
-       .fb_setcolreg = rgbfb_setcolreg,
-       .fb_fillrect = cfb_fillrect,
-       .fb_copyarea = cfb_copyarea,
-       .fb_imageblit = cfb_imageblit,
-};
-
-static int rgbfb_remove(struct platform_device *pdev)
-{
-       struct fb_info *info = platform_get_drvdata(pdev);
-
-       if (info) {
-               unregister_framebuffer(info);
-               fb_dealloc_cmap(&info->cmap);
-               framebuffer_release(info);
-               platform_set_drvdata(pdev, NULL);
-       }
-
-       pnx4008_free_dum_channel(channel_owned, pdev->id);
-       pnx4008_set_dum_exit_notification(pdev->id);
-
-       return 0;
-}
-
-static int __devinit rgbfb_probe(struct platform_device *pdev)
-{
-       struct fb_info *info;
-       struct dumchannel_uf chan_uf;
-       int ret;
-       char *option;
-
-       info = framebuffer_alloc(sizeof(u32) * 16, &pdev->dev);
-       if (!info) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       pnx4008_get_fb_addresses(FB_TYPE_RGB, (void **)&info->screen_base,
-                                (dma_addr_t *) &rgbfb_fix.smem_start,
-                                &rgbfb_fix.smem_len);
-
-       if ((ret = pnx4008_alloc_dum_channel(pdev->id)) < 0)
-               goto err0;
-       else {
-               channel_owned = ret;
-               chan_uf.channelnr = channel_owned;
-               chan_uf.dirty = (u32 *) NULL;
-               chan_uf.source = (u32 *) rgbfb_fix.smem_start;
-               chan_uf.x_offset = 0;
-               chan_uf.y_offset = 0;
-               chan_uf.width = LCD_X_RES;
-               chan_uf.height = LCD_Y_RES;
-
-               if ((ret = pnx4008_put_dum_channel_uf(chan_uf, pdev->id))< 0)
-                       goto err1;
-
-               if ((ret =
-                    pnx4008_set_dum_channel_sync(channel_owned, CONF_SYNC_ON,
-                                                 pdev->id)) < 0)
-                       goto err1;
-
-               if ((ret =
-                    pnx4008_set_dum_channel_dirty_detect(channel_owned,
-                                                        CONF_DIRTYDETECTION_ON,
-                                                        pdev->id)) < 0)
-                       goto err1;
-       }
-
-       if (!fb_get_options("pnxrgbfb", &option) && option &&
-                       !strcmp(option, "nocursor"))
-               rgbfb_ops.fb_cursor = no_cursor;
-
-       info->node = -1;
-       info->flags = FBINFO_FLAG_DEFAULT;
-       info->fbops = &rgbfb_ops;
-       info->fix = rgbfb_fix;
-       info->var = rgbfb_var;
-       info->screen_size = rgbfb_fix.smem_len;
-       info->pseudo_palette = info->par;
-       info->par = NULL;
-
-       ret = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (ret < 0)
-               goto err1;
-
-       ret = register_framebuffer(info);
-       if (ret < 0)
-               goto err2;
-       platform_set_drvdata(pdev, info);
-
-       return 0;
-
-err2:
-       fb_dealloc_cmap(&info->cmap);
-err1:
-       pnx4008_free_dum_channel(channel_owned, pdev->id);
-err0:
-       framebuffer_release(info);
-err:
-       return ret;
-}
-
-static struct platform_driver rgbfb_driver = {
-       .driver = {
-               .name = "pnx4008-rgbfb",
-       },
-       .probe = rgbfb_probe,
-       .remove = rgbfb_remove,
-};
-
-module_platform_driver(rgbfb_driver);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/pnx4008/sdum.c b/drivers/video/pnx4008/sdum.c
deleted file mode 100644 (file)
index c5c7414..0000000
+++ /dev/null
@@ -1,861 +0,0 @@
-/*
- * drivers/video/pnx4008/sdum.c
- *
- * Display Update Master support
- *
- * Authors: Grigory Tolstolytkin <gtolstolytkin@ru.mvista.com>
- *          Vitaly Wool <vitalywool@gmail.com>
- * Based on Philips Semiconductors's code
- *
- * Copyrght (c) 2005-2006 MontaVista Software, Inc.
- * Copyright (c) 2005 Philips Semiconductors
- * 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/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-#include <linux/gfp.h>
-#include <asm/uaccess.h>
-#include <asm/gpio.h>
-
-#include "sdum.h"
-#include "fbcommon.h"
-#include "dum.h"
-
-/* Framebuffers we have */
-
-static struct pnx4008_fb_addr {
-       int fb_type;
-       long addr_offset;
-       long fb_length;
-} fb_addr[] = {
-       [0] = {
-               FB_TYPE_YUV, 0, 0xB0000
-       },
-       [1] = {
-               FB_TYPE_RGB, 0xB0000, 0x50000
-       },
-};
-
-static struct dum_data {
-       u32 lcd_phys_start;
-       u32 lcd_virt_start;
-       u32 slave_phys_base;
-       u32 *slave_virt_base;
-       int fb_owning_channel[MAX_DUM_CHANNELS];
-       struct dumchannel_uf chan_uf_store[MAX_DUM_CHANNELS];
-} dum_data;
-
-/* Different local helper functions */
-
-static u32 nof_pixels_dx(struct dum_ch_setup *ch_setup)
-{
-       return (ch_setup->xmax - ch_setup->xmin + 1);
-}
-
-static u32 nof_pixels_dy(struct dum_ch_setup *ch_setup)
-{
-       return (ch_setup->ymax - ch_setup->ymin + 1);
-}
-
-static u32 nof_pixels_dxy(struct dum_ch_setup *ch_setup)
-{
-       return (nof_pixels_dx(ch_setup) * nof_pixels_dy(ch_setup));
-}
-
-static u32 nof_bytes(struct dum_ch_setup *ch_setup)
-{
-       u32 r = nof_pixels_dxy(ch_setup);
-       switch (ch_setup->format) {
-       case RGB888:
-       case RGB666:
-               r *= 4;
-               break;
-
-       default:
-               r *= 2;
-               break;
-       }
-       return r;
-}
-
-static u32 build_command(int disp_no, u32 reg, u32 val)
-{
-       return ((disp_no << 26) | BIT(25) | (val << 16) | (disp_no << 10) |
-               (reg << 0));
-}
-
-static u32 build_double_index(int disp_no, u32 val)
-{
-       return ((disp_no << 26) | (val << 16) | (disp_no << 10) | (val << 0));
-}
-
-static void build_disp_window(struct dum_ch_setup * ch_setup, struct disp_window * dw)
-{
-       dw->ymin = ch_setup->ymin;
-       dw->ymax = ch_setup->ymax;
-       dw->xmin_l = ch_setup->xmin & 0xFF;
-       dw->xmin_h = (ch_setup->xmin & BIT(8)) >> 8;
-       dw->xmax_l = ch_setup->xmax & 0xFF;
-       dw->xmax_h = (ch_setup->xmax & BIT(8)) >> 8;
-}
-
-static int put_channel(struct dumchannel chan)
-{
-       int i = chan.channelnr;
-
-       if (i < 0 || i > MAX_DUM_CHANNELS)
-               return -EINVAL;
-       else {
-               DUM_CH_MIN(i) = chan.dum_ch_min;
-               DUM_CH_MAX(i) = chan.dum_ch_max;
-               DUM_CH_CONF(i) = chan.dum_ch_conf;
-               DUM_CH_CTRL(i) = chan.dum_ch_ctrl;
-       }
-
-       return 0;
-}
-
-static void clear_channel(int channr)
-{
-       struct dumchannel chan;
-
-       chan.channelnr = channr;
-       chan.dum_ch_min = 0;
-       chan.dum_ch_max = 0;
-       chan.dum_ch_conf = 0;
-       chan.dum_ch_ctrl = 0;
-
-       put_channel(chan);
-}
-
-static int put_cmd_string(struct cmdstring cmds)
-{
-       u16 *cmd_str_virtaddr;
-       u32 *cmd_ptr0_virtaddr;
-       u32 cmd_str_physaddr;
-
-       int i = cmds.channelnr;
-
-       if (i < 0 || i > MAX_DUM_CHANNELS)
-               return -EINVAL;
-       else if ((cmd_ptr0_virtaddr =
-                 (int *)ioremap_nocache(DUM_COM_BASE,
-                                        sizeof(int) * MAX_DUM_CHANNELS)) ==
-                NULL)
-               return -EIOREMAPFAILED;
-       else {
-               cmd_str_physaddr = ioread32(&cmd_ptr0_virtaddr[cmds.channelnr]);
-               if ((cmd_str_virtaddr =
-                    (u16 *) ioremap_nocache(cmd_str_physaddr,
-                                            sizeof(cmds))) == NULL) {
-                       iounmap(cmd_ptr0_virtaddr);
-                       return -EIOREMAPFAILED;
-               } else {
-                       int t;
-                       for (t = 0; t < 8; t++)
-                               iowrite16(*((u16 *)&cmds.prestringlen + t),
-                                         cmd_str_virtaddr + t);
-
-                       for (t = 0; t < cmds.prestringlen / 2; t++)
-                                iowrite16(*((u16 *)&cmds.precmd + t),
-                                          cmd_str_virtaddr + t + 8);
-
-                       for (t = 0; t < cmds.poststringlen / 2; t++)
-                               iowrite16(*((u16 *)&cmds.postcmd + t),
-                                         cmd_str_virtaddr + t + 8 +
-                                               cmds.prestringlen / 2);
-
-                       iounmap(cmd_ptr0_virtaddr);
-                       iounmap(cmd_str_virtaddr);
-               }
-       }
-
-       return 0;
-}
-
-static u32 dum_ch_setup(int ch_no, struct dum_ch_setup * ch_setup)
-{
-       struct cmdstring cmds_c;
-       struct cmdstring *cmds = &cmds_c;
-       struct disp_window dw;
-       int standard;
-       u32 orientation = 0;
-       struct dumchannel chan = { 0 };
-       int ret;
-
-       if ((ch_setup->xmirror) || (ch_setup->ymirror) || (ch_setup->rotate)) {
-               standard = 0;
-
-               orientation = BIT(1);   /* always set 9-bit-bus */
-               if (ch_setup->xmirror)
-                       orientation |= BIT(4);
-               if (ch_setup->ymirror)
-                       orientation |= BIT(3);
-               if (ch_setup->rotate)
-                       orientation |= BIT(0);
-       } else
-               standard = 1;
-
-       cmds->channelnr = ch_no;
-
-       /* build command string header */
-       if (standard) {
-               cmds->prestringlen = 32;
-               cmds->poststringlen = 0;
-       } else {
-               cmds->prestringlen = 48;
-               cmds->poststringlen = 16;
-       }
-
-       cmds->format =
-           (u16) ((ch_setup->disp_no << 4) | (BIT(3)) | (ch_setup->format));
-       cmds->reserved = 0x0;
-       cmds->startaddr_low = (ch_setup->minadr & 0xFFFF);
-       cmds->startaddr_high = (ch_setup->minadr >> 16);
-
-       if ((ch_setup->minadr == 0) && (ch_setup->maxadr == 0)
-           && (ch_setup->xmin == 0)
-           && (ch_setup->ymin == 0) && (ch_setup->xmax == 0)
-           && (ch_setup->ymax == 0)) {
-               cmds->pixdatlen_low = 0;
-               cmds->pixdatlen_high = 0;
-       } else {
-               u32 nbytes = nof_bytes(ch_setup);
-               cmds->pixdatlen_low = (nbytes & 0xFFFF);
-               cmds->pixdatlen_high = (nbytes >> 16);
-       }
-
-       if (ch_setup->slave_trans)
-               cmds->pixdatlen_high |= BIT(15);
-
-       /* build pre-string */
-       build_disp_window(ch_setup, &dw);
-
-       if (standard) {
-               cmds->precmd[0] =
-                   build_command(ch_setup->disp_no, DISP_XMIN_L_REG, 0x99);
-               cmds->precmd[1] =
-                   build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
-                                 dw.xmin_l);
-               cmds->precmd[2] =
-                   build_command(ch_setup->disp_no, DISP_XMIN_H_REG,
-                                 dw.xmin_h);
-               cmds->precmd[3] =
-                   build_command(ch_setup->disp_no, DISP_YMIN_REG, dw.ymin);
-               cmds->precmd[4] =
-                   build_command(ch_setup->disp_no, DISP_XMAX_L_REG,
-                                 dw.xmax_l);
-               cmds->precmd[5] =
-                   build_command(ch_setup->disp_no, DISP_XMAX_H_REG,
-                                 dw.xmax_h);
-               cmds->precmd[6] =
-                   build_command(ch_setup->disp_no, DISP_YMAX_REG, dw.ymax);
-               cmds->precmd[7] =
-                   build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
-       } else {
-               if (dw.xmin_l == ch_no)
-                       cmds->precmd[0] =
-                           build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
-                                         0x99);
-               else
-                       cmds->precmd[0] =
-                           build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
-                                         ch_no);
-
-               cmds->precmd[1] =
-                   build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
-                                 dw.xmin_l);
-               cmds->precmd[2] =
-                   build_command(ch_setup->disp_no, DISP_XMIN_H_REG,
-                                 dw.xmin_h);
-               cmds->precmd[3] =
-                   build_command(ch_setup->disp_no, DISP_YMIN_REG, dw.ymin);
-               cmds->precmd[4] =
-                   build_command(ch_setup->disp_no, DISP_XMAX_L_REG,
-                                 dw.xmax_l);
-               cmds->precmd[5] =
-                   build_command(ch_setup->disp_no, DISP_XMAX_H_REG,
-                                 dw.xmax_h);
-               cmds->precmd[6] =
-                   build_command(ch_setup->disp_no, DISP_YMAX_REG, dw.ymax);
-               cmds->precmd[7] =
-                   build_command(ch_setup->disp_no, DISP_1_REG, orientation);
-               cmds->precmd[8] =
-                   build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
-               cmds->precmd[9] =
-                   build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
-               cmds->precmd[0xA] =
-                   build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
-               cmds->precmd[0xB] =
-                   build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
-               cmds->postcmd[0] =
-                   build_command(ch_setup->disp_no, DISP_1_REG, BIT(1));
-               cmds->postcmd[1] =
-                   build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 1);
-               cmds->postcmd[2] =
-                   build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 2);
-               cmds->postcmd[3] =
-                   build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 3);
-       }
-
-       if ((ret = put_cmd_string(cmds_c)) != 0) {
-               return ret;
-       }
-
-       chan.channelnr = cmds->channelnr;
-       chan.dum_ch_min = ch_setup->dirtybuffer + ch_setup->minadr;
-       chan.dum_ch_max = ch_setup->dirtybuffer + ch_setup->maxadr;
-       chan.dum_ch_conf = 0x002;
-       chan.dum_ch_ctrl = 0x04;
-
-       put_channel(chan);
-
-       return 0;
-}
-
-static u32 display_open(int ch_no, int auto_update, u32 * dirty_buffer,
-                       u32 * frame_buffer, u32 xpos, u32 ypos, u32 w, u32 h)
-{
-
-       struct dum_ch_setup k;
-       int ret;
-
-       /* keep width & height within display area */
-       if ((xpos + w) > DISP_MAX_X_SIZE)
-               w = DISP_MAX_X_SIZE - xpos;
-
-       if ((ypos + h) > DISP_MAX_Y_SIZE)
-               h = DISP_MAX_Y_SIZE - ypos;
-
-       /* assume 1 display only */
-       k.disp_no = 0;
-       k.xmin = xpos;
-       k.ymin = ypos;
-       k.xmax = xpos + (w - 1);
-       k.ymax = ypos + (h - 1);
-
-       /* adjust min and max values if necessary */
-       if (k.xmin > DISP_MAX_X_SIZE - 1)
-               k.xmin = DISP_MAX_X_SIZE - 1;
-       if (k.ymin > DISP_MAX_Y_SIZE - 1)
-               k.ymin = DISP_MAX_Y_SIZE - 1;
-
-       if (k.xmax > DISP_MAX_X_SIZE - 1)
-               k.xmax = DISP_MAX_X_SIZE - 1;
-       if (k.ymax > DISP_MAX_Y_SIZE - 1)
-               k.ymax = DISP_MAX_Y_SIZE - 1;
-
-       k.xmirror = 0;
-       k.ymirror = 0;
-       k.rotate = 0;
-       k.minadr = (u32) frame_buffer;
-       k.maxadr = (u32) frame_buffer + (((w - 1) << 10) | ((h << 2) - 2));
-       k.pad = PAD_1024;
-       k.dirtybuffer = (u32) dirty_buffer;
-       k.format = RGB888;
-       k.hwdirty = 0;
-       k.slave_trans = 0;
-
-       ret = dum_ch_setup(ch_no, &k);
-
-       return ret;
-}
-
-static void lcd_reset(void)
-{
-       u32 *dum_pio_base = (u32 *)IO_ADDRESS(PNX4008_PIO_BASE);
-
-       udelay(1);
-       iowrite32(BIT(19), &dum_pio_base[2]);
-       udelay(1);
-       iowrite32(BIT(19), &dum_pio_base[1]);
-       udelay(1);
-}
-
-static int dum_init(struct platform_device *pdev)
-{
-       struct clk *clk;
-
-       /* enable DUM clock */
-       clk = clk_get(&pdev->dev, "dum_ck");
-       if (IS_ERR(clk)) {
-               printk(KERN_ERR "pnx4008_dum: Unable to access DUM clock\n");
-               return PTR_ERR(clk);
-       }
-
-       clk_set_rate(clk, 1);
-       clk_put(clk);
-
-       DUM_CTRL = V_DUM_RESET;
-
-       /* set priority to "round-robin". All other params to "false" */
-       DUM_CONF = BIT(9);
-
-       /* Display 1 */
-       DUM_WTCFG1 = PNX4008_DUM_WT_CFG;
-       DUM_RTCFG1 = PNX4008_DUM_RT_CFG;
-       DUM_TCFG = PNX4008_DUM_T_CFG;
-
-       return 0;
-}
-
-static void dum_chan_init(void)
-{
-       int i = 0, ch = 0;
-       u32 *cmdptrs;
-       u32 *cmdstrings;
-
-       DUM_COM_BASE =
-               CMDSTRING_BASEADDR + BYTES_PER_CMDSTRING * NR_OF_CMDSTRINGS;
-
-       if ((cmdptrs =
-            (u32 *) ioremap_nocache(DUM_COM_BASE,
-                                    sizeof(u32) * NR_OF_CMDSTRINGS)) == NULL)
-               return;
-
-       for (ch = 0; ch < NR_OF_CMDSTRINGS; ch++)
-               iowrite32(CMDSTRING_BASEADDR + BYTES_PER_CMDSTRING * ch,
-                         cmdptrs + ch);
-
-       for (ch = 0; ch < MAX_DUM_CHANNELS; ch++)
-               clear_channel(ch);
-
-       /* Clear the cmdstrings */
-       cmdstrings =
-           (u32 *)ioremap_nocache(*cmdptrs,
-                                  BYTES_PER_CMDSTRING * NR_OF_CMDSTRINGS);
-
-       if (!cmdstrings)
-               goto out;
-
-       for (i = 0; i < NR_OF_CMDSTRINGS * BYTES_PER_CMDSTRING / sizeof(u32);
-            i++)
-               iowrite32(0, cmdstrings + i);
-
-       iounmap((u32 *)cmdstrings);
-
-out:
-       iounmap((u32 *)cmdptrs);
-}
-
-static void lcd_init(void)
-{
-       lcd_reset();
-
-       DUM_OUTP_FORMAT1 = 0; /* RGB666 */
-
-       udelay(1);
-       iowrite32(V_LCD_STANDBY_OFF, dum_data.slave_virt_base);
-       udelay(1);
-       iowrite32(V_LCD_USE_9BIT_BUS, dum_data.slave_virt_base);
-       udelay(1);
-       iowrite32(V_LCD_SYNC_RISE_L, dum_data.slave_virt_base);
-       udelay(1);
-       iowrite32(V_LCD_SYNC_RISE_H, dum_data.slave_virt_base);
-       udelay(1);
-       iowrite32(V_LCD_SYNC_FALL_L, dum_data.slave_virt_base);
-       udelay(1);
-       iowrite32(V_LCD_SYNC_FALL_H, dum_data.slave_virt_base);
-       udelay(1);
-       iowrite32(V_LCD_SYNC_ENABLE, dum_data.slave_virt_base);
-       udelay(1);
-       iowrite32(V_LCD_DISPLAY_ON, dum_data.slave_virt_base);
-       udelay(1);
-}
-
-/* Interface exported to framebuffer drivers */
-
-int pnx4008_get_fb_addresses(int fb_type, void **virt_addr,
-                            dma_addr_t *phys_addr, int *fb_length)
-{
-       int i;
-       int ret = -1;
-       for (i = 0; i < ARRAY_SIZE(fb_addr); i++)
-               if (fb_addr[i].fb_type == fb_type) {
-                       *virt_addr = (void *)(dum_data.lcd_virt_start +
-                                       fb_addr[i].addr_offset);
-                       *phys_addr =
-                           dum_data.lcd_phys_start + fb_addr[i].addr_offset;
-                       *fb_length = fb_addr[i].fb_length;
-                       ret = 0;
-                       break;
-               }
-
-       return ret;
-}
-
-EXPORT_SYMBOL(pnx4008_get_fb_addresses);
-
-int pnx4008_alloc_dum_channel(int dev_id)
-{
-       int i = 0;
-
-       while ((i < MAX_DUM_CHANNELS) && (dum_data.fb_owning_channel[i] != -1))
-               i++;
-
-       if (i == MAX_DUM_CHANNELS)
-               return -ENORESOURCESLEFT;
-       else {
-               dum_data.fb_owning_channel[i] = dev_id;
-               return i;
-       }
-}
-
-EXPORT_SYMBOL(pnx4008_alloc_dum_channel);
-
-int pnx4008_free_dum_channel(int channr, int dev_id)
-{
-       if (channr < 0 || channr > MAX_DUM_CHANNELS)
-               return -EINVAL;
-       else if (dum_data.fb_owning_channel[channr] != dev_id)
-               return -EFBNOTOWNER;
-       else {
-               clear_channel(channr);
-               dum_data.fb_owning_channel[channr] = -1;
-       }
-
-       return 0;
-}
-
-EXPORT_SYMBOL(pnx4008_free_dum_channel);
-
-int pnx4008_put_dum_channel_uf(struct dumchannel_uf chan_uf, int dev_id)
-{
-       int i = chan_uf.channelnr;
-       int ret;
-
-       if (i < 0 || i > MAX_DUM_CHANNELS)
-               return -EINVAL;
-       else if (dum_data.fb_owning_channel[i] != dev_id)
-               return -EFBNOTOWNER;
-       else if ((ret =
-                 display_open(chan_uf.channelnr, 0, chan_uf.dirty,
-                              chan_uf.source, chan_uf.y_offset,
-                              chan_uf.x_offset, chan_uf.height,
-                              chan_uf.width)) != 0)
-               return ret;
-       else {
-               dum_data.chan_uf_store[i].dirty = chan_uf.dirty;
-               dum_data.chan_uf_store[i].source = chan_uf.source;
-               dum_data.chan_uf_store[i].x_offset = chan_uf.x_offset;
-               dum_data.chan_uf_store[i].y_offset = chan_uf.y_offset;
-               dum_data.chan_uf_store[i].width = chan_uf.width;
-               dum_data.chan_uf_store[i].height = chan_uf.height;
-       }
-
-       return 0;
-}
-
-EXPORT_SYMBOL(pnx4008_put_dum_channel_uf);
-
-int pnx4008_set_dum_channel_sync(int channr, int val, int dev_id)
-{
-       if (channr < 0 || channr > MAX_DUM_CHANNELS)
-               return -EINVAL;
-       else if (dum_data.fb_owning_channel[channr] != dev_id)
-               return -EFBNOTOWNER;
-       else {
-               if (val == CONF_SYNC_ON) {
-                       DUM_CH_CONF(channr) |= CONF_SYNCENABLE;
-                       DUM_CH_CONF(channr) |= DUM_CHANNEL_CFG_SYNC_MASK |
-                               DUM_CHANNEL_CFG_SYNC_MASK_SET;
-               } else if (val == CONF_SYNC_OFF)
-                       DUM_CH_CONF(channr) &= ~CONF_SYNCENABLE;
-               else
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-EXPORT_SYMBOL(pnx4008_set_dum_channel_sync);
-
-int pnx4008_set_dum_channel_dirty_detect(int channr, int val, int dev_id)
-{
-       if (channr < 0 || channr > MAX_DUM_CHANNELS)
-               return -EINVAL;
-       else if (dum_data.fb_owning_channel[channr] != dev_id)
-               return -EFBNOTOWNER;
-       else {
-               if (val == CONF_DIRTYDETECTION_ON)
-                       DUM_CH_CONF(channr) |= CONF_DIRTYENABLE;
-               else if (val == CONF_DIRTYDETECTION_OFF)
-                       DUM_CH_CONF(channr) &= ~CONF_DIRTYENABLE;
-               else
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-EXPORT_SYMBOL(pnx4008_set_dum_channel_dirty_detect);
-
-#if 0 /* Functions not used currently, but likely to be used in future */
-
-static int get_channel(struct dumchannel *p_chan)
-{
-       int i = p_chan->channelnr;
-
-       if (i < 0 || i > MAX_DUM_CHANNELS)
-               return -EINVAL;
-       else {
-               p_chan->dum_ch_min = DUM_CH_MIN(i);
-               p_chan->dum_ch_max = DUM_CH_MAX(i);
-               p_chan->dum_ch_conf = DUM_CH_CONF(i);
-               p_chan->dum_ch_stat = DUM_CH_STAT(i);
-               p_chan->dum_ch_ctrl = 0;        /* WriteOnly control register */
-       }
-
-       return 0;
-}
-
-int pnx4008_get_dum_channel_uf(struct dumchannel_uf *p_chan_uf, int dev_id)
-{
-       int i = p_chan_uf->channelnr;
-
-       if (i < 0 || i > MAX_DUM_CHANNELS)
-               return -EINVAL;
-       else if (dum_data.fb_owning_channel[i] != dev_id)
-               return -EFBNOTOWNER;
-       else {
-               p_chan_uf->dirty = dum_data.chan_uf_store[i].dirty;
-               p_chan_uf->source = dum_data.chan_uf_store[i].source;
-               p_chan_uf->x_offset = dum_data.chan_uf_store[i].x_offset;
-               p_chan_uf->y_offset = dum_data.chan_uf_store[i].y_offset;
-               p_chan_uf->width = dum_data.chan_uf_store[i].width;
-               p_chan_uf->height = dum_data.chan_uf_store[i].height;
-       }
-
-       return 0;
-}
-
-EXPORT_SYMBOL(pnx4008_get_dum_channel_uf);
-
-int pnx4008_get_dum_channel_config(int channr, int dev_id)
-{
-       int ret;
-       struct dumchannel chan;
-
-       if (channr < 0 || channr > MAX_DUM_CHANNELS)
-               return -EINVAL;
-       else if (dum_data.fb_owning_channel[channr] != dev_id)
-               return -EFBNOTOWNER;
-       else {
-               chan.channelnr = channr;
-               if ((ret = get_channel(&chan)) != 0)
-                       return ret;
-       }
-
-       return (chan.dum_ch_conf & DUM_CHANNEL_CFG_MASK);
-}
-
-EXPORT_SYMBOL(pnx4008_get_dum_channel_config);
-
-int pnx4008_force_update_dum_channel(int channr, int dev_id)
-{
-       if (channr < 0 || channr > MAX_DUM_CHANNELS)
-               return -EINVAL;
-
-       else if (dum_data.fb_owning_channel[channr] != dev_id)
-               return -EFBNOTOWNER;
-       else
-               DUM_CH_CTRL(channr) = CTRL_SETDIRTY;
-
-       return 0;
-}
-
-EXPORT_SYMBOL(pnx4008_force_update_dum_channel);
-
-#endif
-
-int pnx4008_sdum_mmap(struct fb_info *info, struct vm_area_struct *vma,
-                     struct device *dev)
-{
-       unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
-
-       if (off < info->fix.smem_len) {
-               vma->vm_pgoff += 1;
-               return dma_mmap_writecombine(dev, vma,
-                               (void *)dum_data.lcd_virt_start,
-                               dum_data.lcd_phys_start,
-                               FB_DMA_SIZE);
-       }
-       return -EINVAL;
-}
-
-EXPORT_SYMBOL(pnx4008_sdum_mmap);
-
-int pnx4008_set_dum_exit_notification(int dev_id)
-{
-       int i;
-
-       for (i = 0; i < MAX_DUM_CHANNELS; i++)
-               if (dum_data.fb_owning_channel[i] == dev_id)
-                       return -ERESOURCESNOTFREED;
-
-       return 0;
-}
-
-EXPORT_SYMBOL(pnx4008_set_dum_exit_notification);
-
-/* Platform device driver for DUM */
-
-static int sdum_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       int retval = 0;
-       struct clk *clk;
-
-       clk = clk_get(0, "dum_ck");
-       if (!IS_ERR(clk)) {
-               clk_set_rate(clk, 0);
-               clk_put(clk);
-       } else
-               retval = PTR_ERR(clk);
-
-       /* disable BAC */
-       DUM_CTRL = V_BAC_DISABLE_IDLE;
-
-       /* LCD standby & turn off display */
-       lcd_reset();
-
-       return retval;
-}
-
-static int sdum_resume(struct platform_device *pdev)
-{
-       int retval = 0;
-       struct clk *clk;
-
-       clk = clk_get(0, "dum_ck");
-       if (!IS_ERR(clk)) {
-               clk_set_rate(clk, 1);
-               clk_put(clk);
-       } else
-               retval = PTR_ERR(clk);
-
-       /* wait for BAC disable */
-       DUM_CTRL = V_BAC_DISABLE_TRIG;
-
-       while (DUM_CTRL & BAC_ENABLED)
-               udelay(10);
-
-       /* re-init LCD */
-       lcd_init();
-
-       /* enable BAC and reset MUX */
-       DUM_CTRL = V_BAC_ENABLE;
-       udelay(1);
-       DUM_CTRL = V_MUX_RESET;
-       return 0;
-}
-
-static int __devinit sdum_probe(struct platform_device *pdev)
-{
-       int ret = 0, i = 0;
-
-       /* map frame buffer */
-       dum_data.lcd_virt_start = (u32) dma_alloc_writecombine(&pdev->dev,
-                                                      FB_DMA_SIZE,
-                                                      &dum_data.lcd_phys_start,
-                                                      GFP_KERNEL);
-
-       if (!dum_data.lcd_virt_start) {
-               ret = -ENOMEM;
-               goto out_3;
-       }
-
-       /* map slave registers */
-       dum_data.slave_phys_base = PNX4008_DUM_SLAVE_BASE;
-       dum_data.slave_virt_base =
-           (u32 *) ioremap_nocache(dum_data.slave_phys_base, sizeof(u32));
-
-       if (dum_data.slave_virt_base == NULL) {
-               ret = -ENOMEM;
-               goto out_2;
-       }
-
-       /* initialize DUM and LCD display */
-       ret = dum_init(pdev);
-       if (ret)
-               goto out_1;
-
-       dum_chan_init();
-       lcd_init();
-
-       DUM_CTRL = V_BAC_ENABLE;
-       udelay(1);
-       DUM_CTRL = V_MUX_RESET;
-
-       /* set decode address and sync clock divider */
-       DUM_DECODE = dum_data.lcd_phys_start & DUM_DECODE_MASK;
-       DUM_CLK_DIV = PNX4008_DUM_CLK_DIV;
-
-       for (i = 0; i < MAX_DUM_CHANNELS; i++)
-               dum_data.fb_owning_channel[i] = -1;
-
-       /*setup wakeup interrupt */
-       start_int_set_rising_edge(SE_DISP_SYNC_INT);
-       start_int_ack(SE_DISP_SYNC_INT);
-       start_int_umask(SE_DISP_SYNC_INT);
-
-       return 0;
-
-out_1:
-       iounmap((void *)dum_data.slave_virt_base);
-out_2:
-       dma_free_writecombine(&pdev->dev, FB_DMA_SIZE,
-                       (void *)dum_data.lcd_virt_start,
-                       dum_data.lcd_phys_start);
-out_3:
-       return ret;
-}
-
-static int sdum_remove(struct platform_device *pdev)
-{
-       struct clk *clk;
-
-       start_int_mask(SE_DISP_SYNC_INT);
-
-       clk = clk_get(0, "dum_ck");
-       if (!IS_ERR(clk)) {
-               clk_set_rate(clk, 0);
-               clk_put(clk);
-       }
-
-       iounmap((void *)dum_data.slave_virt_base);
-
-       dma_free_writecombine(&pdev->dev, FB_DMA_SIZE,
-                       (void *)dum_data.lcd_virt_start,
-                       dum_data.lcd_phys_start);
-
-       return 0;
-}
-
-static struct platform_driver sdum_driver = {
-       .driver = {
-               .name = "pnx4008-sdum",
-       },
-       .probe = sdum_probe,
-       .remove = sdum_remove,
-       .suspend = sdum_suspend,
-       .resume = sdum_resume,
-};
-
-module_platform_driver(sdum_driver);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/pnx4008/sdum.h b/drivers/video/pnx4008/sdum.h
deleted file mode 100644 (file)
index 189c3d6..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2005 Philips 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, 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; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA, or http://www.gnu.org/licenses/gpl.html
-*/
-
-#define MAX_DUM_CHANNELS       64
-
-#define RGB_MEM_WINDOW(x) (0x10000000 + (x)*0x00100000)
-
-#define QCIF_OFFSET(x) (((x) == 0) ? 0x00000: ((x) == 1) ? 0x30000: -1)
-#define CIF_OFFSET(x)  (((x) == 0) ? 0x00000: ((x) == 1) ? 0x60000: -1)
-
-#define CTRL_SETDIRTY          (0x00000001)
-#define CONF_DIRTYENABLE       (0x00000020)
-#define CONF_SYNCENABLE                (0x00000004)
-
-#define DIRTY_ENABLED(conf)    ((conf) & 0x0020)
-#define SYNC_ENABLED(conf)     ((conf) & 0x0004)
-
-/* Display 1 & 2 Write Timing Configuration */
-#define PNX4008_DUM_WT_CFG             0x00372000
-
-/* Display 1 & 2 Read Timing Configuration */
-#define PNX4008_DUM_RT_CFG             0x00003A47
-
-/* DUM Transit State Timing Configuration */
-#define PNX4008_DUM_T_CFG              0x1D    /* 29 HCLK cycles */
-
-/* DUM Sync count clock divider */
-#define PNX4008_DUM_CLK_DIV            0x02DD
-
-/* Memory size for framebuffer, allocated through dma_alloc_writecombine().
- * Must be PAGE aligned
- */
-#define FB_DMA_SIZE (PAGE_ALIGN(SZ_1M + PAGE_SIZE))
-
-#define OFFSET_RGBBUFFER (0xB0000)
-#define OFFSET_YUVBUFFER (0x00000)
-
-#define YUVBUFFER (lcd_video_start + OFFSET_YUVBUFFER)
-#define RGBBUFFER (lcd_video_start + OFFSET_RGBBUFFER)
-
-#define CMDSTRING_BASEADDR     (0x00C000)      /* iram */
-#define BYTES_PER_CMDSTRING    (0x80)
-#define NR_OF_CMDSTRINGS       (64)
-
-#define MAX_NR_PRESTRINGS (0x40)
-#define MAX_NR_POSTSTRINGS (0x40)
-
-/* various mask definitions */
-#define DUM_CLK_ENABLE 0x01
-#define DUM_CLK_DISABLE 0
-#define DUM_DECODE_MASK 0x1FFFFFFF
-#define DUM_CHANNEL_CFG_MASK 0x01FF
-#define DUM_CHANNEL_CFG_SYNC_MASK 0xFFFE00FF
-#define DUM_CHANNEL_CFG_SYNC_MASK_SET 0x0CA00
-
-#define SDUM_RETURNVAL_BASE (0x500)
-
-#define CONF_SYNC_OFF          (0x602)
-#define CONF_SYNC_ON           (0x603)
-
-#define CONF_DIRTYDETECTION_OFF        (0x600)
-#define CONF_DIRTYDETECTION_ON (0x601)
-
-struct dumchannel_uf {
-       int channelnr;
-       u32 *dirty;
-       u32 *source;
-       u32 x_offset;
-       u32 y_offset;
-       u32 width;
-       u32 height;
-};
-
-enum {
-       FB_TYPE_YUV,
-       FB_TYPE_RGB
-};
-
-struct cmdstring {
-       int channelnr;
-       uint16_t prestringlen;
-       uint16_t poststringlen;
-       uint16_t format;
-       uint16_t reserved;
-       uint16_t startaddr_low;
-       uint16_t startaddr_high;
-       uint16_t pixdatlen_low;
-       uint16_t pixdatlen_high;
-       u32 precmd[MAX_NR_PRESTRINGS];
-       u32 postcmd[MAX_NR_POSTSTRINGS];
-
-};
-
-struct dumchannel {
-       int channelnr;
-       int dum_ch_min;
-       int dum_ch_max;
-       int dum_ch_conf;
-       int dum_ch_stat;
-       int dum_ch_ctrl;
-};
-
-int pnx4008_alloc_dum_channel(int dev_id);
-int pnx4008_free_dum_channel(int channr, int dev_id);
-
-int pnx4008_get_dum_channel_uf(struct dumchannel_uf *pChan_uf, int dev_id);
-int pnx4008_put_dum_channel_uf(struct dumchannel_uf chan_uf, int dev_id);
-
-int pnx4008_set_dum_channel_sync(int channr, int val, int dev_id);
-int pnx4008_set_dum_channel_dirty_detect(int channr, int val, int dev_id);
-
-int pnx4008_force_dum_update_channel(int channr, int dev_id);
-
-int pnx4008_get_dum_channel_config(int channr, int dev_id);
-
-int pnx4008_sdum_mmap(struct fb_info *info, struct vm_area_struct *vma, struct device *dev);
-int pnx4008_set_dum_exit_notification(int dev_id);
-
-int pnx4008_get_fb_addresses(int fb_type, void **virt_addr,
-                            dma_addr_t * phys_addr, int *fb_length);
index 4e292f29bf5dedb710085d291105c75f604e3e74..0b340d6ff8a4cab05eb4843f5d5ecff38700fbf9 100644 (file)
@@ -1034,6 +1034,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
        if (status) {
                dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n",
                        __func__, status);
+               retval = -ENOMEM;
                goto err_close_device;
        }
        dev_dbg(&dev->core, "ddr:lpar:0x%llx\n", ddr_lpar);
@@ -1046,6 +1047,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
                dev_err(&dev->core,
                        "%s: lv1_gpu_context_allocate failed: %d\n", __func__,
                        status);
+               retval = -ENOMEM;
                goto err_gpu_memory_free;
        }
 
@@ -1053,6 +1055,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
        dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024);
        if (!dinfo) {
                dev_err(&dev->core, "%s: ioremap failed\n", __func__);
+               retval = -ENOMEM;
                goto err_gpu_context_free;
        }
 
@@ -1121,8 +1124,10 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
        }
 
        info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core);
-       if (!info)
+       if (!info) {
+               retval = -ENOMEM;
                goto err_context_fb_close;
+       }
 
        par = info->par;
        par->mode_id = ~ps3fb_mode;     /* != ps3fb_mode, to trigger change */
index 69bf9d07c237835894ff5377c8527e1a0347adcc..2ed7b633bbd9656352d10e5201efc462c065f991 100644 (file)
@@ -25,8 +25,8 @@
 #include <linux/interrupt.h>
 #include <linux/pm_runtime.h>
 
+#include <video/samsung_fimd.h>
 #include <mach/map.h>
-#include <plat/regs-fb-v4.h>
 #include <plat/fb.h>
 
 /* This driver will export a number of framebuffer interfaces depending
@@ -1398,35 +1398,28 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
 
        spin_lock_init(&sfb->slock);
 
-       sfb->bus_clk = clk_get(dev, "lcd");
+       sfb->bus_clk = devm_clk_get(dev, "lcd");
        if (IS_ERR(sfb->bus_clk)) {
                dev_err(dev, "failed to get bus clock\n");
-               ret = PTR_ERR(sfb->bus_clk);
-               goto err_sfb;
+               return PTR_ERR(sfb->bus_clk);
        }
 
-       clk_enable(sfb->bus_clk);
+       clk_prepare_enable(sfb->bus_clk);
 
        if (!sfb->variant.has_clksel) {
-               sfb->lcd_clk = clk_get(dev, "sclk_fimd");
+               sfb->lcd_clk = devm_clk_get(dev, "sclk_fimd");
                if (IS_ERR(sfb->lcd_clk)) {
                        dev_err(dev, "failed to get lcd clock\n");
                        ret = PTR_ERR(sfb->lcd_clk);
                        goto err_bus_clk;
                }
 
-               clk_enable(sfb->lcd_clk);
+               clk_prepare_enable(sfb->lcd_clk);
        }
 
        pm_runtime_enable(sfb->dev);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "failed to find registers\n");
-               ret = -ENOENT;
-               goto err_lcd_clk;
-       }
-
        sfb->regs = devm_request_and_ioremap(dev, res);
        if (!sfb->regs) {
                dev_err(dev, "failed to map registers\n");
@@ -1510,16 +1503,12 @@ err_pm_runtime:
 err_lcd_clk:
        pm_runtime_disable(sfb->dev);
 
-       if (!sfb->variant.has_clksel) {
-               clk_disable(sfb->lcd_clk);
-               clk_put(sfb->lcd_clk);
-       }
+       if (!sfb->variant.has_clksel)
+               clk_disable_unprepare(sfb->lcd_clk);
 
 err_bus_clk:
-       clk_disable(sfb->bus_clk);
-       clk_put(sfb->bus_clk);
+       clk_disable_unprepare(sfb->bus_clk);
 
-err_sfb:
        return ret;
 }
 
@@ -1541,13 +1530,10 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
                if (sfb->windows[win])
                        s3c_fb_release_win(sfb, sfb->windows[win]);
 
-       if (!sfb->variant.has_clksel) {
-               clk_disable(sfb->lcd_clk);
-               clk_put(sfb->lcd_clk);
-       }
+       if (!sfb->variant.has_clksel)
+               clk_disable_unprepare(sfb->lcd_clk);
 
-       clk_disable(sfb->bus_clk);
-       clk_put(sfb->bus_clk);
+       clk_disable_unprepare(sfb->bus_clk);
 
        pm_runtime_put_sync(sfb->dev);
        pm_runtime_disable(sfb->dev);
@@ -1575,9 +1561,9 @@ static int s3c_fb_suspend(struct device *dev)
        }
 
        if (!sfb->variant.has_clksel)
-               clk_disable(sfb->lcd_clk);
+               clk_disable_unprepare(sfb->lcd_clk);
 
-       clk_disable(sfb->bus_clk);
+       clk_disable_unprepare(sfb->bus_clk);
 
        pm_runtime_put_sync(sfb->dev);
 
@@ -1595,10 +1581,10 @@ static int s3c_fb_resume(struct device *dev)
 
        pm_runtime_get_sync(sfb->dev);
 
-       clk_enable(sfb->bus_clk);
+       clk_prepare_enable(sfb->bus_clk);
 
        if (!sfb->variant.has_clksel)
-               clk_enable(sfb->lcd_clk);
+               clk_prepare_enable(sfb->lcd_clk);
 
        /* setup gpio and output polarity controls */
        pd->setup_gpio();
@@ -1654,9 +1640,9 @@ static int s3c_fb_runtime_suspend(struct device *dev)
        struct s3c_fb *sfb = platform_get_drvdata(pdev);
 
        if (!sfb->variant.has_clksel)
-               clk_disable(sfb->lcd_clk);
+               clk_disable_unprepare(sfb->lcd_clk);
 
-       clk_disable(sfb->bus_clk);
+       clk_disable_unprepare(sfb->bus_clk);
 
        return 0;
 }
@@ -1667,10 +1653,10 @@ static int s3c_fb_runtime_resume(struct device *dev)
        struct s3c_fb *sfb = platform_get_drvdata(pdev);
        struct s3c_fb_platdata *pd = sfb->pdata;
 
-       clk_enable(sfb->bus_clk);
+       clk_prepare_enable(sfb->bus_clk);
 
        if (!sfb->variant.has_clksel)
-               clk_enable(sfb->lcd_clk);
+               clk_prepare_enable(sfb->lcd_clk);
 
        /* setup gpio and output polarity controls */
        pd->setup_gpio();
index 77f34c614c86bc73cd21cd189b542c5f07c1bab3..1083bb9469eec5911727856cba5623d157c273fe 100644 (file)
@@ -11,6 +11,8 @@
  * Driver based on skeletonfb.c, sa1100fb.c and others.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/err.h>
@@ -48,7 +50,11 @@ static int debug     = 1;
 static int debug;
 #endif
 
-#define dprintk(msg...)        if (debug) printk(KERN_DEBUG "s3c2410fb: " msg);
+#define dprintk(msg...) \
+do { \
+       if (debug) \
+               pr_debug(msg); \
+} while (0)
 
 /* useful functions */
 
@@ -598,11 +604,11 @@ static int s3c2410fb_debug_store(struct device *dev,
        if (strnicmp(buf, "on", 2) == 0 ||
            strnicmp(buf, "1", 1) == 0) {
                debug = 1;
-               printk(KERN_DEBUG "s3c2410fb: Debug On");
+               dev_dbg(dev, "s3c2410fb: Debug On");
        } else if (strnicmp(buf, "off", 3) == 0 ||
                   strnicmp(buf, "0", 1) == 0) {
                debug = 0;
-               printk(KERN_DEBUG "s3c2410fb: Debug Off");
+               dev_dbg(dev, "s3c2410fb: Debug Off");
        } else {
                return -EINVAL;
        }
@@ -921,7 +927,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
 
        info->clk = clk_get(NULL, "lcd");
        if (IS_ERR(info->clk)) {
-               printk(KERN_ERR "failed to get lcd clock source\n");
+               dev_err(&pdev->dev, "failed to get lcd clock source\n");
                ret = PTR_ERR(info->clk);
                goto release_irq;
        }
@@ -929,7 +935,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
        clk_enable(info->clk);
        dprintk("got and enabled clock\n");
 
-       usleep_range(1000, 1000);
+       usleep_range(1000, 1100);
 
        info->clk_rate = clk_get_rate(info->clk);
 
@@ -947,7 +953,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
        /* Initialize video memory */
        ret = s3c2410fb_map_video_memory(fbinfo);
        if (ret) {
-               printk(KERN_ERR "Failed to allocate video RAM: %d\n", ret);
+               dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret);
                ret = -ENOMEM;
                goto release_clock;
        }
@@ -970,7 +976,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
 
        ret = register_framebuffer(fbinfo);
        if (ret < 0) {
-               printk(KERN_ERR "Failed to register framebuffer device: %d\n",
+               dev_err(&pdev->dev, "Failed to register framebuffer device: %d\n",
                        ret);
                goto free_cpufreq;
        }
@@ -978,9 +984,9 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
        /* create device files */
        ret = device_create_file(&pdev->dev, &dev_attr_debug);
        if (ret)
-               printk(KERN_ERR "failed to add debug attribute\n");
+               dev_err(&pdev->dev, "failed to add debug attribute\n");
 
-       printk(KERN_INFO "fb%d: %s frame buffer device\n",
+       dev_info(&pdev->dev, "fb%d: %s frame buffer device\n",
                fbinfo->node, fbinfo->fix.id);
 
        return 0;
@@ -1028,7 +1034,7 @@ static int __devexit s3c2410fb_remove(struct platform_device *pdev)
        s3c2410fb_cpufreq_deregister(info);
 
        s3c2410fb_lcd_enable(info, 0);
-       usleep_range(1000, 1000);
+       usleep_range(1000, 1100);
 
        s3c2410fb_unmap_video_memory(fbinfo);
 
@@ -1065,7 +1071,7 @@ static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state)
         * the LCD DMA engine is not going to get back on the bus
         * before the clock goes off again (bjd) */
 
-       usleep_range(1000, 1000);
+       usleep_range(1000, 1100);
        clk_disable(info->clk);
 
        return 0;
@@ -1077,7 +1083,7 @@ static int s3c2410fb_resume(struct platform_device *dev)
        struct s3c2410fb_info *info = fbinfo->par;
 
        clk_enable(info->clk);
-       usleep_range(1000, 1000);
+       usleep_range(1000, 1100);
 
        s3c2410fb_init_registers(fbinfo);
 
@@ -1134,8 +1140,8 @@ static void __exit s3c2410fb_cleanup(void)
 module_init(s3c2410fb_init);
 module_exit(s3c2410fb_cleanup);
 
-MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, "
-             "Ben Dooks <ben-linux@fluff.org>");
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
+MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
 MODULE_DESCRIPTION("Framebuffer driver for the s3c2410");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:s3c2410-lcd");
index 0d0f52c18fd8b56eca8836dea944601fe0047070..f4f53b082d0546b9e7c5ff21df2be606991a4152 100644 (file)
@@ -2266,8 +2266,10 @@ static int __devinit savagefb_probe(struct pci_dev* dev,
        lpitch = info->var.xres_virtual*((info->var.bits_per_pixel + 7) >> 3);
        info->var.yres_virtual = info->fix.smem_len/lpitch;
 
-       if (info->var.yres_virtual < info->var.yres)
+       if (info->var.yres_virtual < info->var.yres) {
+               err = -ENOMEM;
                goto failed;
+       }
 
 #if defined(CONFIG_FB_SAVAGE_ACCEL)
        /*
index 9dec64da401593097b4432e6bf846187ca864ddc..3ab18f5a3759b219ca99048282db9092609685c7 100644 (file)
@@ -65,7 +65,7 @@ sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno,
     }
 #endif
 
-    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {;
+    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {
        printk(KERN_ERR "Could not find mode %x\n", ModeNo);
        return 65000;
     }
index b7f27acaf817075e0ccde9e8108e296c2184f792..729a50722bdfb05138983fbf50c0e74145a97f6d 100644 (file)
@@ -141,8 +141,10 @@ static int __devinit gfb_probe(struct platform_device *op)
 
        gp->fb_base = of_ioremap(&op->resource[6], 0,
                                 gp->fb_size, "gfb fb");
-       if (!gp->fb_base)
+       if (!gp->fb_base) {
+               err = -ENOMEM;
                goto err_release_fb;
+       }
 
        err = gfb_set_fbinfo(gp);
        if (err)
index 5848436c19da294040fd3e5a9e652809b89b702b..7fbcba86d1a223c185069297b9a96033d70deded 100644 (file)
@@ -181,8 +181,10 @@ static int __devinit s3d_pci_register(struct pci_dev *pdev,
        sp->fb_size = info->fix.line_length * sp->height;
 
        sp->fb_base = ioremap(sp->fb_base_phys, sp->fb_size);
-       if (!sp->fb_base)
+       if (!sp->fb_base) {
+               err = -ENOMEM;
                goto err_release_pci;
+       }
 
        err = s3d_set_fbinfo(sp);
        if (err)
index eb931b8626fac98b505506ea5db46d0d8cc1b338..6c71b1b44477322eb1a45b312aa8a0b780e3f9ad 100644 (file)
@@ -298,8 +298,10 @@ static int __devinit e3d_pci_register(struct pci_dev *pdev,
                goto err_release_fb;
        }
        ep->ramdac = ioremap(ep->regs_base_phys + 0x8000, 0x1000);
-       if (!ep->ramdac)
+       if (!ep->ramdac) {
+               err = -ENOMEM;
                goto err_release_pci1;
+       }
 
        ep->fb8_0_off = readl(ep->ramdac + RAMDAC_VID_8FB_0);
        ep->fb8_0_off -= ep->fb_base_reg;
@@ -343,8 +345,10 @@ static int __devinit e3d_pci_register(struct pci_dev *pdev,
        ep->fb_size = info->fix.line_length * ep->height;
 
        ep->fb_base = ioremap(ep->fb_base_phys, ep->fb_size);
-       if (!ep->fb_base)
+       if (!ep->fb_base) {
+               err = -ENOMEM;
                goto err_release_pci0;
+       }
 
        err = e3d_set_fbinfo(ep);
        if (err)
index f45eba3d6150f73b6e12a3e78bba58dd389a3a90..86d449ea31699db3c7e7c5f1a7bfc1a41c2b5d83 100644 (file)
@@ -646,7 +646,7 @@ static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf,
        result = fb_sys_write(info, buf, count, ppos);
 
        if (result > 0) {
-               int start = max((int)(offset / info->fix.line_length) - 1, 0);
+               int start = max((int)(offset / info->fix.line_length), 0);
                int lines = min((u32)((result / info->fix.line_length) + 1),
                                (u32)info->var.yres);
 
index b0e2a4261afec5cd64f524f29807a3cbe70da2d8..2f8f82d874a15995b375a7250d5eb259711d9a69 100644 (file)
@@ -659,6 +659,8 @@ static int __devinit uvesafb_vbe_getedid(struct uvesafb_ktask *task,
        task->t.flags = TF_BUF_RET | TF_BUF_ESDI;
        task->t.buf_len = EDID_LENGTH;
        task->buf = kzalloc(EDID_LENGTH, GFP_KERNEL);
+       if (!task->buf)
+               return -ENOMEM;
 
        err = uvesafb_exec(task);
 
index 89aef343e2951b71f3a34d4377aa7aaa27b63fcb..4709edc3cb7f3057f7de9d8d63555f3fd1aa2cea 100644 (file)
@@ -1167,8 +1167,7 @@ void vmlfb_unregister_subsys(struct vml_sys *sys)
        list_for_each_entry_safe(entry, next, &global_has_mode, head) {
                printk(KERN_DEBUG MODULE_NAME ": subsys disable pipe\n");
                vmlfb_disable_pipe(entry);
-               list_del(&entry->head);
-               list_add_tail(&entry->head, &global_no_mode);
+               list_move_tail(&entry->head, &global_no_mode);
        }
        mutex_unlock(&vml_mutex);
 }
index af8f26b643c15cb8510022d53db9144969907697..db1e39277e321f37a39b690d4f6f0d5638325376 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <linux/kernel.h>
 #include <linux/via-core.h>
+#include <asm/olpc.h>
 #include "via_clock.h"
 #include "global.h"
 #include "debug.h"
@@ -289,6 +290,10 @@ static void dummy_set_pll(struct via_pll_config config)
        printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap);
 }
 
+static void noop_set_clock_state(u8 state)
+{
+}
+
 void via_clock_init(struct via_clock *clock, int gfx_chip)
 {
        switch (gfx_chip) {
@@ -346,4 +351,18 @@ void via_clock_init(struct via_clock *clock, int gfx_chip)
                break;
 
        }
+
+       if (machine_is_olpc()) {
+               /* The OLPC XO-1.5 cannot suspend/resume reliably if the
+                * IGA1/IGA2 clocks are set as on or off (memory rot
+                * occasionally happens during suspend under such
+                * configurations).
+                *
+                * The only known stable scenario is to leave this bits as-is,
+                * which in their default states are documented to enable the
+                * clock only when it is needed.
+                */
+               clock->set_primary_clock_state = noop_set_clock_state;
+               clock->set_secondary_clock_state = noop_set_clock_state;
+       }
 }
index 131dec04794ee3ee1af70c2fd3f1dd2220774070..48220e129f854435292065c5e928f95d982a4ad3 100644 (file)
@@ -48,6 +48,7 @@
 #include <xen/xenbus.h>
 #include <xen/xen.h>
 #include "xenbus_comms.h"
+#include <asm/xen/hypervisor.h>
 
 struct xs_stored_msg {
        struct list_head list;
@@ -618,7 +619,24 @@ static struct xenbus_watch *find_watch(const char *token)
 
        return NULL;
 }
+/*
+ * Certain older XenBus toolstack cannot handle reading values that are
+ * not populated. Some Xen 3.4 installation are incapable of doing this
+ * so if we are running on anything older than 4 do not attempt to read
+ * control/platform-feature-xs_reset_watches.
+ */
+static bool xen_strict_xenbus_quirk()
+{
+       uint32_t eax, ebx, ecx, edx, base;
+
+       base = xen_cpuid_base();
+       cpuid(base + 1, &eax, &ebx, &ecx, &edx);
 
+       if ((eax >> 16) < 4)
+               return true;
+       return false;
+
+}
 static void xs_reset_watches(void)
 {
        int err, supported = 0;
@@ -626,6 +644,9 @@ static void xs_reset_watches(void)
        if (!xen_hvm_domain() || xen_initial_domain())
                return;
 
+       if (xen_strict_xenbus_quirk())
+               return;
+
        err = xenbus_scanf(XBT_NIL, "control",
                        "platform-feature-xs_reset_watches", "%d", &supported);
        if (err != 1 || !supported)
index 392c5dac1981be79b4aff040e552b48c78c5751f..d934f04e77368e00dc76d4a54720cff0758d3a58 100644 (file)
@@ -184,10 +184,20 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
                        v9ses->afid = option;
                        break;
                case Opt_uname:
-                       match_strlcpy(v9ses->uname, &args[0], PATH_MAX);
+                       kfree(v9ses->uname);
+                       v9ses->uname = match_strdup(&args[0]);
+                       if (!v9ses->uname) {
+                               ret = -ENOMEM;
+                               goto free_and_return;
+                       }
                        break;
                case Opt_remotename:
-                       match_strlcpy(v9ses->aname, &args[0], PATH_MAX);
+                       kfree(v9ses->aname);
+                       v9ses->aname = match_strdup(&args[0]);
+                       if (!v9ses->aname) {
+                               ret = -ENOMEM;
+                               goto free_and_return;
+                       }
                        break;
                case Opt_nodevmap:
                        v9ses->nodev = 1;
@@ -287,21 +297,21 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
        struct p9_fid *fid;
        int rc;
 
-       v9ses->uname = __getname();
+       v9ses->uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL);
        if (!v9ses->uname)
                return ERR_PTR(-ENOMEM);
 
-       v9ses->aname = __getname();
+       v9ses->aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL);
        if (!v9ses->aname) {
-               __putname(v9ses->uname);
+               kfree(v9ses->uname);
                return ERR_PTR(-ENOMEM);
        }
        init_rwsem(&v9ses->rename_sem);
 
        rc = bdi_setup_and_register(&v9ses->bdi, "9p", BDI_CAP_MAP_COPY);
        if (rc) {
-               __putname(v9ses->aname);
-               __putname(v9ses->uname);
+               kfree(v9ses->aname);
+               kfree(v9ses->uname);
                return ERR_PTR(rc);
        }
 
@@ -309,8 +319,6 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
        list_add(&v9ses->slist, &v9fs_sessionlist);
        spin_unlock(&v9fs_sessionlist_lock);
 
-       strcpy(v9ses->uname, V9FS_DEFUSER);
-       strcpy(v9ses->aname, V9FS_DEFANAME);
        v9ses->uid = ~0;
        v9ses->dfltuid = V9FS_DEFUID;
        v9ses->dfltgid = V9FS_DEFGID;
@@ -412,8 +420,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
                kfree(v9ses->cachetag);
        }
 #endif
-       __putname(v9ses->uname);
-       __putname(v9ses->aname);
+       kfree(v9ses->uname);
+       kfree(v9ses->aname);
 
        bdi_destroy(&v9ses->bdi);
 
index cbf9dbb1b2a270f4ebd911f7b1aca3d0107969e3..890bed538f9b6417aebbb1e5a2780c0f209ebd17 100644 (file)
@@ -1276,12 +1276,12 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
        }
 
        /* copy extension buffer into buffer */
-       strncpy(buffer, st->extension, buflen);
+       retval = min(strlen(st->extension)+1, (size_t)buflen);
+       memcpy(buffer, st->extension, retval);
 
-       p9_debug(P9_DEBUG_VFS, "%s -> %s (%s)\n",
-                dentry->d_name.name, st->extension, buffer);
+       p9_debug(P9_DEBUG_VFS, "%s -> %s (%.*s)\n",
+                dentry->d_name.name, st->extension, buflen, buffer);
 
-       retval = strnlen(buffer, buflen);
 done:
        p9stat_free(st);
        kfree(st);
index e7396cfdb10999b453567231e433451cb6aecc2f..91b11650722e517e2066219fac803aefdae78470 100644 (file)
@@ -392,10 +392,12 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
                ino->flags |= AUTOFS_INF_PENDING;
                spin_unlock(&sbi->fs_lock);
                status = autofs4_mount_wait(dentry);
-               if (status)
-                       return ERR_PTR(status);
                spin_lock(&sbi->fs_lock);
                ino->flags &= ~AUTOFS_INF_PENDING;
+               if (status) {
+                       spin_unlock(&sbi->fs_lock);
+                       return ERR_PTR(status);
+               }
        }
 done:
        if (!(ino->flags & AUTOFS_INF_EXPIRING)) {
index e800dec958c3273ea91aea2a865daa49d9874224..fbd9f60bd763310c452a08dbb34fc8bbf2515560 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/uaccess.h>
 #include <asm/param.h>
 #include <asm/page.h>
-#include <asm/exec.h>
 
 #ifndef user_long_t
 #define user_long_t long
index 262db114ff0162dd24761c842af617a017e992ea..a46049154107f549eaf3c987cab594db730116f4 100644 (file)
@@ -39,7 +39,6 @@
 #include <asm/uaccess.h>
 #include <asm/param.h>
 #include <asm/pgalloc.h>
-#include <asm/exec.h>
 
 typedef char *elf_caddr_t;
 
index e85c04b9f61c59705d297c5eb137a2b046865e88..a3f28f331b2bba7e6653da30dce92adba5d97140 100644 (file)
@@ -70,23 +70,25 @@ static inline int use_bip_pool(unsigned int idx)
 }
 
 /**
- * bio_integrity_alloc_bioset - Allocate integrity payload and attach it to bio
+ * bio_integrity_alloc - Allocate integrity payload and attach it to bio
  * @bio:       bio to attach integrity metadata to
  * @gfp_mask:  Memory allocation mask
  * @nr_vecs:   Number of integrity metadata scatter-gather elements
- * @bs:                bio_set to allocate from
  *
  * Description: This function prepares a bio for attaching integrity
  * metadata.  nr_vecs specifies the maximum number of pages containing
  * integrity metadata that can be attached.
  */
-struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *bio,
-                                                        gfp_t gfp_mask,
-                                                        unsigned int nr_vecs,
-                                                        struct bio_set *bs)
+struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
+                                                 gfp_t gfp_mask,
+                                                 unsigned int nr_vecs)
 {
        struct bio_integrity_payload *bip;
        unsigned int idx = vecs_to_idx(nr_vecs);
+       struct bio_set *bs = bio->bi_pool;
+
+       if (!bs)
+               bs = fs_bio_set;
 
        BUG_ON(bio == NULL);
        bip = NULL;
@@ -114,37 +116,22 @@ struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *bio,
 
        return bip;
 }
-EXPORT_SYMBOL(bio_integrity_alloc_bioset);
-
-/**
- * bio_integrity_alloc - Allocate integrity payload and attach it to bio
- * @bio:       bio to attach integrity metadata to
- * @gfp_mask:  Memory allocation mask
- * @nr_vecs:   Number of integrity metadata scatter-gather elements
- *
- * Description: This function prepares a bio for attaching integrity
- * metadata.  nr_vecs specifies the maximum number of pages containing
- * integrity metadata that can be attached.
- */
-struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
-                                                 gfp_t gfp_mask,
-                                                 unsigned int nr_vecs)
-{
-       return bio_integrity_alloc_bioset(bio, gfp_mask, nr_vecs, fs_bio_set);
-}
 EXPORT_SYMBOL(bio_integrity_alloc);
 
 /**
  * bio_integrity_free - Free bio integrity payload
  * @bio:       bio containing bip to be freed
- * @bs:                bio_set this bio was allocated from
  *
  * Description: Used to free the integrity portion of a bio. Usually
  * called from bio_free().
  */
-void bio_integrity_free(struct bio *bio, struct bio_set *bs)
+void bio_integrity_free(struct bio *bio)
 {
        struct bio_integrity_payload *bip = bio->bi_integrity;
+       struct bio_set *bs = bio->bi_pool;
+
+       if (!bs)
+               bs = fs_bio_set;
 
        BUG_ON(bip == NULL);
 
@@ -730,19 +717,18 @@ EXPORT_SYMBOL(bio_integrity_split);
  * @bio:       New bio
  * @bio_src:   Original bio
  * @gfp_mask:  Memory allocation mask
- * @bs:                bio_set to allocate bip from
  *
  * Description:        Called to allocate a bip when cloning a bio
  */
 int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
-                       gfp_t gfp_mask, struct bio_set *bs)
+                       gfp_t gfp_mask)
 {
        struct bio_integrity_payload *bip_src = bio_src->bi_integrity;
        struct bio_integrity_payload *bip;
 
        BUG_ON(bip_src == NULL);
 
-       bip = bio_integrity_alloc_bioset(bio, gfp_mask, bip_src->bip_vcnt, bs);
+       bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt);
 
        if (bip == NULL)
                return -EIO;
index 71072ab99128aadf1090e2ceab32bae67827dc9c..9298c65ad9c74bb1c4adde9ef9ffa07b397ca63f 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -55,6 +55,7 @@ static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = {
  * IO code that does not need private memory pools.
  */
 struct bio_set *fs_bio_set;
+EXPORT_SYMBOL(fs_bio_set);
 
 /*
  * Our slab pool management
@@ -233,26 +234,37 @@ fallback:
        return bvl;
 }
 
-void bio_free(struct bio *bio, struct bio_set *bs)
+static void __bio_free(struct bio *bio)
 {
+       bio_disassociate_task(bio);
+
+       if (bio_integrity(bio))
+               bio_integrity_free(bio);
+}
+
+static void bio_free(struct bio *bio)
+{
+       struct bio_set *bs = bio->bi_pool;
        void *p;
 
-       if (bio_has_allocated_vec(bio))
-               bvec_free_bs(bs, bio->bi_io_vec, BIO_POOL_IDX(bio));
+       __bio_free(bio);
 
-       if (bio_integrity(bio))
-               bio_integrity_free(bio, bs);
+       if (bs) {
+               if (bio_has_allocated_vec(bio))
+                       bvec_free_bs(bs, bio->bi_io_vec, BIO_POOL_IDX(bio));
 
-       /*
-        * If we have front padding, adjust the bio pointer before freeing
-        */
-       p = bio;
-       if (bs->front_pad)
+               /*
+                * If we have front padding, adjust the bio pointer before freeing
+                */
+               p = bio;
                p -= bs->front_pad;
 
-       mempool_free(p, bs->bio_pool);
+               mempool_free(p, bs->bio_pool);
+       } else {
+               /* Bio was allocated by bio_kmalloc() */
+               kfree(bio);
+       }
 }
-EXPORT_SYMBOL(bio_free);
 
 void bio_init(struct bio *bio)
 {
@@ -262,6 +274,27 @@ void bio_init(struct bio *bio)
 }
 EXPORT_SYMBOL(bio_init);
 
+/**
+ * bio_reset - reinitialize a bio
+ * @bio:       bio to reset
+ *
+ * Description:
+ *   After calling bio_reset(), @bio will be in the same state as a freshly
+ *   allocated bio returned bio bio_alloc_bioset() - the only fields that are
+ *   preserved are the ones that are initialized by bio_alloc_bioset(). See
+ *   comment in struct bio.
+ */
+void bio_reset(struct bio *bio)
+{
+       unsigned long flags = bio->bi_flags & (~0UL << BIO_RESET_BITS);
+
+       __bio_free(bio);
+
+       memset(bio, 0, BIO_RESET_BYTES);
+       bio->bi_flags = flags|(1 << BIO_UPTODATE);
+}
+EXPORT_SYMBOL(bio_reset);
+
 /**
  * bio_alloc_bioset - allocate a bio for I/O
  * @gfp_mask:   the GFP_ mask given to the slab allocator
@@ -269,42 +302,58 @@ EXPORT_SYMBOL(bio_init);
  * @bs:                the bio_set to allocate from.
  *
  * Description:
- *   bio_alloc_bioset will try its own mempool to satisfy the allocation.
- *   If %__GFP_WAIT is set then we will block on the internal pool waiting
- *   for a &struct bio to become free.
+ *   If @bs is NULL, uses kmalloc() to allocate the bio; else the allocation is
+ *   backed by the @bs's mempool.
  *
- *   Note that the caller must set ->bi_destructor on successful return
- *   of a bio, to do the appropriate freeing of the bio once the reference
- *   count drops to zero.
- **/
+ *   When @bs is not NULL, if %__GFP_WAIT is set then bio_alloc will always be
+ *   able to allocate a bio. This is due to the mempool guarantees. To make this
+ *   work, callers must never allocate more than 1 bio at a time from this pool.
+ *   Callers that need to allocate more than 1 bio must always submit the
+ *   previously allocated bio for IO before attempting to allocate a new one.
+ *   Failure to do so can cause deadlocks under memory pressure.
+ *
+ *   RETURNS:
+ *   Pointer to new bio on success, NULL on failure.
+ */
 struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
 {
+       unsigned front_pad;
+       unsigned inline_vecs;
        unsigned long idx = BIO_POOL_NONE;
        struct bio_vec *bvl = NULL;
        struct bio *bio;
        void *p;
 
-       p = mempool_alloc(bs->bio_pool, gfp_mask);
+       if (!bs) {
+               if (nr_iovecs > UIO_MAXIOV)
+                       return NULL;
+
+               p = kmalloc(sizeof(struct bio) +
+                           nr_iovecs * sizeof(struct bio_vec),
+                           gfp_mask);
+               front_pad = 0;
+               inline_vecs = nr_iovecs;
+       } else {
+               p = mempool_alloc(bs->bio_pool, gfp_mask);
+               front_pad = bs->front_pad;
+               inline_vecs = BIO_INLINE_VECS;
+       }
+
        if (unlikely(!p))
                return NULL;
-       bio = p + bs->front_pad;
 
+       bio = p + front_pad;
        bio_init(bio);
 
-       if (unlikely(!nr_iovecs))
-               goto out_set;
-
-       if (nr_iovecs <= BIO_INLINE_VECS) {
-               bvl = bio->bi_inline_vecs;
-               nr_iovecs = BIO_INLINE_VECS;
-       } else {
+       if (nr_iovecs > inline_vecs) {
                bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs);
                if (unlikely(!bvl))
                        goto err_free;
-
-               nr_iovecs = bvec_nr_vecs(idx);
+       } else if (nr_iovecs) {
+               bvl = bio->bi_inline_vecs;
        }
-out_set:
+
+       bio->bi_pool = bs;
        bio->bi_flags |= idx << BIO_POOL_OFFSET;
        bio->bi_max_vecs = nr_iovecs;
        bio->bi_io_vec = bvl;
@@ -316,80 +365,6 @@ err_free:
 }
 EXPORT_SYMBOL(bio_alloc_bioset);
 
-static void bio_fs_destructor(struct bio *bio)
-{
-       bio_free(bio, fs_bio_set);
-}
-
-/**
- *     bio_alloc - allocate a new bio, memory pool backed
- *     @gfp_mask: allocation mask to use
- *     @nr_iovecs: number of iovecs
- *
- *     bio_alloc will allocate a bio and associated bio_vec array that can hold
- *     at least @nr_iovecs entries. Allocations will be done from the
- *     fs_bio_set. Also see @bio_alloc_bioset and @bio_kmalloc.
- *
- *     If %__GFP_WAIT is set, then bio_alloc will always be able to allocate
- *     a bio. This is due to the mempool guarantees. To make this work, callers
- *     must never allocate more than 1 bio at a time from this pool. Callers
- *     that need to allocate more than 1 bio must always submit the previously
- *     allocated bio for IO before attempting to allocate a new one. Failure to
- *     do so can cause livelocks under memory pressure.
- *
- *     RETURNS:
- *     Pointer to new bio on success, NULL on failure.
- */
-struct bio *bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs)
-{
-       struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
-
-       if (bio)
-               bio->bi_destructor = bio_fs_destructor;
-
-       return bio;
-}
-EXPORT_SYMBOL(bio_alloc);
-
-static void bio_kmalloc_destructor(struct bio *bio)
-{
-       if (bio_integrity(bio))
-               bio_integrity_free(bio, fs_bio_set);
-       kfree(bio);
-}
-
-/**
- * bio_kmalloc - allocate a bio for I/O using kmalloc()
- * @gfp_mask:   the GFP_ mask given to the slab allocator
- * @nr_iovecs: number of iovecs to pre-allocate
- *
- * Description:
- *   Allocate a new bio with @nr_iovecs bvecs.  If @gfp_mask contains
- *   %__GFP_WAIT, the allocation is guaranteed to succeed.
- *
- **/
-struct bio *bio_kmalloc(gfp_t gfp_mask, unsigned int nr_iovecs)
-{
-       struct bio *bio;
-
-       if (nr_iovecs > UIO_MAXIOV)
-               return NULL;
-
-       bio = kmalloc(sizeof(struct bio) + nr_iovecs * sizeof(struct bio_vec),
-                     gfp_mask);
-       if (unlikely(!bio))
-               return NULL;
-
-       bio_init(bio);
-       bio->bi_flags |= BIO_POOL_NONE << BIO_POOL_OFFSET;
-       bio->bi_max_vecs = nr_iovecs;
-       bio->bi_io_vec = bio->bi_inline_vecs;
-       bio->bi_destructor = bio_kmalloc_destructor;
-
-       return bio;
-}
-EXPORT_SYMBOL(bio_kmalloc);
-
 void zero_fill_bio(struct bio *bio)
 {
        unsigned long flags;
@@ -420,11 +395,8 @@ void bio_put(struct bio *bio)
        /*
         * last put frees it
         */
-       if (atomic_dec_and_test(&bio->bi_cnt)) {
-               bio_disassociate_task(bio);
-               bio->bi_next = NULL;
-               bio->bi_destructor(bio);
-       }
+       if (atomic_dec_and_test(&bio->bi_cnt))
+               bio_free(bio);
 }
 EXPORT_SYMBOL(bio_put);
 
@@ -466,26 +438,28 @@ void __bio_clone(struct bio *bio, struct bio *bio_src)
 EXPORT_SYMBOL(__bio_clone);
 
 /**
- *     bio_clone       -       clone a bio
+ *     bio_clone_bioset -      clone a bio
  *     @bio: bio to clone
  *     @gfp_mask: allocation priority
+ *     @bs: bio_set to allocate from
  *
  *     Like __bio_clone, only also allocates the returned bio
  */
-struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask)
+struct bio *bio_clone_bioset(struct bio *bio, gfp_t gfp_mask,
+                            struct bio_set *bs)
 {
-       struct bio *b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs, fs_bio_set);
+       struct bio *b;
 
+       b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs, bs);
        if (!b)
                return NULL;
 
-       b->bi_destructor = bio_fs_destructor;
        __bio_clone(b, bio);
 
        if (bio_integrity(bio)) {
                int ret;
 
-               ret = bio_integrity_clone(b, bio, gfp_mask, fs_bio_set);
+               ret = bio_integrity_clone(b, bio, gfp_mask);
 
                if (ret < 0) {
                        bio_put(b);
@@ -495,7 +469,7 @@ struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask)
 
        return b;
 }
-EXPORT_SYMBOL(bio_clone);
+EXPORT_SYMBOL(bio_clone_bioset);
 
 /**
  *     bio_get_nr_vecs         - return approx number of vecs
@@ -1501,7 +1475,7 @@ struct bio_pair *bio_split(struct bio *bi, int first_sectors)
        trace_block_split(bdev_get_queue(bi->bi_bdev), bi,
                                bi->bi_sector + first_sectors);
 
-       BUG_ON(bi->bi_vcnt != 1);
+       BUG_ON(bi->bi_vcnt != 1 && bi->bi_vcnt != 0);
        BUG_ON(bi->bi_idx != 0);
        atomic_set(&bp->cnt, 3);
        bp->error = 0;
@@ -1511,17 +1485,22 @@ struct bio_pair *bio_split(struct bio *bi, int first_sectors)
        bp->bio2.bi_size -= first_sectors << 9;
        bp->bio1.bi_size = first_sectors << 9;
 
-       bp->bv1 = bi->bi_io_vec[0];
-       bp->bv2 = bi->bi_io_vec[0];
-       bp->bv2.bv_offset += first_sectors << 9;
-       bp->bv2.bv_len -= first_sectors << 9;
-       bp->bv1.bv_len = first_sectors << 9;
+       if (bi->bi_vcnt != 0) {
+               bp->bv1 = bi->bi_io_vec[0];
+               bp->bv2 = bi->bi_io_vec[0];
+
+               if (bio_is_rw(bi)) {
+                       bp->bv2.bv_offset += first_sectors << 9;
+                       bp->bv2.bv_len -= first_sectors << 9;
+                       bp->bv1.bv_len = first_sectors << 9;
+               }
 
-       bp->bio1.bi_io_vec = &bp->bv1;
-       bp->bio2.bi_io_vec = &bp->bv2;
+               bp->bio1.bi_io_vec = &bp->bv1;
+               bp->bio2.bi_io_vec = &bp->bv2;
 
-       bp->bio1.bi_max_vecs = 1;
-       bp->bio2.bi_max_vecs = 1;
+               bp->bio1.bi_max_vecs = 1;
+               bp->bio2.bi_max_vecs = 1;
+       }
 
        bp->bio1.bi_end_io = bio_pair_end_1;
        bp->bio2.bi_end_io = bio_pair_end_2;
index 38e721b35d45388cb0febed8021a02277a4a2f1b..b3c1d3dae77d06fcde3fa3ecf36b2af9e2b25d85 100644 (file)
@@ -116,6 +116,8 @@ EXPORT_SYMBOL(invalidate_bdev);
 
 int set_blocksize(struct block_device *bdev, int size)
 {
+       struct address_space *mapping;
+
        /* Size must be a power of two, and between 512 and PAGE_SIZE */
        if (size > PAGE_SIZE || size < 512 || !is_power_of_2(size))
                return -EINVAL;
@@ -124,6 +126,19 @@ int set_blocksize(struct block_device *bdev, int size)
        if (size < bdev_logical_block_size(bdev))
                return -EINVAL;
 
+       /* Prevent starting I/O or mapping the device */
+       percpu_down_write(&bdev->bd_block_size_semaphore);
+
+       /* Check that the block device is not memory mapped */
+       mapping = bdev->bd_inode->i_mapping;
+       mutex_lock(&mapping->i_mmap_mutex);
+       if (mapping_mapped(mapping)) {
+               mutex_unlock(&mapping->i_mmap_mutex);
+               percpu_up_write(&bdev->bd_block_size_semaphore);
+               return -EBUSY;
+       }
+       mutex_unlock(&mapping->i_mmap_mutex);
+
        /* Don't change the size if it is same as current */
        if (bdev->bd_block_size != size) {
                sync_blockdev(bdev);
@@ -131,6 +146,9 @@ int set_blocksize(struct block_device *bdev, int size)
                bdev->bd_inode->i_blkbits = blksize_bits(size);
                kill_bdev(bdev);
        }
+
+       percpu_up_write(&bdev->bd_block_size_semaphore);
+
        return 0;
 }
 
@@ -441,6 +459,12 @@ static struct inode *bdev_alloc_inode(struct super_block *sb)
        struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
+
+       if (unlikely(percpu_init_rwsem(&ei->bdev.bd_block_size_semaphore))) {
+               kmem_cache_free(bdev_cachep, ei);
+               return NULL;
+       }
+
        return &ei->vfs_inode;
 }
 
@@ -449,6 +473,8 @@ static void bdev_i_callback(struct rcu_head *head)
        struct inode *inode = container_of(head, struct inode, i_rcu);
        struct bdev_inode *bdi = BDEV_I(inode);
 
+       percpu_free_rwsem(&bdi->bdev.bd_block_size_semaphore);
+
        kmem_cache_free(bdev_cachep, bdi);
 }
 
@@ -1567,6 +1593,22 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
        return blkdev_ioctl(bdev, mode, cmd, arg);
 }
 
+ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov,
+                       unsigned long nr_segs, loff_t pos)
+{
+       ssize_t ret;
+       struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host);
+
+       percpu_down_read(&bdev->bd_block_size_semaphore);
+
+       ret = generic_file_aio_read(iocb, iov, nr_segs, pos);
+
+       percpu_up_read(&bdev->bd_block_size_semaphore);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(blkdev_aio_read);
+
 /*
  * Write data to the block device.  Only intended for the block device itself
  * and the raw driver which basically is a fake block device.
@@ -1578,12 +1620,16 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
                         unsigned long nr_segs, loff_t pos)
 {
        struct file *file = iocb->ki_filp;
+       struct block_device *bdev = I_BDEV(file->f_mapping->host);
        struct blk_plug plug;
        ssize_t ret;
 
        BUG_ON(iocb->ki_pos != pos);
 
        blk_start_plug(&plug);
+
+       percpu_down_read(&bdev->bd_block_size_semaphore);
+
        ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
        if (ret > 0 || ret == -EIOCBQUEUED) {
                ssize_t err;
@@ -1592,11 +1638,29 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
                if (err < 0 && ret > 0)
                        ret = err;
        }
+
+       percpu_up_read(&bdev->bd_block_size_semaphore);
+
        blk_finish_plug(&plug);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(blkdev_aio_write);
 
+static int blkdev_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       int ret;
+       struct block_device *bdev = I_BDEV(file->f_mapping->host);
+
+       percpu_down_read(&bdev->bd_block_size_semaphore);
+
+       ret = generic_file_mmap(file, vma);
+
+       percpu_up_read(&bdev->bd_block_size_semaphore);
+
+       return ret;
+}
+
 /*
  * Try to release a page associated with block device when the system
  * is under memory pressure.
@@ -1627,9 +1691,9 @@ const struct file_operations def_blk_fops = {
        .llseek         = block_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
-       .aio_read       = generic_file_aio_read,
+       .aio_read       = blkdev_aio_read,
        .aio_write      = blkdev_aio_write,
-       .mmap           = generic_file_mmap,
+       .mmap           = blkdev_mmap,
        .fsync          = blkdev_fsync,
        .unlocked_ioctl = block_ioctl,
 #ifdef CONFIG_COMPAT
index ff6475f409d64aaade5499f9d0cee64c2989a80c..f3187938e081c7dcbf842d424f5de6ed06d3f93f 100644 (file)
@@ -16,6 +16,7 @@
  * Boston, MA 021110-1307, USA.
  */
 
+#include <linux/vmalloc.h>
 #include "ctree.h"
 #include "disk-io.h"
 #include "backref.h"
@@ -231,7 +232,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
                        }
                        if (!ret) {
                                ret = ulist_add(parents, eb->start,
-                                               (unsigned long)eie, GFP_NOFS);
+                                               (uintptr_t)eie, GFP_NOFS);
                                if (ret < 0)
                                        break;
                                if (!extent_item_pos) {
@@ -363,8 +364,8 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info,
                ULIST_ITER_INIT(&uiter);
                node = ulist_next(parents, &uiter);
                ref->parent = node ? node->val : 0;
-               ref->inode_list =
-                       node ? (struct extent_inode_elem *)node->aux : 0;
+               ref->inode_list = node ?
+                       (struct extent_inode_elem *)(uintptr_t)node->aux : 0;
 
                /* additional parents require new refs being added here */
                while ((node = ulist_next(parents, &uiter))) {
@@ -375,8 +376,8 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info,
                        }
                        memcpy(new_ref, ref, sizeof(*ref));
                        new_ref->parent = node->val;
-                       new_ref->inode_list =
-                                       (struct extent_inode_elem *)node->aux;
+                       new_ref->inode_list = (struct extent_inode_elem *)
+                                                       (uintptr_t)node->aux;
                        list_add(&new_ref->list, &ref->list);
                }
                ulist_reinit(parents);
@@ -914,8 +915,8 @@ again:
                                free_extent_buffer(eb);
                        }
                        ret = ulist_add_merge(refs, ref->parent,
-                                             (unsigned long)ref->inode_list,
-                                             (unsigned long *)&eie, GFP_NOFS);
+                                             (uintptr_t)ref->inode_list,
+                                             (u64 *)&eie, GFP_NOFS);
                        if (!ret && extent_item_pos) {
                                /*
                                 * we've recorded that parent, so we must extend
@@ -959,7 +960,7 @@ static void free_leaf_list(struct ulist *blocks)
        while ((node = ulist_next(blocks, &uiter))) {
                if (!node->aux)
                        continue;
-               eie = (struct extent_inode_elem *)node->aux;
+               eie = (struct extent_inode_elem *)(uintptr_t)node->aux;
                for (; eie; eie = eie_next) {
                        eie_next = eie->next;
                        kfree(eie);
@@ -1108,26 +1109,80 @@ static int inode_ref_info(u64 inum, u64 ioff, struct btrfs_root *fs_root,
                                found_key);
 }
 
-/*
- * this iterates to turn a btrfs_inode_ref into a full filesystem path. elements
- * of the path are separated by '/' and the path is guaranteed to be
- * 0-terminated. the path is only given within the current file system.
- * Therefore, it never starts with a '/'. the caller is responsible to provide
- * "size" bytes in "dest". the dest buffer will be filled backwards. finally,
- * the start point of the resulting string is returned. this pointer is within
- * dest, normally.
- * in case the path buffer would overflow, the pointer is decremented further
- * as if output was written to the buffer, though no more output is actually
- * generated. that way, the caller can determine how much space would be
- * required for the path to fit into the buffer. in that case, the returned
- * value will be smaller than dest. callers must check this!
- */
-char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
-                        struct btrfs_inode_ref *iref,
+int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid,
+                         u64 start_off, struct btrfs_path *path,
+                         struct btrfs_inode_extref **ret_extref,
+                         u64 *found_off)
+{
+       int ret, slot;
+       struct btrfs_key key;
+       struct btrfs_key found_key;
+       struct btrfs_inode_extref *extref;
+       struct extent_buffer *leaf;
+       unsigned long ptr;
+
+       key.objectid = inode_objectid;
+       btrfs_set_key_type(&key, BTRFS_INODE_EXTREF_KEY);
+       key.offset = start_off;
+
+       ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+       if (ret < 0)
+               return ret;
+
+       while (1) {
+               leaf = path->nodes[0];
+               slot = path->slots[0];
+               if (slot >= btrfs_header_nritems(leaf)) {
+                       /*
+                        * If the item at offset is not found,
+                        * btrfs_search_slot will point us to the slot
+                        * where it should be inserted. In our case
+                        * that will be the slot directly before the
+                        * next INODE_REF_KEY_V2 item. In the case
+                        * that we're pointing to the last slot in a
+                        * leaf, we must move one leaf over.
+                        */
+                       ret = btrfs_next_leaf(root, path);
+                       if (ret) {
+                               if (ret >= 1)
+                                       ret = -ENOENT;
+                               break;
+                       }
+                       continue;
+               }
+
+               btrfs_item_key_to_cpu(leaf, &found_key, slot);
+
+               /*
+                * Check that we're still looking at an extended ref key for
+                * this particular objectid. If we have different
+                * objectid or type then there are no more to be found
+                * in the tree and we can exit.
+                */
+               ret = -ENOENT;
+               if (found_key.objectid != inode_objectid)
+                       break;
+               if (btrfs_key_type(&found_key) != BTRFS_INODE_EXTREF_KEY)
+                       break;
+
+               ret = 0;
+               ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
+               extref = (struct btrfs_inode_extref *)ptr;
+               *ret_extref = extref;
+               if (found_off)
+                       *found_off = found_key.offset;
+               break;
+       }
+
+       return ret;
+}
+
+static char *ref_to_path(struct btrfs_root *fs_root,
+                        struct btrfs_path *path,
+                        u32 name_len, unsigned long name_off,
                         struct extent_buffer *eb_in, u64 parent,
                         char *dest, u32 size)
 {
-       u32 len;
        int slot;
        u64 next_inum;
        int ret;
@@ -1135,17 +1190,17 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
        struct extent_buffer *eb = eb_in;
        struct btrfs_key found_key;
        int leave_spinning = path->leave_spinning;
+       struct btrfs_inode_ref *iref;
 
        if (bytes_left >= 0)
                dest[bytes_left] = '\0';
 
        path->leave_spinning = 1;
        while (1) {
-               len = btrfs_inode_ref_name_len(eb, iref);
-               bytes_left -= len;
+               bytes_left -= name_len;
                if (bytes_left >= 0)
                        read_extent_buffer(eb, dest + bytes_left,
-                                               (unsigned long)(iref + 1), len);
+                                          name_off, name_len);
                if (eb != eb_in) {
                        btrfs_tree_read_unlock_blocking(eb);
                        free_extent_buffer(eb);
@@ -1155,6 +1210,7 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
                        ret = -ENOENT;
                if (ret)
                        break;
+
                next_inum = found_key.offset;
 
                /* regular exit ahead */
@@ -1170,8 +1226,11 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
                        btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
                }
                btrfs_release_path(path);
-
                iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref);
+
+               name_len = btrfs_inode_ref_name_len(eb, iref);
+               name_off = (unsigned long)(iref + 1);
+
                parent = next_inum;
                --bytes_left;
                if (bytes_left >= 0)
@@ -1187,13 +1246,40 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
        return dest + bytes_left;
 }
 
+/*
+ * this iterates to turn a btrfs_inode_ref into a full filesystem path. elements
+ * of the path are separated by '/' and the path is guaranteed to be
+ * 0-terminated. the path is only given within the current file system.
+ * Therefore, it never starts with a '/'. the caller is responsible to provide
+ * "size" bytes in "dest". the dest buffer will be filled backwards. finally,
+ * the start point of the resulting string is returned. this pointer is within
+ * dest, normally.
+ * in case the path buffer would overflow, the pointer is decremented further
+ * as if output was written to the buffer, though no more output is actually
+ * generated. that way, the caller can determine how much space would be
+ * required for the path to fit into the buffer. in that case, the returned
+ * value will be smaller than dest. callers must check this!
+ */
+char *btrfs_iref_to_path(struct btrfs_root *fs_root,
+                        struct btrfs_path *path,
+                        struct btrfs_inode_ref *iref,
+                        struct extent_buffer *eb_in, u64 parent,
+                        char *dest, u32 size)
+{
+       return ref_to_path(fs_root, path,
+                          btrfs_inode_ref_name_len(eb_in, iref),
+                          (unsigned long)(iref + 1),
+                          eb_in, parent, dest, size);
+}
+
 /*
  * this makes the path point to (logical EXTENT_ITEM *)
  * returns BTRFS_EXTENT_FLAG_DATA for data, BTRFS_EXTENT_FLAG_TREE_BLOCK for
  * tree blocks and <0 on error.
  */
 int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
-                       struct btrfs_path *path, struct btrfs_key *found_key)
+                       struct btrfs_path *path, struct btrfs_key *found_key,
+                       u64 *flags_ret)
 {
        int ret;
        u64 flags;
@@ -1237,10 +1323,17 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
                 (unsigned long long)found_key->objectid,
                 (unsigned long long)found_key->offset,
                 (unsigned long long)flags, item_size);
-       if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)
-               return BTRFS_EXTENT_FLAG_TREE_BLOCK;
-       if (flags & BTRFS_EXTENT_FLAG_DATA)
-               return BTRFS_EXTENT_FLAG_DATA;
+
+       WARN_ON(!flags_ret);
+       if (flags_ret) {
+               if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)
+                       *flags_ret = BTRFS_EXTENT_FLAG_TREE_BLOCK;
+               else if (flags & BTRFS_EXTENT_FLAG_DATA)
+                       *flags_ret = BTRFS_EXTENT_FLAG_DATA;
+               else
+                       BUG_ON(1);
+               return 0;
+       }
 
        return -EIO;
 }
@@ -1404,12 +1497,13 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
                ULIST_ITER_INIT(&root_uiter);
                while (!ret && (root_node = ulist_next(roots, &root_uiter))) {
                        pr_debug("root %llu references leaf %llu, data list "
-                                "%#lx\n", root_node->val, ref_node->val,
-                                ref_node->aux);
-                       ret = iterate_leaf_refs(
-                               (struct extent_inode_elem *)ref_node->aux,
-                               root_node->val, extent_item_objectid,
-                               iterate, ctx);
+                                "%#llx\n", root_node->val, ref_node->val,
+                                (long long)ref_node->aux);
+                       ret = iterate_leaf_refs((struct extent_inode_elem *)
+                                               (uintptr_t)ref_node->aux,
+                                               root_node->val,
+                                               extent_item_objectid,
+                                               iterate, ctx);
                }
                ulist_free(roots);
                roots = NULL;
@@ -1432,15 +1526,15 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
 {
        int ret;
        u64 extent_item_pos;
+       u64 flags = 0;
        struct btrfs_key found_key;
        int search_commit_root = path->search_commit_root;
 
-       ret = extent_from_logical(fs_info, logical, path,
-                                       &found_key);
+       ret = extent_from_logical(fs_info, logical, path, &found_key, &flags);
        btrfs_release_path(path);
        if (ret < 0)
                return ret;
-       if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK)
+       if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)
                return -EINVAL;
 
        extent_item_pos = logical - found_key.objectid;
@@ -1451,9 +1545,12 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
        return ret;
 }
 
-static int iterate_irefs(u64 inum, struct btrfs_root *fs_root,
-                               struct btrfs_path *path,
-                               iterate_irefs_t *iterate, void *ctx)
+typedef int (iterate_irefs_t)(u64 parent, u32 name_len, unsigned long name_off,
+                             struct extent_buffer *eb, void *ctx);
+
+static int iterate_inode_refs(u64 inum, struct btrfs_root *fs_root,
+                             struct btrfs_path *path,
+                             iterate_irefs_t *iterate, void *ctx)
 {
        int ret = 0;
        int slot;
@@ -1470,7 +1567,7 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root,
        while (!ret) {
                path->leave_spinning = 1;
                ret = inode_ref_info(inum, parent ? parent+1 : 0, fs_root, path,
-                                       &found_key);
+                                    &found_key);
                if (ret < 0)
                        break;
                if (ret) {
@@ -1498,7 +1595,8 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root,
                                 "tree %llu\n", cur,
                                 (unsigned long long)found_key.objectid,
                                 (unsigned long long)fs_root->objectid);
-                       ret = iterate(parent, iref, eb, ctx);
+                       ret = iterate(parent, name_len,
+                                     (unsigned long)(iref + 1), eb, ctx);
                        if (ret)
                                break;
                        len = sizeof(*iref) + name_len;
@@ -1513,12 +1611,98 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root,
        return ret;
 }
 
+static int iterate_inode_extrefs(u64 inum, struct btrfs_root *fs_root,
+                                struct btrfs_path *path,
+                                iterate_irefs_t *iterate, void *ctx)
+{
+       int ret;
+       int slot;
+       u64 offset = 0;
+       u64 parent;
+       int found = 0;
+       struct extent_buffer *eb;
+       struct btrfs_inode_extref *extref;
+       struct extent_buffer *leaf;
+       u32 item_size;
+       u32 cur_offset;
+       unsigned long ptr;
+
+       while (1) {
+               ret = btrfs_find_one_extref(fs_root, inum, offset, path, &extref,
+                                           &offset);
+               if (ret < 0)
+                       break;
+               if (ret) {
+                       ret = found ? 0 : -ENOENT;
+                       break;
+               }
+               ++found;
+
+               slot = path->slots[0];
+               eb = path->nodes[0];
+               /* make sure we can use eb after releasing the path */
+               atomic_inc(&eb->refs);
+
+               btrfs_tree_read_lock(eb);
+               btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
+               btrfs_release_path(path);
+
+               leaf = path->nodes[0];
+               item_size = btrfs_item_size_nr(leaf, path->slots[0]);
+               ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
+               cur_offset = 0;
+
+               while (cur_offset < item_size) {
+                       u32 name_len;
+
+                       extref = (struct btrfs_inode_extref *)(ptr + cur_offset);
+                       parent = btrfs_inode_extref_parent(eb, extref);
+                       name_len = btrfs_inode_extref_name_len(eb, extref);
+                       ret = iterate(parent, name_len,
+                                     (unsigned long)&extref->name, eb, ctx);
+                       if (ret)
+                               break;
+
+                       cur_offset += btrfs_inode_extref_name_len(leaf, extref);
+                       cur_offset += sizeof(*extref);
+               }
+               btrfs_tree_read_unlock_blocking(eb);
+               free_extent_buffer(eb);
+
+               offset++;
+       }
+
+       btrfs_release_path(path);
+
+       return ret;
+}
+
+static int iterate_irefs(u64 inum, struct btrfs_root *fs_root,
+                        struct btrfs_path *path, iterate_irefs_t *iterate,
+                        void *ctx)
+{
+       int ret;
+       int found_refs = 0;
+
+       ret = iterate_inode_refs(inum, fs_root, path, iterate, ctx);
+       if (!ret)
+               ++found_refs;
+       else if (ret != -ENOENT)
+               return ret;
+
+       ret = iterate_inode_extrefs(inum, fs_root, path, iterate, ctx);
+       if (ret == -ENOENT && found_refs)
+               return 0;
+
+       return ret;
+}
+
 /*
  * returns 0 if the path could be dumped (probably truncated)
  * returns <0 in case of an error
  */
-static int inode_to_path(u64 inum, struct btrfs_inode_ref *iref,
-                               struct extent_buffer *eb, void *ctx)
+static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off,
+                        struct extent_buffer *eb, void *ctx)
 {
        struct inode_fs_paths *ipath = ctx;
        char *fspath;
@@ -1531,20 +1715,17 @@ static int inode_to_path(u64 inum, struct btrfs_inode_ref *iref,
                                        ipath->fspath->bytes_left - s_ptr : 0;
 
        fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr;
-       fspath = btrfs_iref_to_path(ipath->fs_root, ipath->btrfs_path, iref, eb,
-                               inum, fspath_min, bytes_left);
+       fspath = ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len,
+                            name_off, eb, inum, fspath_min,
+                            bytes_left);
        if (IS_ERR(fspath))
                return PTR_ERR(fspath);
 
        if (fspath > fspath_min) {
-               pr_debug("path resolved: %s\n", fspath);
                ipath->fspath->val[i] = (u64)(unsigned long)fspath;
                ++ipath->fspath->elem_cnt;
                ipath->fspath->bytes_left = fspath - fspath_min;
        } else {
-               pr_debug("missed path, not enough space. missing bytes: %lu, "
-                        "constructed so far: %s\n",
-                        (unsigned long)(fspath_min - fspath), fspath_min);
                ++ipath->fspath->elem_missed;
                ipath->fspath->bytes_missing += fspath_min - fspath;
                ipath->fspath->bytes_left = 0;
@@ -1566,7 +1747,7 @@ static int inode_to_path(u64 inum, struct btrfs_inode_ref *iref,
 int paths_from_inode(u64 inum, struct inode_fs_paths *ipath)
 {
        return iterate_irefs(inum, ipath->fs_root, ipath->btrfs_path,
-                               inode_to_path, ipath);
+                            inode_to_path, ipath);
 }
 
 struct btrfs_data_container *init_data_container(u32 total_bytes)
@@ -1575,7 +1756,7 @@ struct btrfs_data_container *init_data_container(u32 total_bytes)
        size_t alloc_bytes;
 
        alloc_bytes = max_t(size_t, total_bytes, sizeof(*data));
-       data = kmalloc(alloc_bytes, GFP_NOFS);
+       data = vmalloc(alloc_bytes);
        if (!data)
                return ERR_PTR(-ENOMEM);
 
@@ -1626,6 +1807,6 @@ void free_ipath(struct inode_fs_paths *ipath)
 {
        if (!ipath)
                return;
-       kfree(ipath->fspath);
+       vfree(ipath->fspath);
        kfree(ipath);
 }
index 032f4dc7eab82f9ba5e17497e0062d5556451698..e75533043a5ffbab21ff133877c352b743ef6592 100644 (file)
@@ -33,14 +33,13 @@ struct inode_fs_paths {
 
 typedef int (iterate_extent_inodes_t)(u64 inum, u64 offset, u64 root,
                void *ctx);
-typedef int (iterate_irefs_t)(u64 parent, struct btrfs_inode_ref *iref,
-                               struct extent_buffer *eb, void *ctx);
 
 int inode_item_info(u64 inum, u64 ioff, struct btrfs_root *fs_root,
                        struct btrfs_path *path);
 
 int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
-                       struct btrfs_path *path, struct btrfs_key *found_key);
+                       struct btrfs_path *path, struct btrfs_key *found_key,
+                       u64 *flags);
 
 int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb,
                                struct btrfs_extent_item *ei, u32 item_size,
@@ -69,4 +68,9 @@ struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root,
                                        struct btrfs_path *path);
 void free_ipath(struct inode_fs_paths *ipath);
 
+int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid,
+                         u64 start_off, struct btrfs_path *path,
+                         struct btrfs_inode_extref **ret_extref,
+                         u64 *found_off);
+
 #endif
index 5b2ad6bc4fe7f18ca8038052d26db5afb2b6c6c6..ed8ca7ca5eff2d2ce0529f42d32fb394b0331e89 100644 (file)
@@ -38,6 +38,7 @@
 #define BTRFS_INODE_DELALLOC_META_RESERVED     4
 #define BTRFS_INODE_HAS_ORPHAN_ITEM            5
 #define BTRFS_INODE_HAS_ASYNC_EXTENT           6
+#define BTRFS_INODE_NEEDS_FULL_SYNC            7
 
 /* in memory btrfs inode */
 struct btrfs_inode {
@@ -143,6 +144,9 @@ struct btrfs_inode {
        /* flags field from the on disk inode */
        u32 flags;
 
+       /* a local copy of root's last_log_commit */
+       unsigned long last_log_commit;
+
        /*
         * Counters to keep track of the number of extent item's we may use due
         * to delalloc and such.  outstanding_extents is the number of extent
@@ -202,15 +206,10 @@ static inline bool btrfs_is_free_space_inode(struct inode *inode)
 
 static inline int btrfs_inode_in_log(struct inode *inode, u64 generation)
 {
-       struct btrfs_root *root = BTRFS_I(inode)->root;
-       int ret = 0;
-
-       mutex_lock(&root->log_mutex);
        if (BTRFS_I(inode)->logged_trans == generation &&
-           BTRFS_I(inode)->last_sub_trans <= root->last_log_commit)
-               ret = 1;
-       mutex_unlock(&root->log_mutex);
-       return ret;
+           BTRFS_I(inode)->last_sub_trans <= BTRFS_I(inode)->last_log_commit)
+               return 1;
+       return 0;
 }
 
 #endif
index 9197e2e33407d26f67a91196ae95328840e3f6ce..5a3e45db642a6b1c64998ba523be143d382d396e 100644 (file)
@@ -37,8 +37,9 @@
  *        the file system was mounted, (i.e., they have been
  *        referenced by the super block) or they have been
  *        written since then and the write completion callback
- *        was called and a FLUSH request to the device where
- *        these blocks are located was received and completed.
+ *        was called and no write error was indicated and a
+ *        FLUSH request to the device where these blocks are
+ *        located was received and completed.
  *    2b. All referenced blocks need to have a generation
  *        number which is equal to the parent's number.
  *
@@ -2601,6 +2602,17 @@ static int btrfsic_check_all_ref_blocks(struct btrfsic_state *state,
                               (unsigned long long)l->block_ref_to->dev_bytenr,
                               l->block_ref_to->mirror_num);
                        ret = -1;
+               } else if (l->block_ref_to->iodone_w_error) {
+                       printk(KERN_INFO "btrfs: attempt to write superblock"
+                              " which references block %c @%llu (%s/%llu/%d)"
+                              " which has write error!\n",
+                              btrfsic_get_block_type(state, l->block_ref_to),
+                              (unsigned long long)
+                              l->block_ref_to->logical_bytenr,
+                              l->block_ref_to->dev_state->name,
+                              (unsigned long long)l->block_ref_to->dev_bytenr,
+                              l->block_ref_to->mirror_num);
+                       ret = -1;
                } else if (l->parent_generation !=
                           l->block_ref_to->generation &&
                           BTRFSIC_GENERATION_UNKNOWN !=
index 43d1c5a3a030888544d8dd8f7b36239386552d08..c6467aa88bee24fb3f4fe401306aed57442a0a59 100644 (file)
@@ -577,6 +577,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
        u64 em_start;
        struct extent_map *em;
        int ret = -ENOMEM;
+       int faili = 0;
        u32 *sums;
 
        tree = &BTRFS_I(inode)->io_tree;
@@ -626,9 +627,13 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
        for (pg_index = 0; pg_index < nr_pages; pg_index++) {
                cb->compressed_pages[pg_index] = alloc_page(GFP_NOFS |
                                                              __GFP_HIGHMEM);
-               if (!cb->compressed_pages[pg_index])
+               if (!cb->compressed_pages[pg_index]) {
+                       faili = pg_index - 1;
+                       ret = -ENOMEM;
                        goto fail2;
+               }
        }
+       faili = nr_pages - 1;
        cb->nr_pages = nr_pages;
 
        add_ra_bio_pages(inode, em_start + em_len, cb);
@@ -713,8 +718,10 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
        return 0;
 
 fail2:
-       for (pg_index = 0; pg_index < nr_pages; pg_index++)
-               free_page((unsigned long)cb->compressed_pages[pg_index]);
+       while (faili >= 0) {
+               __free_page(cb->compressed_pages[faili]);
+               faili--;
+       }
 
        kfree(cb->compressed_pages);
 fail1:
index 6d183f60d63a0521e8c4461e4d5fd705163d17d1..b334362110003165a72b63433b192f2b481c3b01 100644 (file)
@@ -4401,149 +4401,6 @@ void btrfs_extend_item(struct btrfs_trans_handle *trans,
        }
 }
 
-/*
- * Given a key and some data, insert items into the tree.
- * This does all the path init required, making room in the tree if needed.
- * Returns the number of keys that were inserted.
- */
-int btrfs_insert_some_items(struct btrfs_trans_handle *trans,
-                           struct btrfs_root *root,
-                           struct btrfs_path *path,
-                           struct btrfs_key *cpu_key, u32 *data_size,
-                           int nr)
-{
-       struct extent_buffer *leaf;
-       struct btrfs_item *item;
-       int ret = 0;
-       int slot;
-       int i;
-       u32 nritems;
-       u32 total_data = 0;
-       u32 total_size = 0;
-       unsigned int data_end;
-       struct btrfs_disk_key disk_key;
-       struct btrfs_key found_key;
-       struct btrfs_map_token token;
-
-       btrfs_init_map_token(&token);
-
-       for (i = 0; i < nr; i++) {
-               if (total_size + data_size[i] + sizeof(struct btrfs_item) >
-                   BTRFS_LEAF_DATA_SIZE(root)) {
-                       break;
-                       nr = i;
-               }
-               total_data += data_size[i];
-               total_size += data_size[i] + sizeof(struct btrfs_item);
-       }
-       BUG_ON(nr == 0);
-
-       ret = btrfs_search_slot(trans, root, cpu_key, path, total_size, 1);
-       if (ret == 0)
-               return -EEXIST;
-       if (ret < 0)
-               goto out;
-
-       leaf = path->nodes[0];
-
-       nritems = btrfs_header_nritems(leaf);
-       data_end = leaf_data_end(root, leaf);
-
-       if (btrfs_leaf_free_space(root, leaf) < total_size) {
-               for (i = nr; i >= 0; i--) {
-                       total_data -= data_size[i];
-                       total_size -= data_size[i] + sizeof(struct btrfs_item);
-                       if (total_size < btrfs_leaf_free_space(root, leaf))
-                               break;
-               }
-               nr = i;
-       }
-
-       slot = path->slots[0];
-       BUG_ON(slot < 0);
-
-       if (slot != nritems) {
-               unsigned int old_data = btrfs_item_end_nr(leaf, slot);
-
-               item = btrfs_item_nr(leaf, slot);
-               btrfs_item_key_to_cpu(leaf, &found_key, slot);
-
-               /* figure out how many keys we can insert in here */
-               total_data = data_size[0];
-               for (i = 1; i < nr; i++) {
-                       if (btrfs_comp_cpu_keys(&found_key, cpu_key + i) <= 0)
-                               break;
-                       total_data += data_size[i];
-               }
-               nr = i;
-
-               if (old_data < data_end) {
-                       btrfs_print_leaf(root, leaf);
-                       printk(KERN_CRIT "slot %d old_data %d data_end %d\n",
-                              slot, old_data, data_end);
-                       BUG_ON(1);
-               }
-               /*
-                * item0..itemN ... dataN.offset..dataN.size .. data0.size
-                */
-               /* first correct the data pointers */
-               for (i = slot; i < nritems; i++) {
-                       u32 ioff;
-
-                       item = btrfs_item_nr(leaf, i);
-                       ioff = btrfs_token_item_offset(leaf, item, &token);
-                       btrfs_set_token_item_offset(leaf, item,
-                                                   ioff - total_data, &token);
-               }
-               /* shift the items */
-               memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + nr),
-                             btrfs_item_nr_offset(slot),
-                             (nritems - slot) * sizeof(struct btrfs_item));
-
-               /* shift the data */
-               memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
-                             data_end - total_data, btrfs_leaf_data(leaf) +
-                             data_end, old_data - data_end);
-               data_end = old_data;
-       } else {
-               /*
-                * this sucks but it has to be done, if we are inserting at
-                * the end of the leaf only insert 1 of the items, since we
-                * have no way of knowing whats on the next leaf and we'd have
-                * to drop our current locks to figure it out
-                */
-               nr = 1;
-       }
-
-       /* setup the item for the new data */
-       for (i = 0; i < nr; i++) {
-               btrfs_cpu_key_to_disk(&disk_key, cpu_key + i);
-               btrfs_set_item_key(leaf, &disk_key, slot + i);
-               item = btrfs_item_nr(leaf, slot + i);
-               btrfs_set_token_item_offset(leaf, item,
-                                           data_end - data_size[i], &token);
-               data_end -= data_size[i];
-               btrfs_set_token_item_size(leaf, item, data_size[i], &token);
-       }
-       btrfs_set_header_nritems(leaf, nritems + nr);
-       btrfs_mark_buffer_dirty(leaf);
-
-       ret = 0;
-       if (slot == 0) {
-               btrfs_cpu_key_to_disk(&disk_key, cpu_key);
-               fixup_low_keys(trans, root, path, &disk_key, 1);
-       }
-
-       if (btrfs_leaf_free_space(root, leaf) < 0) {
-               btrfs_print_leaf(root, leaf);
-               BUG();
-       }
-out:
-       if (!ret)
-               ret = nr;
-       return ret;
-}
-
 /*
  * this is a helper for btrfs_insert_empty_items, the main goal here is
  * to save stack depth by doing the bulk of the work in a function
@@ -5073,6 +4930,7 @@ static void tree_move_down(struct btrfs_root *root,
                           struct btrfs_path *path,
                           int *level, int root_level)
 {
+       BUG_ON(*level == 0);
        path->nodes[*level - 1] = read_node_slot(root, path->nodes[*level],
                                        path->slots[*level]);
        path->slots[*level - 1] = 0;
@@ -5089,7 +4947,7 @@ static int tree_move_next_or_upnext(struct btrfs_root *root,
 
        path->slots[*level]++;
 
-       while (path->slots[*level] == nritems) {
+       while (path->slots[*level] >= nritems) {
                if (*level == root_level)
                        return -1;
 
@@ -5433,9 +5291,11 @@ int btrfs_compare_trees(struct btrfs_root *left_root,
                                        goto out;
                                advance_right = ADVANCE;
                        } else {
+                               WARN_ON(!extent_buffer_uptodate(left_path->nodes[0]));
                                ret = tree_compare_item(left_root, left_path,
                                                right_path, tmp_buf);
                                if (ret) {
+                                       WARN_ON(!extent_buffer_uptodate(left_path->nodes[0]));
                                        ret = changed_cb(left_root, right_root,
                                                left_path, right_path,
                                                &left_key,
index 9821b672f5a254fb02c4b17c2f3db3798c538c45..926c9ffc66d93324d155481c4ecba13d27fa3fec 100644 (file)
@@ -154,6 +154,13 @@ struct btrfs_ordered_sum;
  */
 #define BTRFS_NAME_LEN 255
 
+/*
+ * Theoretical limit is larger, but we keep this down to a sane
+ * value. That should limit greatly the possibility of collisions on
+ * inode ref items.
+ */
+#define BTRFS_LINK_MAX 65535U
+
 /* 32 bytes in various csum fields */
 #define BTRFS_CSUM_SIZE 32
 
@@ -489,6 +496,8 @@ struct btrfs_super_block {
  */
 #define BTRFS_FEATURE_INCOMPAT_BIG_METADATA    (1ULL << 5)
 
+#define BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF   (1ULL << 6)
+
 #define BTRFS_FEATURE_COMPAT_SUPP              0ULL
 #define BTRFS_FEATURE_COMPAT_RO_SUPP           0ULL
 #define BTRFS_FEATURE_INCOMPAT_SUPP                    \
@@ -496,7 +505,8 @@ struct btrfs_super_block {
         BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL |        \
         BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS |          \
         BTRFS_FEATURE_INCOMPAT_BIG_METADATA |          \
-        BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO)
+        BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO |          \
+        BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF)
 
 /*
  * A leaf is full of items. offset and size tell us where to find
@@ -643,6 +653,14 @@ struct btrfs_inode_ref {
        /* name goes here */
 } __attribute__ ((__packed__));
 
+struct btrfs_inode_extref {
+       __le64 parent_objectid;
+       __le64 index;
+       __le16 name_len;
+       __u8   name[0];
+       /* name goes here */
+} __attribute__ ((__packed__));
+
 struct btrfs_timespec {
        __le64 sec;
        __le32 nsec;
@@ -1028,12 +1046,22 @@ struct btrfs_space_info {
        wait_queue_head_t wait;
 };
 
+#define        BTRFS_BLOCK_RSV_GLOBAL          1
+#define        BTRFS_BLOCK_RSV_DELALLOC        2
+#define        BTRFS_BLOCK_RSV_TRANS           3
+#define        BTRFS_BLOCK_RSV_CHUNK           4
+#define        BTRFS_BLOCK_RSV_DELOPS          5
+#define        BTRFS_BLOCK_RSV_EMPTY           6
+#define        BTRFS_BLOCK_RSV_TEMP            7
+
 struct btrfs_block_rsv {
        u64 size;
        u64 reserved;
        struct btrfs_space_info *space_info;
        spinlock_t lock;
-       unsigned int full;
+       unsigned short full;
+       unsigned short type;
+       unsigned short failfast;
 };
 
 /*
@@ -1127,6 +1155,9 @@ struct btrfs_block_group_cache {
         * Today it will only have one thing on it, but that may change
         */
        struct list_head cluster_list;
+
+       /* For delayed block group creation */
+       struct list_head new_bg_list;
 };
 
 /* delayed seq elem */
@@ -1240,7 +1271,6 @@ struct btrfs_fs_info {
        struct mutex reloc_mutex;
 
        struct list_head trans_list;
-       struct list_head hashers;
        struct list_head dead_roots;
        struct list_head caching_block_groups;
 
@@ -1366,9 +1396,6 @@ struct btrfs_fs_info {
        struct rb_root defrag_inodes;
        atomic_t defrag_running;
 
-       spinlock_t ref_cache_lock;
-       u64 total_ref_cache_size;
-
        /*
         * these three are in extended format (availability of single
         * chunks is denoted by BTRFS_AVAIL_ALLOC_BIT_SINGLE bit, other
@@ -1441,6 +1468,8 @@ struct btrfs_fs_info {
 
        /* next backup root to be overwritten */
        int backup_root_index;
+
+       int num_tolerated_disk_barrier_failures;
 };
 
 /*
@@ -1481,9 +1510,9 @@ struct btrfs_root {
        wait_queue_head_t log_commit_wait[2];
        atomic_t log_writers;
        atomic_t log_commit[2];
+       atomic_t log_batch;
        unsigned long log_transid;
        unsigned long last_log_commit;
-       unsigned long log_batch;
        pid_t log_start_pid;
        bool log_multiple_pids;
 
@@ -1592,6 +1621,7 @@ struct btrfs_ioctl_defrag_range_args {
  */
 #define BTRFS_INODE_ITEM_KEY           1
 #define BTRFS_INODE_REF_KEY            12
+#define BTRFS_INODE_EXTREF_KEY         13
 #define BTRFS_XATTR_ITEM_KEY           24
 #define BTRFS_ORPHAN_ITEM_KEY          48
 /* reserve 2-15 close to the inode for later flexibility */
@@ -1978,6 +2008,13 @@ BTRFS_SETGET_STACK_FUNCS(block_group_flags,
 BTRFS_SETGET_FUNCS(inode_ref_name_len, struct btrfs_inode_ref, name_len, 16);
 BTRFS_SETGET_FUNCS(inode_ref_index, struct btrfs_inode_ref, index, 64);
 
+/* struct btrfs_inode_extref */
+BTRFS_SETGET_FUNCS(inode_extref_parent, struct btrfs_inode_extref,
+                  parent_objectid, 64);
+BTRFS_SETGET_FUNCS(inode_extref_name_len, struct btrfs_inode_extref,
+                  name_len, 16);
+BTRFS_SETGET_FUNCS(inode_extref_index, struct btrfs_inode_extref, index, 64);
+
 /* struct btrfs_inode_item */
 BTRFS_SETGET_FUNCS(inode_generation, struct btrfs_inode_item, generation, 64);
 BTRFS_SETGET_FUNCS(inode_sequence, struct btrfs_inode_item, sequence, 64);
@@ -2858,6 +2895,8 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
                           u64 size);
 int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                             struct btrfs_root *root, u64 group_start);
+void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans,
+                                      struct btrfs_root *root);
 u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags);
 u64 btrfs_get_alloc_profile(struct btrfs_root *root, int data);
 void btrfs_clear_space_info_full(struct btrfs_fs_info *info);
@@ -2874,8 +2913,9 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes);
 void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes);
 int btrfs_delalloc_reserve_space(struct inode *inode, u64 num_bytes);
 void btrfs_delalloc_release_space(struct inode *inode, u64 num_bytes);
-void btrfs_init_block_rsv(struct btrfs_block_rsv *rsv);
-struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root);
+void btrfs_init_block_rsv(struct btrfs_block_rsv *rsv, unsigned short type);
+struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root,
+                                             unsigned short type);
 void btrfs_free_block_rsv(struct btrfs_root *root,
                          struct btrfs_block_rsv *rsv);
 int btrfs_block_rsv_add(struct btrfs_root *root,
@@ -3172,12 +3212,12 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root,
                           const char *name, int name_len,
                           u64 inode_objectid, u64 ref_objectid, u64 *index);
-struct btrfs_inode_ref *
-btrfs_lookup_inode_ref(struct btrfs_trans_handle *trans,
-                       struct btrfs_root *root,
-                       struct btrfs_path *path,
-                       const char *name, int name_len,
-                       u64 inode_objectid, u64 ref_objectid, int mod);
+int btrfs_get_inode_ref_index(struct btrfs_trans_handle *trans,
+                             struct btrfs_root *root,
+                             struct btrfs_path *path,
+                             const char *name, int name_len,
+                             u64 inode_objectid, u64 ref_objectid, int mod,
+                             u64 *ret_index);
 int btrfs_insert_empty_inode(struct btrfs_trans_handle *trans,
                             struct btrfs_root *root,
                             struct btrfs_path *path, u64 objectid);
@@ -3185,6 +3225,19 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root
                       *root, struct btrfs_path *path,
                       struct btrfs_key *location, int mod);
 
+struct btrfs_inode_extref *
+btrfs_lookup_inode_extref(struct btrfs_trans_handle *trans,
+                         struct btrfs_root *root,
+                         struct btrfs_path *path,
+                         const char *name, int name_len,
+                         u64 inode_objectid, u64 ref_objectid, int ins_len,
+                         int cow);
+
+int btrfs_find_name_in_ext_backref(struct btrfs_path *path,
+                                  u64 ref_objectid, const char *name,
+                                  int name_len,
+                                  struct btrfs_inode_extref **extref_ret);
+
 /* file-item.c */
 int btrfs_del_csums(struct btrfs_trans_handle *trans,
                    struct btrfs_root *root, u64 bytenr, u64 len);
@@ -3249,6 +3302,8 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
                        struct btrfs_root *root,
                        struct inode *dir, u64 objectid,
                        const char *name, int name_len);
+int btrfs_truncate_page(struct inode *inode, loff_t from, loff_t len,
+                       int front);
 int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
                               struct btrfs_root *root,
                               struct inode *inode, u64 new_size,
@@ -3308,16 +3363,27 @@ void btrfs_inherit_iflags(struct inode *inode, struct inode *dir);
 int btrfs_defrag_file(struct inode *inode, struct file *file,
                      struct btrfs_ioctl_defrag_range_args *range,
                      u64 newer_than, unsigned long max_pages);
+void btrfs_get_block_group_info(struct list_head *groups_list,
+                               struct btrfs_ioctl_space_info *space);
+
 /* file.c */
 int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
                           struct inode *inode);
 int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info);
 int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync);
-int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
-                           int skip_pinned);
+void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
+                            int skip_pinned);
+int btrfs_replace_extent_cache(struct inode *inode, struct extent_map *replace,
+                              u64 start, u64 end, int skip_pinned,
+                              int modified);
 extern const struct file_operations btrfs_file_operations;
-int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,
-                      u64 start, u64 end, u64 *hint_byte, int drop_cache);
+int __btrfs_drop_extents(struct btrfs_trans_handle *trans,
+                        struct btrfs_root *root, struct inode *inode,
+                        struct btrfs_path *path, u64 start, u64 end,
+                        u64 *drop_end, int drop_cache);
+int btrfs_drop_extents(struct btrfs_trans_handle *trans,
+                      struct btrfs_root *root, struct inode *inode, u64 start,
+                      u64 end, int drop_cache);
 int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
                              struct inode *inode, u64 start, u64 end);
 int btrfs_release_file(struct inode *inode, struct file *file);
@@ -3378,6 +3444,11 @@ static inline void __btrfs_set_fs_incompat(struct btrfs_fs_info *fs_info,
        }
 }
 
+/*
+ * Call btrfs_abort_transaction as early as possible when an error condition is
+ * detected, that way the exact line number is reported.
+ */
+
 #define btrfs_abort_transaction(trans, root, errno)            \
 do {                                                           \
        __btrfs_abort_transaction(trans, root, __func__,        \
index 52c85e2b95d0f7efa9cbd105bab093eca90e1b9c..478f66bdc57b958445365baf739122e4eec263af 100644 (file)
@@ -29,7 +29,7 @@ static struct kmem_cache *delayed_node_cache;
 
 int __init btrfs_delayed_inode_init(void)
 {
-       delayed_node_cache = kmem_cache_create("delayed_node",
+       delayed_node_cache = kmem_cache_create("btrfs_delayed_node",
                                        sizeof(struct btrfs_delayed_node),
                                        0,
                                        SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
@@ -650,7 +650,7 @@ static int btrfs_delayed_inode_reserve_metadata(
         * we're accounted for.
         */
        if (!src_rsv || (!trans->bytes_reserved &&
-           src_rsv != &root->fs_info->delalloc_block_rsv)) {
+                        src_rsv->type != BTRFS_BLOCK_RSV_DELALLOC)) {
                ret = btrfs_block_rsv_add_noflush(root, dst_rsv, num_bytes);
                /*
                 * Since we're under a transaction reserve_metadata_bytes could
@@ -668,7 +668,7 @@ static int btrfs_delayed_inode_reserve_metadata(
                                                      num_bytes, 1);
                }
                return ret;
-       } else if (src_rsv == &root->fs_info->delalloc_block_rsv) {
+       } else if (src_rsv->type == BTRFS_BLOCK_RSV_DELALLOC) {
                spin_lock(&BTRFS_I(inode)->lock);
                if (test_and_clear_bit(BTRFS_INODE_DELALLOC_META_RESERVED,
                                       &BTRFS_I(inode)->runtime_flags)) {
index 22e98e04c2eabbc0b4baeb2618033657a9344fb9..7cda51995c1e589eaf36fe048518bbbe0bd21109 100644 (file)
 #include "check-integrity.h"
 #include "rcu-string.h"
 
+#ifdef CONFIG_X86
+#include <asm/cpufeature.h>
+#endif
+
 static struct extent_io_ops btree_extent_io_ops;
 static void end_workqueue_fn(struct btrfs_work *work);
 static void free_fs_root(struct btrfs_root *root);
@@ -217,26 +221,16 @@ static struct extent_map *btree_get_extent(struct inode *inode,
        write_lock(&em_tree->lock);
        ret = add_extent_mapping(em_tree, em);
        if (ret == -EEXIST) {
-               u64 failed_start = em->start;
-               u64 failed_len = em->len;
-
                free_extent_map(em);
                em = lookup_extent_mapping(em_tree, start, len);
-               if (em) {
-                       ret = 0;
-               } else {
-                       em = lookup_extent_mapping(em_tree, failed_start,
-                                                  failed_len);
-                       ret = -EIO;
-               }
+               if (!em)
+                       em = ERR_PTR(-EIO);
        } else if (ret) {
                free_extent_map(em);
-               em = NULL;
+               em = ERR_PTR(ret);
        }
        write_unlock(&em_tree->lock);
 
-       if (ret)
-               em = ERR_PTR(ret);
 out:
        return em;
 }
@@ -439,10 +433,6 @@ static int csum_dirty_buffer(struct btrfs_root *root, struct page *page)
                WARN_ON(1);
                return 0;
        }
-       if (eb->pages[0] != page) {
-               WARN_ON(1);
-               return 0;
-       }
        if (!PageUptodate(page)) {
                WARN_ON(1);
                return 0;
@@ -869,10 +859,22 @@ static int __btree_submit_bio_done(struct inode *inode, int rw, struct bio *bio,
        return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio, mirror_num, 1);
 }
 
+static int check_async_write(struct inode *inode, unsigned long bio_flags)
+{
+       if (bio_flags & EXTENT_BIO_TREE_LOG)
+               return 0;
+#ifdef CONFIG_X86
+       if (cpu_has_xmm4_2)
+               return 0;
+#endif
+       return 1;
+}
+
 static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
                                 int mirror_num, unsigned long bio_flags,
                                 u64 bio_offset)
 {
+       int async = check_async_write(inode, bio_flags);
        int ret;
 
        if (!(rw & REQ_WRITE)) {
@@ -887,6 +889,12 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
                        return ret;
                return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio,
                                     mirror_num, 0);
+       } else if (!async) {
+               ret = btree_csum_one_bio(bio);
+               if (ret)
+                       return ret;
+               return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio,
+                                    mirror_num, 0);
        }
 
        /*
@@ -1168,8 +1176,8 @@ static void __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
        atomic_set(&root->log_commit[0], 0);
        atomic_set(&root->log_commit[1], 0);
        atomic_set(&root->log_writers, 0);
+       atomic_set(&root->log_batch, 0);
        atomic_set(&root->orphan_inodes, 0);
-       root->log_batch = 0;
        root->log_transid = 0;
        root->last_log_commit = 0;
        extent_io_tree_init(&root->dirty_log_pages,
@@ -1667,9 +1675,10 @@ static int transaction_kthread(void *arg)
                spin_unlock(&root->fs_info->trans_lock);
 
                /* If the file system is aborted, this will always fail. */
-               trans = btrfs_join_transaction(root);
+               trans = btrfs_attach_transaction(root);
                if (IS_ERR(trans)) {
-                       cannot_commit = true;
+                       if (PTR_ERR(trans) != -ENOENT)
+                               cannot_commit = true;
                        goto sleep;
                }
                if (transid == trans->transid) {
@@ -1994,13 +2003,11 @@ int open_ctree(struct super_block *sb,
        INIT_LIST_HEAD(&fs_info->trans_list);
        INIT_LIST_HEAD(&fs_info->dead_roots);
        INIT_LIST_HEAD(&fs_info->delayed_iputs);
-       INIT_LIST_HEAD(&fs_info->hashers);
        INIT_LIST_HEAD(&fs_info->delalloc_inodes);
        INIT_LIST_HEAD(&fs_info->ordered_operations);
        INIT_LIST_HEAD(&fs_info->caching_block_groups);
        spin_lock_init(&fs_info->delalloc_lock);
        spin_lock_init(&fs_info->trans_lock);
-       spin_lock_init(&fs_info->ref_cache_lock);
        spin_lock_init(&fs_info->fs_roots_radix_lock);
        spin_lock_init(&fs_info->delayed_iput_lock);
        spin_lock_init(&fs_info->defrag_inodes_lock);
@@ -2014,12 +2021,15 @@ int open_ctree(struct super_block *sb,
        INIT_LIST_HEAD(&fs_info->space_info);
        INIT_LIST_HEAD(&fs_info->tree_mod_seq_list);
        btrfs_mapping_init(&fs_info->mapping_tree);
-       btrfs_init_block_rsv(&fs_info->global_block_rsv);
-       btrfs_init_block_rsv(&fs_info->delalloc_block_rsv);
-       btrfs_init_block_rsv(&fs_info->trans_block_rsv);
-       btrfs_init_block_rsv(&fs_info->chunk_block_rsv);
-       btrfs_init_block_rsv(&fs_info->empty_block_rsv);
-       btrfs_init_block_rsv(&fs_info->delayed_block_rsv);
+       btrfs_init_block_rsv(&fs_info->global_block_rsv,
+                            BTRFS_BLOCK_RSV_GLOBAL);
+       btrfs_init_block_rsv(&fs_info->delalloc_block_rsv,
+                            BTRFS_BLOCK_RSV_DELALLOC);
+       btrfs_init_block_rsv(&fs_info->trans_block_rsv, BTRFS_BLOCK_RSV_TRANS);
+       btrfs_init_block_rsv(&fs_info->chunk_block_rsv, BTRFS_BLOCK_RSV_CHUNK);
+       btrfs_init_block_rsv(&fs_info->empty_block_rsv, BTRFS_BLOCK_RSV_EMPTY);
+       btrfs_init_block_rsv(&fs_info->delayed_block_rsv,
+                            BTRFS_BLOCK_RSV_DELOPS);
        atomic_set(&fs_info->nr_async_submits, 0);
        atomic_set(&fs_info->async_delalloc_pages, 0);
        atomic_set(&fs_info->async_submit_draining, 0);
@@ -2491,6 +2501,8 @@ retry_root_backup:
                printk(KERN_ERR "Failed to read block groups: %d\n", ret);
                goto fail_block_groups;
        }
+       fs_info->num_tolerated_disk_barrier_failures =
+               btrfs_calc_num_tolerated_disk_barrier_failures(fs_info);
 
        fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
                                               "btrfs-cleaner");
@@ -2874,12 +2886,10 @@ static int write_dev_flush(struct btrfs_device *device, int wait)
                        printk_in_rcu("btrfs: disabling barriers on dev %s\n",
                                      rcu_str_deref(device->name));
                        device->nobarriers = 1;
-               }
-               if (!bio_flagged(bio, BIO_UPTODATE)) {
+               } else if (!bio_flagged(bio, BIO_UPTODATE)) {
                        ret = -EIO;
-                       if (!bio_flagged(bio, BIO_EOPNOTSUPP))
-                               btrfs_dev_stat_inc_and_print(device,
-                                       BTRFS_DEV_STAT_FLUSH_ERRS);
+                       btrfs_dev_stat_inc_and_print(device,
+                               BTRFS_DEV_STAT_FLUSH_ERRS);
                }
 
                /* drop the reference from the wait == 0 run */
@@ -2918,14 +2928,15 @@ static int barrier_all_devices(struct btrfs_fs_info *info)
 {
        struct list_head *head;
        struct btrfs_device *dev;
-       int errors = 0;
+       int errors_send = 0;
+       int errors_wait = 0;
        int ret;
 
        /* send down all the barriers */
        head = &info->fs_devices->devices;
        list_for_each_entry_rcu(dev, head, dev_list) {
                if (!dev->bdev) {
-                       errors++;
+                       errors_send++;
                        continue;
                }
                if (!dev->in_fs_metadata || !dev->writeable)
@@ -2933,13 +2944,13 @@ static int barrier_all_devices(struct btrfs_fs_info *info)
 
                ret = write_dev_flush(dev, 0);
                if (ret)
-                       errors++;
+                       errors_send++;
        }
 
        /* wait for all the barriers */
        list_for_each_entry_rcu(dev, head, dev_list) {
                if (!dev->bdev) {
-                       errors++;
+                       errors_wait++;
                        continue;
                }
                if (!dev->in_fs_metadata || !dev->writeable)
@@ -2947,13 +2958,87 @@ static int barrier_all_devices(struct btrfs_fs_info *info)
 
                ret = write_dev_flush(dev, 1);
                if (ret)
-                       errors++;
+                       errors_wait++;
        }
-       if (errors)
+       if (errors_send > info->num_tolerated_disk_barrier_failures ||
+           errors_wait > info->num_tolerated_disk_barrier_failures)
                return -EIO;
        return 0;
 }
 
+int btrfs_calc_num_tolerated_disk_barrier_failures(
+       struct btrfs_fs_info *fs_info)
+{
+       struct btrfs_ioctl_space_info space;
+       struct btrfs_space_info *sinfo;
+       u64 types[] = {BTRFS_BLOCK_GROUP_DATA,
+                      BTRFS_BLOCK_GROUP_SYSTEM,
+                      BTRFS_BLOCK_GROUP_METADATA,
+                      BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA};
+       int num_types = 4;
+       int i;
+       int c;
+       int num_tolerated_disk_barrier_failures =
+               (int)fs_info->fs_devices->num_devices;
+
+       for (i = 0; i < num_types; i++) {
+               struct btrfs_space_info *tmp;
+
+               sinfo = NULL;
+               rcu_read_lock();
+               list_for_each_entry_rcu(tmp, &fs_info->space_info, list) {
+                       if (tmp->flags == types[i]) {
+                               sinfo = tmp;
+                               break;
+                       }
+               }
+               rcu_read_unlock();
+
+               if (!sinfo)
+                       continue;
+
+               down_read(&sinfo->groups_sem);
+               for (c = 0; c < BTRFS_NR_RAID_TYPES; c++) {
+                       if (!list_empty(&sinfo->block_groups[c])) {
+                               u64 flags;
+
+                               btrfs_get_block_group_info(
+                                       &sinfo->block_groups[c], &space);
+                               if (space.total_bytes == 0 ||
+                                   space.used_bytes == 0)
+                                       continue;
+                               flags = space.flags;
+                               /*
+                                * return
+                                * 0: if dup, single or RAID0 is configured for
+                                *    any of metadata, system or data, else
+                                * 1: if RAID5 is configured, or if RAID1 or
+                                *    RAID10 is configured and only two mirrors
+                                *    are used, else
+                                * 2: if RAID6 is configured, else
+                                * num_mirrors - 1: if RAID1 or RAID10 is
+                                *                  configured and more than
+                                *                  2 mirrors are used.
+                                */
+                               if (num_tolerated_disk_barrier_failures > 0 &&
+                                   ((flags & (BTRFS_BLOCK_GROUP_DUP |
+                                              BTRFS_BLOCK_GROUP_RAID0)) ||
+                                    ((flags & BTRFS_BLOCK_GROUP_PROFILE_MASK)
+                                     == 0)))
+                                       num_tolerated_disk_barrier_failures = 0;
+                               else if (num_tolerated_disk_barrier_failures > 1
+                                        &&
+                                        (flags & (BTRFS_BLOCK_GROUP_RAID1 |
+                                                  BTRFS_BLOCK_GROUP_RAID10)))
+                                       num_tolerated_disk_barrier_failures = 1;
+                       }
+               }
+               up_read(&sinfo->groups_sem);
+       }
+
+       return num_tolerated_disk_barrier_failures;
+}
+
 int write_all_supers(struct btrfs_root *root, int max_mirrors)
 {
        struct list_head *head;
@@ -2976,8 +3061,16 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors)
        mutex_lock(&root->fs_info->fs_devices->device_list_mutex);
        head = &root->fs_info->fs_devices->devices;
 
-       if (do_barriers)
-               barrier_all_devices(root->fs_info);
+       if (do_barriers) {
+               ret = barrier_all_devices(root->fs_info);
+               if (ret) {
+                       mutex_unlock(
+                               &root->fs_info->fs_devices->device_list_mutex);
+                       btrfs_error(root->fs_info, ret,
+                                   "errors while submitting device barriers.");
+                       return ret;
+               }
+       }
 
        list_for_each_entry_rcu(dev, head, dev_list) {
                if (!dev->bdev) {
@@ -3211,10 +3304,6 @@ int close_ctree(struct btrfs_root *root)
                printk(KERN_INFO "btrfs: at unmount delalloc count %llu\n",
                       (unsigned long long)fs_info->delalloc_bytes);
        }
-       if (fs_info->total_ref_cache_size) {
-               printk(KERN_INFO "btrfs: at umount reference cache size %llu\n",
-                      (unsigned long long)fs_info->total_ref_cache_size);
-       }
 
        free_extent_buffer(fs_info->extent_root->node);
        free_extent_buffer(fs_info->extent_root->commit_root);
@@ -3360,52 +3449,6 @@ int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid)
        return btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
 }
 
-int btree_lock_page_hook(struct page *page, void *data,
-                               void (*flush_fn)(void *))
-{
-       struct inode *inode = page->mapping->host;
-       struct btrfs_root *root = BTRFS_I(inode)->root;
-       struct extent_buffer *eb;
-
-       /*
-        * We culled this eb but the page is still hanging out on the mapping,
-        * carry on.
-        */
-       if (!PagePrivate(page))
-               goto out;
-
-       eb = (struct extent_buffer *)page->private;
-       if (!eb) {
-               WARN_ON(1);
-               goto out;
-       }
-       if (page != eb->pages[0])
-               goto out;
-
-       if (!btrfs_try_tree_write_lock(eb)) {
-               flush_fn(data);
-               btrfs_tree_lock(eb);
-       }
-       btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
-
-       if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) {
-               spin_lock(&root->fs_info->delalloc_lock);
-               if (root->fs_info->dirty_metadata_bytes >= eb->len)
-                       root->fs_info->dirty_metadata_bytes -= eb->len;
-               else
-                       WARN_ON(1);
-               spin_unlock(&root->fs_info->delalloc_lock);
-       }
-
-       btrfs_tree_unlock(eb);
-out:
-       if (!trylock_page(page)) {
-               flush_fn(data);
-               lock_page(page);
-       }
-       return 0;
-}
-
 static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
                              int read_only)
 {
@@ -3608,7 +3651,7 @@ static int btrfs_destroy_marked_extents(struct btrfs_root *root,
 
        while (1) {
                ret = find_first_extent_bit(dirty_pages, start, &start, &end,
-                                           mark);
+                                           mark, NULL);
                if (ret)
                        break;
 
@@ -3663,7 +3706,7 @@ static int btrfs_destroy_pinned_extent(struct btrfs_root *root,
 again:
        while (1) {
                ret = find_first_extent_bit(unpin, 0, &start, &end,
-                                           EXTENT_DIRTY);
+                                           EXTENT_DIRTY, NULL);
                if (ret)
                        break;
 
@@ -3800,7 +3843,6 @@ int btrfs_cleanup_transaction(struct btrfs_root *root)
 }
 
 static struct extent_io_ops btree_extent_io_ops = {
-       .write_cache_pages_lock_hook = btree_lock_page_hook,
        .readpage_end_io_hook = btree_readpage_end_io_hook,
        .readpage_io_failed_hook = btree_io_failed_hook,
        .submit_bio_hook = btree_submit_bio_hook,
index c5b00a735fefac258b7914223139d902efacbf99..2025a9132c16119c5795b2614b7d114ada047643 100644 (file)
@@ -95,6 +95,8 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
                                     u64 objectid);
 int btree_lock_page_hook(struct page *page, void *data,
                                void (*flush_fn)(void *));
+int btrfs_calc_num_tolerated_disk_barrier_failures(
+       struct btrfs_fs_info *fs_info);
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 void btrfs_init_lockdep(void);
index ba58024d40d3eaf486c50d96cd116c3b828b9c75..3d3e2c17d8d12234a4a5fdcf2fc1af0eb717b6dd 100644 (file)
@@ -94,8 +94,8 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
                                     u64 flags, struct btrfs_disk_key *key,
                                     int level, struct btrfs_key *ins);
 static int do_chunk_alloc(struct btrfs_trans_handle *trans,
-                         struct btrfs_root *extent_root, u64 alloc_bytes,
-                         u64 flags, int force);
+                         struct btrfs_root *extent_root, u64 flags,
+                         int force);
 static int find_next_key(struct btrfs_path *path, int level,
                         struct btrfs_key *key);
 static void dump_space_info(struct btrfs_space_info *info, u64 bytes,
@@ -312,7 +312,8 @@ static u64 add_new_free_space(struct btrfs_block_group_cache *block_group,
        while (start < end) {
                ret = find_first_extent_bit(info->pinned_extents, start,
                                            &extent_start, &extent_end,
-                                           EXTENT_DIRTY | EXTENT_UPTODATE);
+                                           EXTENT_DIRTY | EXTENT_UPTODATE,
+                                           NULL);
                if (ret)
                        break;
 
@@ -2361,10 +2362,6 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
                }
 
 next:
-               do_chunk_alloc(trans, fs_info->extent_root,
-                              2 * 1024 * 1024,
-                              btrfs_get_alloc_profile(root, 0),
-                              CHUNK_ALLOC_NO_FORCE);
                cond_resched();
                spin_lock(&delayed_refs->lock);
        }
@@ -2478,10 +2475,6 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
        if (root == root->fs_info->extent_root)
                root = root->fs_info->tree_root;
 
-       do_chunk_alloc(trans, root->fs_info->extent_root,
-                      2 * 1024 * 1024, btrfs_get_alloc_profile(root, 0),
-                      CHUNK_ALLOC_NO_FORCE);
-
        btrfs_delayed_refs_qgroup_accounting(trans, root->fs_info);
 
        delayed_refs = &trans->transaction->delayed_refs;
@@ -2551,6 +2544,12 @@ again:
        }
 
        if (run_all) {
+               if (!list_empty(&trans->new_bgs)) {
+                       spin_unlock(&delayed_refs->lock);
+                       btrfs_create_pending_block_groups(trans, root);
+                       spin_lock(&delayed_refs->lock);
+               }
+
                node = rb_first(&delayed_refs->root);
                if (!node)
                        goto out;
@@ -3406,7 +3405,6 @@ alloc:
                                return PTR_ERR(trans);
 
                        ret = do_chunk_alloc(trans, root->fs_info->extent_root,
-                                            bytes + 2 * 1024 * 1024,
                                             alloc_target,
                                             CHUNK_ALLOC_NO_FORCE);
                        btrfs_end_transaction(trans, root);
@@ -3488,8 +3486,7 @@ static void force_metadata_allocation(struct btrfs_fs_info *info)
 }
 
 static int should_alloc_chunk(struct btrfs_root *root,
-                             struct btrfs_space_info *sinfo, u64 alloc_bytes,
-                             int force)
+                             struct btrfs_space_info *sinfo, int force)
 {
        struct btrfs_block_rsv *global_rsv = &root->fs_info->global_block_rsv;
        u64 num_bytes = sinfo->total_bytes - sinfo->bytes_readonly;
@@ -3504,7 +3501,8 @@ static int should_alloc_chunk(struct btrfs_root *root,
         * and purposes it's used space.  Don't worry about locking the
         * global_rsv, it doesn't change except when the transaction commits.
         */
-       num_allocated += global_rsv->size;
+       if (sinfo->flags & BTRFS_BLOCK_GROUP_METADATA)
+               num_allocated += global_rsv->size;
 
        /*
         * in limited mode, we want to have some free space up to
@@ -3518,15 +3516,8 @@ static int should_alloc_chunk(struct btrfs_root *root,
                if (num_bytes - num_allocated < thresh)
                        return 1;
        }
-       thresh = btrfs_super_total_bytes(root->fs_info->super_copy);
 
-       /* 256MB or 2% of the FS */
-       thresh = max_t(u64, 256 * 1024 * 1024, div_factor_fine(thresh, 2));
-       /* system chunks need a much small threshold */
-       if (sinfo->flags & BTRFS_BLOCK_GROUP_SYSTEM)
-               thresh = 32 * 1024 * 1024;
-
-       if (num_bytes > thresh && sinfo->bytes_used < div_factor(num_bytes, 8))
+       if (num_allocated + 2 * 1024 * 1024 < div_factor(num_bytes, 8))
                return 0;
        return 1;
 }
@@ -3576,8 +3567,7 @@ static void check_system_chunk(struct btrfs_trans_handle *trans,
 }
 
 static int do_chunk_alloc(struct btrfs_trans_handle *trans,
-                         struct btrfs_root *extent_root, u64 alloc_bytes,
-                         u64 flags, int force)
+                         struct btrfs_root *extent_root, u64 flags, int force)
 {
        struct btrfs_space_info *space_info;
        struct btrfs_fs_info *fs_info = extent_root->fs_info;
@@ -3601,7 +3591,7 @@ again:
                return 0;
        }
 
-       if (!should_alloc_chunk(extent_root, space_info, alloc_bytes, force)) {
+       if (!should_alloc_chunk(extent_root, space_info, force)) {
                spin_unlock(&space_info->lock);
                return 0;
        } else if (space_info->chunk_alloc) {
@@ -3669,6 +3659,46 @@ out:
        return ret;
 }
 
+static int can_overcommit(struct btrfs_root *root,
+                         struct btrfs_space_info *space_info, u64 bytes,
+                         int flush)
+{
+       u64 profile = btrfs_get_alloc_profile(root, 0);
+       u64 avail;
+       u64 used;
+
+       used = space_info->bytes_used + space_info->bytes_reserved +
+               space_info->bytes_pinned + space_info->bytes_readonly +
+               space_info->bytes_may_use;
+
+       spin_lock(&root->fs_info->free_chunk_lock);
+       avail = root->fs_info->free_chunk_space;
+       spin_unlock(&root->fs_info->free_chunk_lock);
+
+       /*
+        * If we have dup, raid1 or raid10 then only half of the free
+        * space is actually useable.
+        */
+       if (profile & (BTRFS_BLOCK_GROUP_DUP |
+                      BTRFS_BLOCK_GROUP_RAID1 |
+                      BTRFS_BLOCK_GROUP_RAID10))
+               avail >>= 1;
+
+       /*
+        * If we aren't flushing don't let us overcommit too much, say
+        * 1/8th of the space.  If we can flush, let it overcommit up to
+        * 1/2 of the space.
+        */
+       if (flush)
+               avail >>= 3;
+       else
+               avail >>= 1;
+
+       if (used + bytes < space_info->total_bytes + avail)
+               return 1;
+       return 0;
+}
+
 /*
  * shrink metadata reservation for delalloc
  */
@@ -3693,7 +3723,7 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,
        if (delalloc_bytes == 0) {
                if (trans)
                        return;
-               btrfs_wait_ordered_extents(root, 0, 0);
+               btrfs_wait_ordered_extents(root, 0);
                return;
        }
 
@@ -3703,11 +3733,15 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,
                writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages,
                                               WB_REASON_FS_FREE_SPACE);
 
+               /*
+                * We need to wait for the async pages to actually start before
+                * we do anything.
+                */
+               wait_event(root->fs_info->async_submit_wait,
+                          !atomic_read(&root->fs_info->async_delalloc_pages));
+
                spin_lock(&space_info->lock);
-               if (space_info->bytes_used + space_info->bytes_reserved +
-                   space_info->bytes_pinned + space_info->bytes_readonly +
-                   space_info->bytes_may_use + orig <=
-                   space_info->total_bytes) {
+               if (can_overcommit(root, space_info, orig, !trans)) {
                        spin_unlock(&space_info->lock);
                        break;
                }
@@ -3715,7 +3749,7 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,
 
                loops++;
                if (wait_ordered && !trans) {
-                       btrfs_wait_ordered_extents(root, 0, 0);
+                       btrfs_wait_ordered_extents(root, 0);
                } else {
                        time_left = schedule_timeout_killable(1);
                        if (time_left)
@@ -3784,11 +3818,12 @@ commit:
 }
 
 enum flush_state {
-       FLUSH_DELALLOC          =       1,
-       FLUSH_DELALLOC_WAIT     =       2,
-       FLUSH_DELAYED_ITEMS_NR  =       3,
-       FLUSH_DELAYED_ITEMS     =       4,
-       COMMIT_TRANS            =       5,
+       FLUSH_DELAYED_ITEMS_NR  =       1,
+       FLUSH_DELAYED_ITEMS     =       2,
+       FLUSH_DELALLOC          =       3,
+       FLUSH_DELALLOC_WAIT     =       4,
+       ALLOC_CHUNK             =       5,
+       COMMIT_TRANS            =       6,
 };
 
 static int flush_space(struct btrfs_root *root,
@@ -3800,11 +3835,6 @@ static int flush_space(struct btrfs_root *root,
        int ret = 0;
 
        switch (state) {
-       case FLUSH_DELALLOC:
-       case FLUSH_DELALLOC_WAIT:
-               shrink_delalloc(root, num_bytes, orig_bytes,
-                               state == FLUSH_DELALLOC_WAIT);
-               break;
        case FLUSH_DELAYED_ITEMS_NR:
        case FLUSH_DELAYED_ITEMS:
                if (state == FLUSH_DELAYED_ITEMS_NR) {
@@ -3825,6 +3855,24 @@ static int flush_space(struct btrfs_root *root,
                ret = btrfs_run_delayed_items_nr(trans, root, nr);
                btrfs_end_transaction(trans, root);
                break;
+       case FLUSH_DELALLOC:
+       case FLUSH_DELALLOC_WAIT:
+               shrink_delalloc(root, num_bytes, orig_bytes,
+                               state == FLUSH_DELALLOC_WAIT);
+               break;
+       case ALLOC_CHUNK:
+               trans = btrfs_join_transaction(root);
+               if (IS_ERR(trans)) {
+                       ret = PTR_ERR(trans);
+                       break;
+               }
+               ret = do_chunk_alloc(trans, root->fs_info->extent_root,
+                                    btrfs_get_alloc_profile(root, 0),
+                                    CHUNK_ALLOC_NO_FORCE);
+               btrfs_end_transaction(trans, root);
+               if (ret == -ENOSPC)
+                       ret = 0;
+               break;
        case COMMIT_TRANS:
                ret = may_commit_transaction(root, space_info, orig_bytes, 0);
                break;
@@ -3856,10 +3904,9 @@ static int reserve_metadata_bytes(struct btrfs_root *root,
        struct btrfs_space_info *space_info = block_rsv->space_info;
        u64 used;
        u64 num_bytes = orig_bytes;
-       int flush_state = FLUSH_DELALLOC;
+       int flush_state = FLUSH_DELAYED_ITEMS_NR;
        int ret = 0;
        bool flushing = false;
-       bool committed = false;
 
 again:
        ret = 0;
@@ -3922,57 +3969,12 @@ again:
                        (orig_bytes * 2);
        }
 
-       if (ret) {
-               u64 profile = btrfs_get_alloc_profile(root, 0);
-               u64 avail;
-
-               /*
-                * If we have a lot of space that's pinned, don't bother doing
-                * the overcommit dance yet and just commit the transaction.
-                */
-               avail = (space_info->total_bytes - space_info->bytes_used) * 8;
-               do_div(avail, 10);
-               if (space_info->bytes_pinned >= avail && flush && !committed) {
-                       space_info->flush = 1;
-                       flushing = true;
-                       spin_unlock(&space_info->lock);
-                       ret = may_commit_transaction(root, space_info,
-                                                    orig_bytes, 1);
-                       if (ret)
-                               goto out;
-                       committed = true;
-                       goto again;
-               }
-
-               spin_lock(&root->fs_info->free_chunk_lock);
-               avail = root->fs_info->free_chunk_space;
-
-               /*
-                * If we have dup, raid1 or raid10 then only half of the free
-                * space is actually useable.
-                */
-               if (profile & (BTRFS_BLOCK_GROUP_DUP |
-                              BTRFS_BLOCK_GROUP_RAID1 |
-                              BTRFS_BLOCK_GROUP_RAID10))
-                       avail >>= 1;
-
-               /*
-                * If we aren't flushing don't let us overcommit too much, say
-                * 1/8th of the space.  If we can flush, let it overcommit up to
-                * 1/2 of the space.
-                */
-               if (flush)
-                       avail >>= 3;
-               else
-                       avail >>= 1;
-                spin_unlock(&root->fs_info->free_chunk_lock);
-
-               if (used + num_bytes < space_info->total_bytes + avail) {
-                       space_info->bytes_may_use += orig_bytes;
-                       trace_btrfs_space_reservation(root->fs_info,
-                               "space_info", space_info->flags, orig_bytes, 1);
-                       ret = 0;
-               }
+       if (ret && can_overcommit(root, space_info, orig_bytes, flush)) {
+               space_info->bytes_may_use += orig_bytes;
+               trace_btrfs_space_reservation(root->fs_info, "space_info",
+                                             space_info->flags, orig_bytes,
+                                             1);
+               ret = 0;
        }
 
        /*
@@ -4114,13 +4116,15 @@ static int block_rsv_migrate_bytes(struct btrfs_block_rsv *src,
        return 0;
 }
 
-void btrfs_init_block_rsv(struct btrfs_block_rsv *rsv)
+void btrfs_init_block_rsv(struct btrfs_block_rsv *rsv, unsigned short type)
 {
        memset(rsv, 0, sizeof(*rsv));
        spin_lock_init(&rsv->lock);
+       rsv->type = type;
 }
 
-struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root)
+struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root,
+                                             unsigned short type)
 {
        struct btrfs_block_rsv *block_rsv;
        struct btrfs_fs_info *fs_info = root->fs_info;
@@ -4129,7 +4133,7 @@ struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root)
        if (!block_rsv)
                return NULL;
 
-       btrfs_init_block_rsv(block_rsv);
+       btrfs_init_block_rsv(block_rsv, type);
        block_rsv->space_info = __find_space_info(fs_info,
                                                  BTRFS_BLOCK_GROUP_METADATA);
        return block_rsv;
@@ -4138,6 +4142,8 @@ struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root)
 void btrfs_free_block_rsv(struct btrfs_root *root,
                          struct btrfs_block_rsv *rsv)
 {
+       if (!rsv)
+               return;
        btrfs_block_rsv_release(root, rsv, (u64)-1);
        kfree(rsv);
 }
@@ -4416,10 +4422,10 @@ int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans,
        struct btrfs_block_rsv *src_rsv = get_block_rsv(trans, root);
        struct btrfs_block_rsv *dst_rsv = &pending->block_rsv;
        /*
-        * two for root back/forward refs, two for directory entries
-        * and one for root of the snapshot.
+        * two for root back/forward refs, two for directory entries,
+        * one for root of the snapshot and one for parent inode.
         */
-       u64 num_bytes = btrfs_calc_trans_metadata_size(root, 5);
+       u64 num_bytes = btrfs_calc_trans_metadata_size(root, 6);
        dst_rsv->space_info = src_rsv->space_info;
        return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes);
 }
@@ -5018,7 +5024,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
 
        while (1) {
                ret = find_first_extent_bit(unpin, 0, &start, &end,
-                                           EXTENT_DIRTY);
+                                           EXTENT_DIRTY, NULL);
                if (ret)
                        break;
 
@@ -5096,8 +5102,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                        ret = remove_extent_backref(trans, extent_root, path,
                                                    NULL, refs_to_drop,
                                                    is_data);
-                       if (ret)
-                               goto abort;
+                       if (ret) {
+                               btrfs_abort_transaction(trans, extent_root, ret);
+                               goto out;
+                       }
                        btrfs_release_path(path);
                        path->leave_spinning = 1;
 
@@ -5115,8 +5123,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                                        btrfs_print_leaf(extent_root,
                                                         path->nodes[0]);
                        }
-                       if (ret < 0)
-                               goto abort;
+                       if (ret < 0) {
+                               btrfs_abort_transaction(trans, extent_root, ret);
+                               goto out;
+                       }
                        extent_slot = path->slots[0];
                }
        } else if (ret == -ENOENT) {
@@ -5130,7 +5140,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                       (unsigned long long)owner_objectid,
                       (unsigned long long)owner_offset);
        } else {
-               goto abort;
+               btrfs_abort_transaction(trans, extent_root, ret);
+               goto out;
        }
 
        leaf = path->nodes[0];
@@ -5140,8 +5151,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                BUG_ON(found_extent || extent_slot != path->slots[0]);
                ret = convert_extent_item_v0(trans, extent_root, path,
                                             owner_objectid, 0);
-               if (ret < 0)
-                       goto abort;
+               if (ret < 0) {
+                       btrfs_abort_transaction(trans, extent_root, ret);
+                       goto out;
+               }
 
                btrfs_release_path(path);
                path->leave_spinning = 1;
@@ -5158,8 +5171,11 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                               (unsigned long long)bytenr);
                        btrfs_print_leaf(extent_root, path->nodes[0]);
                }
-               if (ret < 0)
-                       goto abort;
+               if (ret < 0) {
+                       btrfs_abort_transaction(trans, extent_root, ret);
+                       goto out;
+               }
+
                extent_slot = path->slots[0];
                leaf = path->nodes[0];
                item_size = btrfs_item_size_nr(leaf, extent_slot);
@@ -5196,8 +5212,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                        ret = remove_extent_backref(trans, extent_root, path,
                                                    iref, refs_to_drop,
                                                    is_data);
-                       if (ret)
-                               goto abort;
+                       if (ret) {
+                               btrfs_abort_transaction(trans, extent_root, ret);
+                               goto out;
+                       }
                }
        } else {
                if (found_extent) {
@@ -5214,27 +5232,29 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
 
                ret = btrfs_del_items(trans, extent_root, path, path->slots[0],
                                      num_to_del);
-               if (ret)
-                       goto abort;
+               if (ret) {
+                       btrfs_abort_transaction(trans, extent_root, ret);
+                       goto out;
+               }
                btrfs_release_path(path);
 
                if (is_data) {
                        ret = btrfs_del_csums(trans, root, bytenr, num_bytes);
-                       if (ret)
-                               goto abort;
+                       if (ret) {
+                               btrfs_abort_transaction(trans, extent_root, ret);
+                               goto out;
+                       }
                }
 
                ret = update_block_group(trans, root, bytenr, num_bytes, 0);
-               if (ret)
-                       goto abort;
+               if (ret) {
+                       btrfs_abort_transaction(trans, extent_root, ret);
+                       goto out;
+               }
        }
 out:
        btrfs_free_path(path);
        return ret;
-
-abort:
-       btrfs_abort_transaction(trans, extent_root, ret);
-       goto out;
 }
 
 /*
@@ -5497,8 +5517,6 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
        struct btrfs_block_group_cache *used_block_group;
        u64 search_start = 0;
        int empty_cluster = 2 * 1024 * 1024;
-       int allowed_chunk_alloc = 0;
-       int done_chunk_alloc = 0;
        struct btrfs_space_info *space_info;
        int loop = 0;
        int index = 0;
@@ -5530,9 +5548,6 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
        if (btrfs_mixed_space_info(space_info))
                use_cluster = false;
 
-       if (orig_root->ref_cows || empty_size)
-               allowed_chunk_alloc = 1;
-
        if (data & BTRFS_BLOCK_GROUP_METADATA && use_cluster) {
                last_ptr = &root->fs_info->meta_alloc_cluster;
                if (!btrfs_test_opt(root, SSD))
@@ -5806,10 +5821,6 @@ checks:
 
                trace_btrfs_reserve_extent(orig_root, block_group,
                                           search_start, num_bytes);
-               if (offset < search_start)
-                       btrfs_add_free_space(used_block_group, offset,
-                                            search_start - offset);
-               BUG_ON(offset > search_start);
                if (used_block_group != block_group)
                        btrfs_put_block_group(used_block_group);
                btrfs_put_block_group(block_group);
@@ -5842,34 +5853,17 @@ loop:
                index = 0;
                loop++;
                if (loop == LOOP_ALLOC_CHUNK) {
-                      if (allowed_chunk_alloc) {
-                               ret = do_chunk_alloc(trans, root, num_bytes +
-                                                    2 * 1024 * 1024, data,
-                                                    CHUNK_ALLOC_LIMITED);
-                               /*
-                                * Do not bail out on ENOSPC since we
-                                * can do more things.
-                                */
-                               if (ret < 0 && ret != -ENOSPC) {
-                                       btrfs_abort_transaction(trans,
-                                                               root, ret);
-                                       goto out;
-                               }
-                               allowed_chunk_alloc = 0;
-                               if (ret == 1)
-                                       done_chunk_alloc = 1;
-                       } else if (!done_chunk_alloc &&
-                                  space_info->force_alloc ==
-                                  CHUNK_ALLOC_NO_FORCE) {
-                               space_info->force_alloc = CHUNK_ALLOC_LIMITED;
+                       ret = do_chunk_alloc(trans, root, data,
+                                            CHUNK_ALLOC_FORCE);
+                       /*
+                        * Do not bail out on ENOSPC since we
+                        * can do more things.
+                        */
+                       if (ret < 0 && ret != -ENOSPC) {
+                               btrfs_abort_transaction(trans,
+                                                       root, ret);
+                               goto out;
                        }
-
-                      /*
-                       * We didn't allocate a chunk, go ahead and drop the
-                       * empty size and loop again.
-                       */
-                      if (!done_chunk_alloc)
-                              loop = LOOP_NO_EMPTY_SIZE;
                }
 
                if (loop == LOOP_NO_EMPTY_SIZE) {
@@ -5944,20 +5938,6 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
 
        data = btrfs_get_alloc_profile(root, data);
 again:
-       /*
-        * the only place that sets empty_size is btrfs_realloc_node, which
-        * is not called recursively on allocations
-        */
-       if (empty_size || root->ref_cows) {
-               ret = do_chunk_alloc(trans, root->fs_info->extent_root,
-                                    num_bytes + 2 * 1024 * 1024, data,
-                                    CHUNK_ALLOC_NO_FORCE);
-               if (ret < 0 && ret != -ENOSPC) {
-                       btrfs_abort_transaction(trans, root, ret);
-                       return ret;
-               }
-       }
-
        WARN_ON(num_bytes < root->sectorsize);
        ret = find_free_extent(trans, root, num_bytes, empty_size,
                               hint_byte, ins, data);
@@ -5967,12 +5947,6 @@ again:
                        num_bytes = num_bytes >> 1;
                        num_bytes = num_bytes & ~(root->sectorsize - 1);
                        num_bytes = max(num_bytes, min_alloc_size);
-                       ret = do_chunk_alloc(trans, root->fs_info->extent_root,
-                                      num_bytes, data, CHUNK_ALLOC_FORCE);
-                       if (ret < 0 && ret != -ENOSPC) {
-                               btrfs_abort_transaction(trans, root, ret);
-                               return ret;
-                       }
                        if (num_bytes == min_alloc_size)
                                final_tried = true;
                        goto again;
@@ -6314,7 +6288,7 @@ use_block_rsv(struct btrfs_trans_handle *trans,
        ret = block_rsv_use_bytes(block_rsv, blocksize);
        if (!ret)
                return block_rsv;
-       if (ret) {
+       if (ret && !block_rsv->failfast) {
                static DEFINE_RATELIMIT_STATE(_rs,
                                DEFAULT_RATELIMIT_INTERVAL,
                                /*DEFAULT_RATELIMIT_BURST*/ 2);
@@ -7279,7 +7253,7 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
 
        alloc_flags = update_block_group_flags(root, cache->flags);
        if (alloc_flags != cache->flags) {
-               ret = do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags,
+               ret = do_chunk_alloc(trans, root, alloc_flags,
                                     CHUNK_ALLOC_FORCE);
                if (ret < 0)
                        goto out;
@@ -7289,7 +7263,7 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
        if (!ret)
                goto out;
        alloc_flags = get_alloc_profile(root, cache->space_info->flags);
-       ret = do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags,
+       ret = do_chunk_alloc(trans, root, alloc_flags,
                             CHUNK_ALLOC_FORCE);
        if (ret < 0)
                goto out;
@@ -7303,7 +7277,7 @@ int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans,
                            struct btrfs_root *root, u64 type)
 {
        u64 alloc_flags = get_alloc_profile(root, type);
-       return do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags,
+       return do_chunk_alloc(trans, root, alloc_flags,
                              CHUNK_ALLOC_FORCE);
 }
 
@@ -7810,6 +7784,34 @@ error:
        return ret;
 }
 
+void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans,
+                                      struct btrfs_root *root)
+{
+       struct btrfs_block_group_cache *block_group, *tmp;
+       struct btrfs_root *extent_root = root->fs_info->extent_root;
+       struct btrfs_block_group_item item;
+       struct btrfs_key key;
+       int ret = 0;
+
+       list_for_each_entry_safe(block_group, tmp, &trans->new_bgs,
+                                new_bg_list) {
+               list_del_init(&block_group->new_bg_list);
+
+               if (ret)
+                       continue;
+
+               spin_lock(&block_group->lock);
+               memcpy(&item, &block_group->item, sizeof(item));
+               memcpy(&key, &block_group->key, sizeof(key));
+               spin_unlock(&block_group->lock);
+
+               ret = btrfs_insert_item(trans, extent_root, &key, &item,
+                                       sizeof(item));
+               if (ret)
+                       btrfs_abort_transaction(trans, extent_root, ret);
+       }
+}
+
 int btrfs_make_block_group(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root, u64 bytes_used,
                           u64 type, u64 chunk_objectid, u64 chunk_offset,
@@ -7843,6 +7845,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
        spin_lock_init(&cache->lock);
        INIT_LIST_HEAD(&cache->list);
        INIT_LIST_HEAD(&cache->cluster_list);
+       INIT_LIST_HEAD(&cache->new_bg_list);
 
        btrfs_init_free_space_ctl(cache);
 
@@ -7874,12 +7877,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
        ret = btrfs_add_block_group_cache(root->fs_info, cache);
        BUG_ON(ret); /* Logic error */
 
-       ret = btrfs_insert_item(trans, extent_root, &cache->key, &cache->item,
-                               sizeof(cache->item));
-       if (ret) {
-               btrfs_abort_transaction(trans, extent_root, ret);
-               return ret;
-       }
+       list_add_tail(&cache->new_bg_list, &trans->new_bgs);
 
        set_avail_alloc_bits(extent_root->fs_info, type);
 
index b08ea4717e9d70ef7967fe33c1658b669eee16ac..8036d3a848530daed167453ebfb68eb8a83950f3 100644 (file)
@@ -45,6 +45,7 @@ struct extent_page_data {
        struct bio *bio;
        struct extent_io_tree *tree;
        get_extent_t *get_extent;
+       unsigned long bio_flags;
 
        /* tells writepage not to lock the state bits for this range
         * it still does the unlocking
@@ -64,13 +65,13 @@ tree_fs_info(struct extent_io_tree *tree)
 
 int __init extent_io_init(void)
 {
-       extent_state_cache = kmem_cache_create("extent_state",
+       extent_state_cache = kmem_cache_create("btrfs_extent_state",
                        sizeof(struct extent_state), 0,
                        SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
        if (!extent_state_cache)
                return -ENOMEM;
 
-       extent_buffer_cache = kmem_cache_create("extent_buffers",
+       extent_buffer_cache = kmem_cache_create("btrfs_extent_buffer",
                        sizeof(struct extent_buffer), 0,
                        SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
        if (!extent_buffer_cache)
@@ -942,6 +943,7 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int bits,
  * @end:       the end offset in bytes (inclusive)
  * @bits:      the bits to set in this range
  * @clear_bits:        the bits to clear in this range
+ * @cached_state:      state that we're going to cache
  * @mask:      the allocation mask
  *
  * This will go through and set bits for the given range.  If any states exist
@@ -951,7 +953,8 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int bits,
  * boundary bits like LOCK.
  */
 int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
-                      int bits, int clear_bits, gfp_t mask)
+                      int bits, int clear_bits,
+                      struct extent_state **cached_state, gfp_t mask)
 {
        struct extent_state *state;
        struct extent_state *prealloc = NULL;
@@ -968,6 +971,15 @@ again:
        }
 
        spin_lock(&tree->lock);
+       if (cached_state && *cached_state) {
+               state = *cached_state;
+               if (state->start <= start && state->end > start &&
+                   state->tree) {
+                       node = &state->rb_node;
+                       goto hit_next;
+               }
+       }
+
        /*
         * this search will find all the extents that end after
         * our range starts.
@@ -998,6 +1010,7 @@ hit_next:
         */
        if (state->start == start && state->end <= end) {
                set_state_bits(tree, state, &bits);
+               cache_state(state, cached_state);
                state = clear_state_bit(tree, state, &clear_bits, 0);
                if (last_end == (u64)-1)
                        goto out;
@@ -1038,6 +1051,7 @@ hit_next:
                        goto out;
                if (state->end <= end) {
                        set_state_bits(tree, state, &bits);
+                       cache_state(state, cached_state);
                        state = clear_state_bit(tree, state, &clear_bits, 0);
                        if (last_end == (u64)-1)
                                goto out;
@@ -1076,6 +1090,7 @@ hit_next:
                                   &bits);
                if (err)
                        extent_io_tree_panic(tree, err);
+               cache_state(prealloc, cached_state);
                prealloc = NULL;
                start = this_end + 1;
                goto search_again;
@@ -1098,6 +1113,7 @@ hit_next:
                        extent_io_tree_panic(tree, err);
 
                set_state_bits(tree, prealloc, &bits);
+               cache_state(prealloc, cached_state);
                clear_state_bit(tree, prealloc, &clear_bits, 0);
                prealloc = NULL;
                goto out;
@@ -1150,6 +1166,14 @@ int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end,
                              NULL, cached_state, mask);
 }
 
+int set_extent_defrag(struct extent_io_tree *tree, u64 start, u64 end,
+                     struct extent_state **cached_state, gfp_t mask)
+{
+       return set_extent_bit(tree, start, end,
+                             EXTENT_DELALLOC | EXTENT_UPTODATE | EXTENT_DEFRAG,
+                             NULL, cached_state, mask);
+}
+
 int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
                       gfp_t mask)
 {
@@ -1294,18 +1318,42 @@ out:
  * If nothing was found, 1 is returned. If found something, return 0.
  */
 int find_first_extent_bit(struct extent_io_tree *tree, u64 start,
-                         u64 *start_ret, u64 *end_ret, int bits)
+                         u64 *start_ret, u64 *end_ret, int bits,
+                         struct extent_state **cached_state)
 {
        struct extent_state *state;
+       struct rb_node *n;
        int ret = 1;
 
        spin_lock(&tree->lock);
+       if (cached_state && *cached_state) {
+               state = *cached_state;
+               if (state->end == start - 1 && state->tree) {
+                       n = rb_next(&state->rb_node);
+                       while (n) {
+                               state = rb_entry(n, struct extent_state,
+                                                rb_node);
+                               if (state->state & bits)
+                                       goto got_it;
+                               n = rb_next(n);
+                       }
+                       free_extent_state(*cached_state);
+                       *cached_state = NULL;
+                       goto out;
+               }
+               free_extent_state(*cached_state);
+               *cached_state = NULL;
+       }
+
        state = find_first_extent_bit_state(tree, start, bits);
+got_it:
        if (state) {
+               cache_state(state, cached_state);
                *start_ret = state->start;
                *end_ret = state->end;
                ret = 0;
        }
+out:
        spin_unlock(&tree->lock);
        return ret;
 }
@@ -2068,7 +2116,7 @@ static int bio_readpage_error(struct bio *failed_bio, struct page *page,
                }
                read_unlock(&em_tree->lock);
 
-               if (!em || IS_ERR(em)) {
+               if (!em) {
                        kfree(failrec);
                        return -EIO;
                }
@@ -2304,8 +2352,8 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                struct extent_state *cached = NULL;
                struct extent_state *state;
 
-               pr_debug("end_bio_extent_readpage: bi_vcnt=%d, idx=%d, err=%d, "
-                        "mirror=%ld\n", bio->bi_vcnt, bio->bi_idx, err,
+               pr_debug("end_bio_extent_readpage: bi_sector=%llu, err=%d, "
+                        "mirror=%ld\n", (u64)bio->bi_sector, err,
                         (long int)bio->bi_bdev);
                tree = &BTRFS_I(page->mapping->host)->io_tree;
 
@@ -2709,12 +2757,15 @@ static int __extent_read_full_page(struct extent_io_tree *tree,
                                         end_bio_extent_readpage, mirror_num,
                                         *bio_flags,
                                         this_bio_flag);
-                       BUG_ON(ret == -ENOMEM);
-                       nr++;
-                       *bio_flags = this_bio_flag;
+                       if (!ret) {
+                               nr++;
+                               *bio_flags = this_bio_flag;
+                       }
                }
-               if (ret)
+               if (ret) {
                        SetPageError(page);
+                       unlock_extent(tree, cur, cur + iosize - 1);
+               }
                cur = cur + iosize;
                pg_offset += iosize;
        }
@@ -3161,12 +3212,16 @@ static int write_one_eb(struct extent_buffer *eb,
        struct block_device *bdev = fs_info->fs_devices->latest_bdev;
        u64 offset = eb->start;
        unsigned long i, num_pages;
+       unsigned long bio_flags = 0;
        int rw = (epd->sync_io ? WRITE_SYNC : WRITE);
        int ret = 0;
 
        clear_bit(EXTENT_BUFFER_IOERR, &eb->bflags);
        num_pages = num_extent_pages(eb->start, eb->len);
        atomic_set(&eb->io_pages, num_pages);
+       if (btrfs_header_owner(eb) == BTRFS_TREE_LOG_OBJECTID)
+               bio_flags = EXTENT_BIO_TREE_LOG;
+
        for (i = 0; i < num_pages; i++) {
                struct page *p = extent_buffer_page(eb, i);
 
@@ -3175,7 +3230,8 @@ static int write_one_eb(struct extent_buffer *eb,
                ret = submit_extent_page(rw, eb->tree, p, offset >> 9,
                                         PAGE_CACHE_SIZE, 0, bdev, &epd->bio,
                                         -1, end_bio_extent_buffer_writepage,
-                                        0, 0, 0);
+                                        0, epd->bio_flags, bio_flags);
+               epd->bio_flags = bio_flags;
                if (ret) {
                        set_bit(EXTENT_BUFFER_IOERR, &eb->bflags);
                        SetPageError(p);
@@ -3210,6 +3266,7 @@ int btree_write_cache_pages(struct address_space *mapping,
                .tree = tree,
                .extent_locked = 0,
                .sync_io = wbc->sync_mode == WB_SYNC_ALL,
+               .bio_flags = 0,
        };
        int ret = 0;
        int done = 0;
@@ -3254,19 +3311,34 @@ retry:
                                break;
                        }
 
+                       spin_lock(&mapping->private_lock);
+                       if (!PagePrivate(page)) {
+                               spin_unlock(&mapping->private_lock);
+                               continue;
+                       }
+
                        eb = (struct extent_buffer *)page->private;
+
+                       /*
+                        * Shouldn't happen and normally this would be a BUG_ON
+                        * but no sense in crashing the users box for something
+                        * we can survive anyway.
+                        */
                        if (!eb) {
+                               spin_unlock(&mapping->private_lock);
                                WARN_ON(1);
                                continue;
                        }
 
-                       if (eb == prev_eb)
+                       if (eb == prev_eb) {
+                               spin_unlock(&mapping->private_lock);
                                continue;
+                       }
 
-                       if (!atomic_inc_not_zero(&eb->refs)) {
-                               WARN_ON(1);
+                       ret = atomic_inc_not_zero(&eb->refs);
+                       spin_unlock(&mapping->private_lock);
+                       if (!ret)
                                continue;
-                       }
 
                        prev_eb = eb;
                        ret = lock_extent_buffer_for_io(eb, fs_info, &epd);
@@ -3457,7 +3529,7 @@ static void flush_epd_write_bio(struct extent_page_data *epd)
                if (epd->sync_io)
                        rw = WRITE_SYNC;
 
-               ret = submit_one_bio(rw, epd->bio, 0, 0);
+               ret = submit_one_bio(rw, epd->bio, 0, epd->bio_flags);
                BUG_ON(ret < 0); /* -ENOMEM */
                epd->bio = NULL;
        }
@@ -3480,6 +3552,7 @@ int extent_write_full_page(struct extent_io_tree *tree, struct page *page,
                .get_extent = get_extent,
                .extent_locked = 0,
                .sync_io = wbc->sync_mode == WB_SYNC_ALL,
+               .bio_flags = 0,
        };
 
        ret = __extent_writepage(page, wbc, &epd);
@@ -3504,6 +3577,7 @@ int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode,
                .get_extent = get_extent,
                .extent_locked = 1,
                .sync_io = mode == WB_SYNC_ALL,
+               .bio_flags = 0,
        };
        struct writeback_control wbc_writepages = {
                .sync_mode      = mode,
@@ -3543,6 +3617,7 @@ int extent_writepages(struct extent_io_tree *tree,
                .get_extent = get_extent,
                .extent_locked = 0,
                .sync_io = wbc->sync_mode == WB_SYNC_ALL,
+               .bio_flags = 0,
        };
 
        ret = extent_write_cache_pages(tree, mapping, wbc,
@@ -3920,18 +3995,6 @@ out:
        return ret;
 }
 
-inline struct page *extent_buffer_page(struct extent_buffer *eb,
-                                             unsigned long i)
-{
-       return eb->pages[i];
-}
-
-inline unsigned long num_extent_pages(u64 start, u64 len)
-{
-       return ((start + len + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) -
-               (start >> PAGE_CACHE_SHIFT);
-}
-
 static void __free_extent_buffer(struct extent_buffer *eb)
 {
 #if LEAK_DEBUG
@@ -4047,7 +4110,7 @@ struct extent_buffer *alloc_dummy_extent_buffer(u64 start, unsigned long len)
 
        return eb;
 err:
-       for (i--; i > 0; i--)
+       for (i--; i >= 0; i--)
                __free_page(eb->pages[i]);
        __free_extent_buffer(eb);
        return NULL;
@@ -4192,10 +4255,8 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree,
 
        for (i = 0; i < num_pages; i++, index++) {
                p = find_or_create_page(mapping, index, GFP_NOFS);
-               if (!p) {
-                       WARN_ON(1);
+               if (!p)
                        goto free_eb;
-               }
 
                spin_lock(&mapping->private_lock);
                if (PagePrivate(p)) {
@@ -4338,7 +4399,6 @@ static int release_extent_buffer(struct extent_buffer *eb, gfp_t mask)
 
                /* Should be safe to release our pages at this point */
                btrfs_release_extent_buffer_page(eb, 0);
-
                call_rcu(&eb->rcu_head, btrfs_release_extent_buffer_rcu);
                return 1;
        }
index 25900af5b15d43e6bdfe0cef7c865ac2aa81bd36..711d12b80028b701033d7a326b28ed18b43e37ff 100644 (file)
@@ -27,6 +27,7 @@
  * type for this bio
  */
 #define EXTENT_BIO_COMPRESSED 1
+#define EXTENT_BIO_TREE_LOG 2
 #define EXTENT_BIO_FLAG_SHIFT 16
 
 /* these are bit numbers for test/set bit */
@@ -232,11 +233,15 @@ int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
 int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
                       gfp_t mask);
 int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
-                      int bits, int clear_bits, gfp_t mask);
+                      int bits, int clear_bits,
+                      struct extent_state **cached_state, gfp_t mask);
 int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end,
                        struct extent_state **cached_state, gfp_t mask);
+int set_extent_defrag(struct extent_io_tree *tree, u64 start, u64 end,
+                     struct extent_state **cached_state, gfp_t mask);
 int find_first_extent_bit(struct extent_io_tree *tree, u64 start,
-                         u64 *start_ret, u64 *end_ret, int bits);
+                         u64 *start_ret, u64 *end_ret, int bits,
+                         struct extent_state **cached_state);
 struct extent_state *find_first_extent_bit_state(struct extent_io_tree *tree,
                                                 u64 start, int bits);
 int extent_invalidatepage(struct extent_io_tree *tree,
@@ -277,8 +282,18 @@ void free_extent_buffer_stale(struct extent_buffer *eb);
 int read_extent_buffer_pages(struct extent_io_tree *tree,
                             struct extent_buffer *eb, u64 start, int wait,
                             get_extent_t *get_extent, int mirror_num);
-unsigned long num_extent_pages(u64 start, u64 len);
-struct page *extent_buffer_page(struct extent_buffer *eb, unsigned long i);
+
+static inline unsigned long num_extent_pages(u64 start, u64 len)
+{
+       return ((start + len + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) -
+               (start >> PAGE_CACHE_SHIFT);
+}
+
+static inline struct page *extent_buffer_page(struct extent_buffer *eb,
+                                             unsigned long i)
+{
+       return eb->pages[i];
+}
 
 static inline void extent_buffer_get(struct extent_buffer *eb)
 {
index 7c97b330145981d241cec9f13a75b3fa1869f8db..b8cbc8d5c7f7cb39ed770fb2b256427f25bb9c69 100644 (file)
@@ -11,7 +11,7 @@ static struct kmem_cache *extent_map_cache;
 
 int __init extent_map_init(void)
 {
-       extent_map_cache = kmem_cache_create("extent_map",
+       extent_map_cache = kmem_cache_create("btrfs_extent_map",
                        sizeof(struct extent_map), 0,
                        SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
        if (!extent_map_cache)
@@ -35,6 +35,7 @@ void extent_map_exit(void)
 void extent_map_tree_init(struct extent_map_tree *tree)
 {
        tree->map = RB_ROOT;
+       INIT_LIST_HEAD(&tree->modified_extents);
        rwlock_init(&tree->lock);
 }
 
@@ -54,7 +55,9 @@ struct extent_map *alloc_extent_map(void)
        em->in_tree = 0;
        em->flags = 0;
        em->compress_type = BTRFS_COMPRESS_NONE;
+       em->generation = 0;
        atomic_set(&em->refs, 1);
+       INIT_LIST_HEAD(&em->list);
        return em;
 }
 
@@ -72,6 +75,7 @@ void free_extent_map(struct extent_map *em)
        WARN_ON(atomic_read(&em->refs) == 0);
        if (atomic_dec_and_test(&em->refs)) {
                WARN_ON(em->in_tree);
+               WARN_ON(!list_empty(&em->list));
                kmem_cache_free(extent_map_cache, em);
        }
 }
@@ -198,6 +202,14 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
                        em->block_len += merge->block_len;
                        em->block_start = merge->block_start;
                        merge->in_tree = 0;
+                       if (merge->generation > em->generation) {
+                               em->mod_start = em->start;
+                               em->mod_len = em->len;
+                               em->generation = merge->generation;
+                               list_move(&em->list, &tree->modified_extents);
+                       }
+
+                       list_del_init(&merge->list);
                        rb_erase(&merge->rb_node, &tree->map);
                        free_extent_map(merge);
                }
@@ -211,14 +223,34 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
                em->block_len += merge->len;
                rb_erase(&merge->rb_node, &tree->map);
                merge->in_tree = 0;
+               if (merge->generation > em->generation) {
+                       em->mod_len = em->len;
+                       em->generation = merge->generation;
+                       list_move(&em->list, &tree->modified_extents);
+               }
+               list_del_init(&merge->list);
                free_extent_map(merge);
        }
 }
 
-int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len)
+/**
+ * unpint_extent_cache - unpin an extent from the cache
+ * @tree:      tree to unpin the extent in
+ * @start:     logical offset in the file
+ * @len:       length of the extent
+ * @gen:       generation that this extent has been modified in
+ * @prealloc:  if this is set we need to clear the prealloc flag
+ *
+ * Called after an extent has been written to disk properly.  Set the generation
+ * to the generation that actually added the file item to the inode so we know
+ * we need to sync this extent when we call fsync().
+ */
+int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len,
+                      u64 gen)
 {
        int ret = 0;
        struct extent_map *em;
+       bool prealloc = false;
 
        write_lock(&tree->lock);
        em = lookup_extent_mapping(tree, start, len);
@@ -228,10 +260,24 @@ int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len)
        if (!em)
                goto out;
 
+       list_move(&em->list, &tree->modified_extents);
+       em->generation = gen;
        clear_bit(EXTENT_FLAG_PINNED, &em->flags);
+       em->mod_start = em->start;
+       em->mod_len = em->len;
+
+       if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) {
+               prealloc = true;
+               clear_bit(EXTENT_FLAG_PREALLOC, &em->flags);
+       }
 
        try_merge_map(tree, em);
 
+       if (prealloc) {
+               em->mod_start = em->start;
+               em->mod_len = em->len;
+       }
+
        free_extent_map(em);
 out:
        write_unlock(&tree->lock);
@@ -269,6 +315,9 @@ int add_extent_mapping(struct extent_map_tree *tree,
        }
        atomic_inc(&em->refs);
 
+       em->mod_start = em->start;
+       em->mod_len = em->len;
+
        try_merge_map(tree, em);
 out:
        return ret;
@@ -358,6 +407,8 @@ int remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em)
 
        WARN_ON(test_bit(EXTENT_FLAG_PINNED, &em->flags));
        rb_erase(&em->rb_node, &tree->map);
+       if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags))
+               list_del_init(&em->list);
        em->in_tree = 0;
        return ret;
 }
index 1195f09761fedd2e5c109b74d3000c2973bc75f4..679225555f7b597b91012e5a47434a72e1774c91 100644 (file)
@@ -13,6 +13,7 @@
 #define EXTENT_FLAG_COMPRESSED 1
 #define EXTENT_FLAG_VACANCY 2 /* no file extent item found */
 #define EXTENT_FLAG_PREALLOC 3 /* pre-allocated extent */
+#define EXTENT_FLAG_LOGGING 4 /* Logging this extent */
 
 struct extent_map {
        struct rb_node rb_node;
@@ -20,18 +21,23 @@ struct extent_map {
        /* all of these are in bytes */
        u64 start;
        u64 len;
+       u64 mod_start;
+       u64 mod_len;
        u64 orig_start;
        u64 block_start;
        u64 block_len;
+       u64 generation;
        unsigned long flags;
        struct block_device *bdev;
        atomic_t refs;
        unsigned int in_tree;
        unsigned int compress_type;
+       struct list_head list;
 };
 
 struct extent_map_tree {
        struct rb_root map;
+       struct list_head modified_extents;
        rwlock_t lock;
 };
 
@@ -60,7 +66,7 @@ struct extent_map *alloc_extent_map(void);
 void free_extent_map(struct extent_map *em);
 int __init extent_map_init(void);
 void extent_map_exit(void);
-int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len);
+int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, u64 gen);
 struct extent_map *search_extent_mapping(struct extent_map_tree *tree,
                                         u64 start, u64 len);
 #endif
index 857d93cd01dc579eb46838624349442fef07cf00..1ad08e4e4a15fa25ea7f65397cbc1e154fa1f4b9 100644 (file)
 #include "transaction.h"
 #include "print-tree.h"
 
-#define __MAX_CSUM_ITEMS(r, size) ((((BTRFS_LEAF_DATA_SIZE(r) - \
+#define __MAX_CSUM_ITEMS(r, size) ((unsigned long)(((BTRFS_LEAF_DATA_SIZE(r) - \
                                   sizeof(struct btrfs_item) * 2) / \
                                  size) - 1))
 
-#define MAX_CSUM_ITEMS(r, size) (min(__MAX_CSUM_ITEMS(r, size), PAGE_CACHE_SIZE))
+#define MAX_CSUM_ITEMS(r, size) (min_t(u32, __MAX_CSUM_ITEMS(r, size), \
+                                      PAGE_CACHE_SIZE))
 
 #define MAX_ORDERED_SUM_BYTES(r) ((PAGE_SIZE - \
                                   sizeof(struct btrfs_ordered_sum)) / \
index f6b40e86121b007bf06954268254bcaae0fe7bf5..9ab1bed88116bd8f412f095aaef231f5bb749baf 100644 (file)
@@ -39,6 +39,7 @@
 #include "tree-log.h"
 #include "locking.h"
 #include "compat.h"
+#include "volumes.h"
 
 /*
  * when auto defrag is enabled we
@@ -458,14 +459,15 @@ int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode,
  * this drops all the extents in the cache that intersect the range
  * [start, end].  Existing extents are split as required.
  */
-int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
-                           int skip_pinned)
+void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
+                            int skip_pinned)
 {
        struct extent_map *em;
        struct extent_map *split = NULL;
        struct extent_map *split2 = NULL;
        struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
        u64 len = end - start + 1;
+       u64 gen;
        int ret;
        int testend = 1;
        unsigned long flags;
@@ -477,11 +479,14 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
                testend = 0;
        }
        while (1) {
+               int no_splits = 0;
+
                if (!split)
                        split = alloc_extent_map();
                if (!split2)
                        split2 = alloc_extent_map();
-               BUG_ON(!split || !split2); /* -ENOMEM */
+               if (!split || !split2)
+                       no_splits = 1;
 
                write_lock(&em_tree->lock);
                em = lookup_extent_mapping(em_tree, start, len);
@@ -490,6 +495,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
                        break;
                }
                flags = em->flags;
+               gen = em->generation;
                if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) {
                        if (testend && em->start + em->len >= start + len) {
                                free_extent_map(em);
@@ -506,6 +512,8 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
                compressed = test_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
                clear_bit(EXTENT_FLAG_PINNED, &em->flags);
                remove_extent_mapping(em_tree, em);
+               if (no_splits)
+                       goto next;
 
                if (em->block_start < EXTENT_MAP_LAST_BYTE &&
                    em->start < start) {
@@ -518,12 +526,13 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
                                split->block_len = em->block_len;
                        else
                                split->block_len = split->len;
-
+                       split->generation = gen;
                        split->bdev = em->bdev;
                        split->flags = flags;
                        split->compress_type = em->compress_type;
                        ret = add_extent_mapping(em_tree, split);
                        BUG_ON(ret); /* Logic error */
+                       list_move(&split->list, &em_tree->modified_extents);
                        free_extent_map(split);
                        split = split2;
                        split2 = NULL;
@@ -537,6 +546,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
                        split->bdev = em->bdev;
                        split->flags = flags;
                        split->compress_type = em->compress_type;
+                       split->generation = gen;
 
                        if (compressed) {
                                split->block_len = em->block_len;
@@ -550,9 +560,11 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
 
                        ret = add_extent_mapping(em_tree, split);
                        BUG_ON(ret); /* Logic error */
+                       list_move(&split->list, &em_tree->modified_extents);
                        free_extent_map(split);
                        split = NULL;
                }
+next:
                write_unlock(&em_tree->lock);
 
                /* once for us */
@@ -564,7 +576,6 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
                free_extent_map(split);
        if (split2)
                free_extent_map(split2);
-       return 0;
 }
 
 /*
@@ -576,13 +587,13 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
  * it is either truncated or split.  Anything entirely inside the range
  * is deleted from the tree.
  */
-int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,
-                      u64 start, u64 end, u64 *hint_byte, int drop_cache)
+int __btrfs_drop_extents(struct btrfs_trans_handle *trans,
+                        struct btrfs_root *root, struct inode *inode,
+                        struct btrfs_path *path, u64 start, u64 end,
+                        u64 *drop_end, int drop_cache)
 {
-       struct btrfs_root *root = BTRFS_I(inode)->root;
        struct extent_buffer *leaf;
        struct btrfs_file_extent_item *fi;
-       struct btrfs_path *path;
        struct btrfs_key key;
        struct btrfs_key new_key;
        u64 ino = btrfs_ino(inode);
@@ -597,14 +608,12 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,
        int recow;
        int ret;
        int modify_tree = -1;
+       int update_refs = (root->ref_cows || root == root->fs_info->tree_root);
+       int found = 0;
 
        if (drop_cache)
                btrfs_drop_extent_cache(inode, start, end - 1, 0);
 
-       path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
-
        if (start >= BTRFS_I(inode)->disk_i_size)
                modify_tree = 0;
 
@@ -666,6 +675,7 @@ next_slot:
                        goto next_slot;
                }
 
+               found = 1;
                search_start = max(key.offset, start);
                if (recow || !modify_tree) {
                        modify_tree = -1;
@@ -707,14 +717,13 @@ next_slot:
                                                        extent_end - start);
                        btrfs_mark_buffer_dirty(leaf);
 
-                       if (disk_bytenr > 0) {
+                       if (update_refs && disk_bytenr > 0) {
                                ret = btrfs_inc_extent_ref(trans, root,
                                                disk_bytenr, num_bytes, 0,
                                                root->root_key.objectid,
                                                new_key.objectid,
                                                start - extent_offset, 0);
                                BUG_ON(ret); /* -ENOMEM */
-                               *hint_byte = disk_bytenr;
                        }
                        key.offset = start;
                }
@@ -734,10 +743,8 @@ next_slot:
                        btrfs_set_file_extent_num_bytes(leaf, fi,
                                                        extent_end - end);
                        btrfs_mark_buffer_dirty(leaf);
-                       if (disk_bytenr > 0) {
+                       if (update_refs && disk_bytenr > 0)
                                inode_sub_bytes(inode, end - key.offset);
-                               *hint_byte = disk_bytenr;
-                       }
                        break;
                }
 
@@ -753,10 +760,8 @@ next_slot:
                        btrfs_set_file_extent_num_bytes(leaf, fi,
                                                        start - key.offset);
                        btrfs_mark_buffer_dirty(leaf);
-                       if (disk_bytenr > 0) {
+                       if (update_refs && disk_bytenr > 0)
                                inode_sub_bytes(inode, extent_end - start);
-                               *hint_byte = disk_bytenr;
-                       }
                        if (end == extent_end)
                                break;
 
@@ -777,12 +782,13 @@ next_slot:
                                del_nr++;
                        }
 
-                       if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
+                       if (update_refs &&
+                           extent_type == BTRFS_FILE_EXTENT_INLINE) {
                                inode_sub_bytes(inode,
                                                extent_end - key.offset);
                                extent_end = ALIGN(extent_end,
                                                   root->sectorsize);
-                       } else if (disk_bytenr > 0) {
+                       } else if (update_refs && disk_bytenr > 0) {
                                ret = btrfs_free_extent(trans, root,
                                                disk_bytenr, num_bytes, 0,
                                                root->root_key.objectid,
@@ -791,7 +797,6 @@ next_slot:
                                BUG_ON(ret); /* -ENOMEM */
                                inode_sub_bytes(inode,
                                                extent_end - key.offset);
-                               *hint_byte = disk_bytenr;
                        }
 
                        if (end == extent_end)
@@ -806,7 +811,7 @@ next_slot:
                                              del_nr);
                        if (ret) {
                                btrfs_abort_transaction(trans, root, ret);
-                               goto out;
+                               break;
                        }
 
                        del_nr = 0;
@@ -825,7 +830,24 @@ next_slot:
                        btrfs_abort_transaction(trans, root, ret);
        }
 
-out:
+       if (drop_end)
+               *drop_end = found ? min(end, extent_end) : end;
+       btrfs_release_path(path);
+       return ret;
+}
+
+int btrfs_drop_extents(struct btrfs_trans_handle *trans,
+                      struct btrfs_root *root, struct inode *inode, u64 start,
+                      u64 end, int drop_cache)
+{
+       struct btrfs_path *path;
+       int ret;
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+       ret = __btrfs_drop_extents(trans, root, inode, path, start, end, NULL,
+                                  drop_cache);
        btrfs_free_path(path);
        return ret;
 }
@@ -892,8 +914,6 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
        int ret;
        u64 ino = btrfs_ino(inode);
 
-       btrfs_drop_extent_cache(inode, start, end - 1, 0);
-
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
@@ -935,12 +955,16 @@ again:
                        btrfs_set_item_key_safe(trans, root, path, &new_key);
                        fi = btrfs_item_ptr(leaf, path->slots[0],
                                            struct btrfs_file_extent_item);
+                       btrfs_set_file_extent_generation(leaf, fi,
+                                                        trans->transid);
                        btrfs_set_file_extent_num_bytes(leaf, fi,
                                                        extent_end - end);
                        btrfs_set_file_extent_offset(leaf, fi,
                                                     end - orig_offset);
                        fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
                                            struct btrfs_file_extent_item);
+                       btrfs_set_file_extent_generation(leaf, fi,
+                                                        trans->transid);
                        btrfs_set_file_extent_num_bytes(leaf, fi,
                                                        end - other_start);
                        btrfs_mark_buffer_dirty(leaf);
@@ -958,12 +982,16 @@ again:
                                            struct btrfs_file_extent_item);
                        btrfs_set_file_extent_num_bytes(leaf, fi,
                                                        start - key.offset);
+                       btrfs_set_file_extent_generation(leaf, fi,
+                                                        trans->transid);
                        path->slots[0]++;
                        new_key.offset = start;
                        btrfs_set_item_key_safe(trans, root, path, &new_key);
 
                        fi = btrfs_item_ptr(leaf, path->slots[0],
                                            struct btrfs_file_extent_item);
+                       btrfs_set_file_extent_generation(leaf, fi,
+                                                        trans->transid);
                        btrfs_set_file_extent_num_bytes(leaf, fi,
                                                        other_end - start);
                        btrfs_set_file_extent_offset(leaf, fi,
@@ -991,12 +1019,14 @@ again:
                leaf = path->nodes[0];
                fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
                                    struct btrfs_file_extent_item);
+               btrfs_set_file_extent_generation(leaf, fi, trans->transid);
                btrfs_set_file_extent_num_bytes(leaf, fi,
                                                split - key.offset);
 
                fi = btrfs_item_ptr(leaf, path->slots[0],
                                    struct btrfs_file_extent_item);
 
+               btrfs_set_file_extent_generation(leaf, fi, trans->transid);
                btrfs_set_file_extent_offset(leaf, fi, split - orig_offset);
                btrfs_set_file_extent_num_bytes(leaf, fi,
                                                extent_end - split);
@@ -1056,12 +1086,14 @@ again:
                           struct btrfs_file_extent_item);
                btrfs_set_file_extent_type(leaf, fi,
                                           BTRFS_FILE_EXTENT_REG);
+               btrfs_set_file_extent_generation(leaf, fi, trans->transid);
                btrfs_mark_buffer_dirty(leaf);
        } else {
                fi = btrfs_item_ptr(leaf, del_slot - 1,
                           struct btrfs_file_extent_item);
                btrfs_set_file_extent_type(leaf, fi,
                                           BTRFS_FILE_EXTENT_REG);
+               btrfs_set_file_extent_generation(leaf, fi, trans->transid);
                btrfs_set_file_extent_num_bytes(leaf, fi,
                                                extent_end - key.offset);
                btrfs_mark_buffer_dirty(leaf);
@@ -1173,8 +1205,8 @@ again:
 
                clear_extent_bit(&BTRFS_I(inode)->io_tree, start_pos,
                                  last_pos - 1, EXTENT_DIRTY | EXTENT_DELALLOC |
-                                 EXTENT_DO_ACCOUNTING, 0, 0, &cached_state,
-                                 GFP_NOFS);
+                                 EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
+                                 0, 0, &cached_state, GFP_NOFS);
                unlock_extent_cached(&BTRFS_I(inode)->io_tree,
                                     start_pos, last_pos - 1, &cached_state,
                                     GFP_NOFS);
@@ -1514,16 +1546,24 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 
        trace_btrfs_sync_file(file, datasync);
 
+       /*
+        * We write the dirty pages in the range and wait until they complete
+        * out of the ->i_mutex. If so, we can flush the dirty pages by
+        * multi-task, and make the performance up.
+        */
+       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret)
+               return ret;
+
        mutex_lock(&inode->i_mutex);
 
        /*
-        * we wait first, since the writeback may change the inode, also wait
-        * ordered range does a filemape_write_and_wait_range which is why we
-        * don't do it above like other file systems.
+        * We flush the dirty pages again to avoid some dirty pages in the
+        * range being left.
         */
-       root->log_batch++;
+       atomic_inc(&root->log_batch);
        btrfs_wait_ordered_range(inode, start, end);
-       root->log_batch++;
+       atomic_inc(&root->log_batch);
 
        /*
         * check the transaction that last modified this inode
@@ -1544,6 +1584,14 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
            BTRFS_I(inode)->last_trans <=
            root->fs_info->last_trans_committed) {
                BTRFS_I(inode)->last_trans = 0;
+
+               /*
+                * We'v had everything committed since the last time we were
+                * modified so clear this flag in case it was set for whatever
+                * reason, it's no longer relevant.
+                */
+               clear_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
+                         &BTRFS_I(inode)->runtime_flags);
                mutex_unlock(&inode->i_mutex);
                goto out;
        }
@@ -1615,6 +1663,324 @@ static int btrfs_file_mmap(struct file  *filp, struct vm_area_struct *vma)
        return 0;
 }
 
+static int hole_mergeable(struct inode *inode, struct extent_buffer *leaf,
+                         int slot, u64 start, u64 end)
+{
+       struct btrfs_file_extent_item *fi;
+       struct btrfs_key key;
+
+       if (slot < 0 || slot >= btrfs_header_nritems(leaf))
+               return 0;
+
+       btrfs_item_key_to_cpu(leaf, &key, slot);
+       if (key.objectid != btrfs_ino(inode) ||
+           key.type != BTRFS_EXTENT_DATA_KEY)
+               return 0;
+
+       fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
+
+       if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_REG)
+               return 0;
+
+       if (btrfs_file_extent_disk_bytenr(leaf, fi))
+               return 0;
+
+       if (key.offset == end)
+               return 1;
+       if (key.offset + btrfs_file_extent_num_bytes(leaf, fi) == start)
+               return 1;
+       return 0;
+}
+
+static int fill_holes(struct btrfs_trans_handle *trans, struct inode *inode,
+                     struct btrfs_path *path, u64 offset, u64 end)
+{
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct extent_buffer *leaf;
+       struct btrfs_file_extent_item *fi;
+       struct extent_map *hole_em;
+       struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
+       struct btrfs_key key;
+       int ret;
+
+       key.objectid = btrfs_ino(inode);
+       key.type = BTRFS_EXTENT_DATA_KEY;
+       key.offset = offset;
+
+
+       ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
+       if (ret < 0)
+               return ret;
+       BUG_ON(!ret);
+
+       leaf = path->nodes[0];
+       if (hole_mergeable(inode, leaf, path->slots[0]-1, offset, end)) {
+               u64 num_bytes;
+
+               path->slots[0]--;
+               fi = btrfs_item_ptr(leaf, path->slots[0],
+                                   struct btrfs_file_extent_item);
+               num_bytes = btrfs_file_extent_num_bytes(leaf, fi) +
+                       end - offset;
+               btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes);
+               btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
+               btrfs_set_file_extent_offset(leaf, fi, 0);
+               btrfs_mark_buffer_dirty(leaf);
+               goto out;
+       }
+
+       if (hole_mergeable(inode, leaf, path->slots[0]+1, offset, end)) {
+               u64 num_bytes;
+
+               path->slots[0]++;
+               key.offset = offset;
+               btrfs_set_item_key_safe(trans, root, path, &key);
+               fi = btrfs_item_ptr(leaf, path->slots[0],
+                                   struct btrfs_file_extent_item);
+               num_bytes = btrfs_file_extent_num_bytes(leaf, fi) + end -
+                       offset;
+               btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes);
+               btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
+               btrfs_set_file_extent_offset(leaf, fi, 0);
+               btrfs_mark_buffer_dirty(leaf);
+               goto out;
+       }
+       btrfs_release_path(path);
+
+       ret = btrfs_insert_file_extent(trans, root, btrfs_ino(inode), offset,
+                                      0, 0, end - offset, 0, end - offset,
+                                      0, 0, 0);
+       if (ret)
+               return ret;
+
+out:
+       btrfs_release_path(path);
+
+       hole_em = alloc_extent_map();
+       if (!hole_em) {
+               btrfs_drop_extent_cache(inode, offset, end - 1, 0);
+               set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
+                       &BTRFS_I(inode)->runtime_flags);
+       } else {
+               hole_em->start = offset;
+               hole_em->len = end - offset;
+               hole_em->orig_start = offset;
+
+               hole_em->block_start = EXTENT_MAP_HOLE;
+               hole_em->block_len = 0;
+               hole_em->bdev = root->fs_info->fs_devices->latest_bdev;
+               hole_em->compress_type = BTRFS_COMPRESS_NONE;
+               hole_em->generation = trans->transid;
+
+               do {
+                       btrfs_drop_extent_cache(inode, offset, end - 1, 0);
+                       write_lock(&em_tree->lock);
+                       ret = add_extent_mapping(em_tree, hole_em);
+                       if (!ret)
+                               list_move(&hole_em->list,
+                                         &em_tree->modified_extents);
+                       write_unlock(&em_tree->lock);
+               } while (ret == -EEXIST);
+               free_extent_map(hole_em);
+               if (ret)
+                       set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
+                               &BTRFS_I(inode)->runtime_flags);
+       }
+
+       return 0;
+}
+
+static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
+{
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct extent_state *cached_state = NULL;
+       struct btrfs_path *path;
+       struct btrfs_block_rsv *rsv;
+       struct btrfs_trans_handle *trans;
+       u64 mask = BTRFS_I(inode)->root->sectorsize - 1;
+       u64 lockstart = (offset + mask) & ~mask;
+       u64 lockend = ((offset + len) & ~mask) - 1;
+       u64 cur_offset = lockstart;
+       u64 min_size = btrfs_calc_trunc_metadata_size(root, 1);
+       u64 drop_end;
+       unsigned long nr;
+       int ret = 0;
+       int err = 0;
+       bool same_page = (offset >> PAGE_CACHE_SHIFT) ==
+               ((offset + len) >> PAGE_CACHE_SHIFT);
+
+       btrfs_wait_ordered_range(inode, offset, len);
+
+       mutex_lock(&inode->i_mutex);
+       if (offset >= inode->i_size) {
+               mutex_unlock(&inode->i_mutex);
+               return 0;
+       }
+
+       /*
+        * Only do this if we are in the same page and we aren't doing the
+        * entire page.
+        */
+       if (same_page && len < PAGE_CACHE_SIZE) {
+               ret = btrfs_truncate_page(inode, offset, len, 0);
+               mutex_unlock(&inode->i_mutex);
+               return ret;
+       }
+
+       /* zero back part of the first page */
+       ret = btrfs_truncate_page(inode, offset, 0, 0);
+       if (ret) {
+               mutex_unlock(&inode->i_mutex);
+               return ret;
+       }
+
+       /* zero the front end of the last page */
+       ret = btrfs_truncate_page(inode, offset + len, 0, 1);
+       if (ret) {
+               mutex_unlock(&inode->i_mutex);
+               return ret;
+       }
+
+       if (lockend < lockstart) {
+               mutex_unlock(&inode->i_mutex);
+               return 0;
+       }
+
+       while (1) {
+               struct btrfs_ordered_extent *ordered;
+
+               truncate_pagecache_range(inode, lockstart, lockend);
+
+               lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend,
+                                0, &cached_state);
+               ordered = btrfs_lookup_first_ordered_extent(inode, lockend);
+
+               /*
+                * We need to make sure we have no ordered extents in this range
+                * and nobody raced in and read a page in this range, if we did
+                * we need to try again.
+                */
+               if ((!ordered ||
+                   (ordered->file_offset + ordered->len < lockstart ||
+                    ordered->file_offset > lockend)) &&
+                    !test_range_bit(&BTRFS_I(inode)->io_tree, lockstart,
+                                    lockend, EXTENT_UPTODATE, 0,
+                                    cached_state)) {
+                       if (ordered)
+                               btrfs_put_ordered_extent(ordered);
+                       break;
+               }
+               if (ordered)
+                       btrfs_put_ordered_extent(ordered);
+               unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart,
+                                    lockend, &cached_state, GFP_NOFS);
+               btrfs_wait_ordered_range(inode, lockstart,
+                                        lockend - lockstart + 1);
+       }
+
+       path = btrfs_alloc_path();
+       if (!path) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       rsv = btrfs_alloc_block_rsv(root, BTRFS_BLOCK_RSV_TEMP);
+       if (!rsv) {
+               ret = -ENOMEM;
+               goto out_free;
+       }
+       rsv->size = btrfs_calc_trunc_metadata_size(root, 1);
+       rsv->failfast = 1;
+
+       /*
+        * 1 - update the inode
+        * 1 - removing the extents in the range
+        * 1 - adding the hole extent
+        */
+       trans = btrfs_start_transaction(root, 3);
+       if (IS_ERR(trans)) {
+               err = PTR_ERR(trans);
+               goto out_free;
+       }
+
+       ret = btrfs_block_rsv_migrate(&root->fs_info->trans_block_rsv, rsv,
+                                     min_size);
+       BUG_ON(ret);
+       trans->block_rsv = rsv;
+
+       while (cur_offset < lockend) {
+               ret = __btrfs_drop_extents(trans, root, inode, path,
+                                          cur_offset, lockend + 1,
+                                          &drop_end, 1);
+               if (ret != -ENOSPC)
+                       break;
+
+               trans->block_rsv = &root->fs_info->trans_block_rsv;
+
+               ret = fill_holes(trans, inode, path, cur_offset, drop_end);
+               if (ret) {
+                       err = ret;
+                       break;
+               }
+
+               cur_offset = drop_end;
+
+               ret = btrfs_update_inode(trans, root, inode);
+               if (ret) {
+                       err = ret;
+                       break;
+               }
+
+               nr = trans->blocks_used;
+               btrfs_end_transaction(trans, root);
+               btrfs_btree_balance_dirty(root, nr);
+
+               trans = btrfs_start_transaction(root, 3);
+               if (IS_ERR(trans)) {
+                       ret = PTR_ERR(trans);
+                       trans = NULL;
+                       break;
+               }
+
+               ret = btrfs_block_rsv_migrate(&root->fs_info->trans_block_rsv,
+                                             rsv, min_size);
+               BUG_ON(ret);    /* shouldn't happen */
+               trans->block_rsv = rsv;
+       }
+
+       if (ret) {
+               err = ret;
+               goto out_trans;
+       }
+
+       trans->block_rsv = &root->fs_info->trans_block_rsv;
+       ret = fill_holes(trans, inode, path, cur_offset, drop_end);
+       if (ret) {
+               err = ret;
+               goto out_trans;
+       }
+
+out_trans:
+       if (!trans)
+               goto out_free;
+
+       trans->block_rsv = &root->fs_info->trans_block_rsv;
+       ret = btrfs_update_inode(trans, root, inode);
+       nr = trans->blocks_used;
+       btrfs_end_transaction(trans, root);
+       btrfs_btree_balance_dirty(root, nr);
+out_free:
+       btrfs_free_path(path);
+       btrfs_free_block_rsv(root, rsv);
+out:
+       unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend,
+                            &cached_state, GFP_NOFS);
+       mutex_unlock(&inode->i_mutex);
+       if (ret && !err)
+               err = ret;
+       return err;
+}
+
 static long btrfs_fallocate(struct file *file, int mode,
                            loff_t offset, loff_t len)
 {
@@ -1633,15 +1999,18 @@ static long btrfs_fallocate(struct file *file, int mode,
        alloc_start = offset & ~mask;
        alloc_end =  (offset + len + mask) & ~mask;
 
-       /* We only support the FALLOC_FL_KEEP_SIZE mode */
-       if (mode & ~FALLOC_FL_KEEP_SIZE)
+       /* Make sure we aren't being give some crap mode */
+       if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
                return -EOPNOTSUPP;
 
+       if (mode & FALLOC_FL_PUNCH_HOLE)
+               return btrfs_punch_hole(inode, offset, len);
+
        /*
         * Make sure we have enough space before we do the
         * allocation.
         */
-       ret = btrfs_check_data_free_space(inode, len);
+       ret = btrfs_check_data_free_space(inode, alloc_end - alloc_start + 1);
        if (ret)
                return ret;
 
@@ -1748,7 +2117,7 @@ static long btrfs_fallocate(struct file *file, int mode,
 out:
        mutex_unlock(&inode->i_mutex);
        /* Let go of our reservation. */
-       btrfs_free_reserved_data_space(inode, len);
+       btrfs_free_reserved_data_space(inode, alloc_end - alloc_start + 1);
        return ret;
 }
 
index 6b10acfc2f5cae609fca043caba43f0d57b60dd2..1027b854b90cec02b9d2328804bc12f23f9bc00b 100644 (file)
@@ -966,7 +966,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
                               block_group->key.offset)) {
                ret = find_first_extent_bit(unpin, start,
                                            &extent_start, &extent_end,
-                                           EXTENT_DIRTY);
+                                           EXTENT_DIRTY, NULL);
                if (ret) {
                        ret = 0;
                        break;
@@ -1454,9 +1454,7 @@ static int search_bitmap(struct btrfs_free_space_ctl *ctl,
                          max_t(u64, *offset, bitmap_info->offset));
        bits = bytes_to_bits(*bytes, ctl->unit);
 
-       for (i = find_next_bit(bitmap_info->bitmap, BITS_PER_BITMAP, i);
-            i < BITS_PER_BITMAP;
-            i = find_next_bit(bitmap_info->bitmap, BITS_PER_BITMAP, i + 1)) {
+       for_each_set_bit_from(i, bitmap_info->bitmap, BITS_PER_BITMAP) {
                next_zero = find_next_zero_bit(bitmap_info->bitmap,
                                               BITS_PER_BITMAP, i);
                if ((next_zero - i) >= bits) {
@@ -2307,9 +2305,7 @@ static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group,
 
 again:
        found_bits = 0;
-       for (i = find_next_bit(entry->bitmap, BITS_PER_BITMAP, i);
-            i < BITS_PER_BITMAP;
-            i = find_next_bit(entry->bitmap, BITS_PER_BITMAP, i + 1)) {
+       for_each_set_bit_from(i, entry->bitmap, BITS_PER_BITMAP) {
                next_zero = find_next_zero_bit(entry->bitmap,
                                               BITS_PER_BITMAP, i);
                if (next_zero - i >= min_bits) {
index db2ff9773b99d02300e84f4bec207f59c65e73ef..1d982812ab6761077673985dea55970f418cedf7 100644 (file)
@@ -24,4 +24,14 @@ static inline u64 btrfs_name_hash(const char *name, int len)
 {
        return crc32c((u32)~1, name, len);
 }
+
+/*
+ * Figure the key offset of an extended inode ref
+ */
+static inline u64 btrfs_extref_hash(u64 parent_objectid, const char *name,
+                                   int len)
+{
+       return (u64) crc32c(parent_objectid, name, len);
+}
+
 #endif
index a13cf1a96c73ca00f4baa453f864029c03525fe4..48b8fda93132b799b695efc4f1bd9e59cca1f064 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "ctree.h"
 #include "disk-io.h"
+#include "hash.h"
 #include "transaction.h"
 #include "print-tree.h"
 
@@ -50,18 +51,57 @@ static int find_name_in_backref(struct btrfs_path *path, const char *name,
        return 0;
 }
 
-struct btrfs_inode_ref *
+int btrfs_find_name_in_ext_backref(struct btrfs_path *path, u64 ref_objectid,
+                                  const char *name, int name_len,
+                                  struct btrfs_inode_extref **extref_ret)
+{
+       struct extent_buffer *leaf;
+       struct btrfs_inode_extref *extref;
+       unsigned long ptr;
+       unsigned long name_ptr;
+       u32 item_size;
+       u32 cur_offset = 0;
+       int ref_name_len;
+
+       leaf = path->nodes[0];
+       item_size = btrfs_item_size_nr(leaf, path->slots[0]);
+       ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
+
+       /*
+        * Search all extended backrefs in this item. We're only
+        * looking through any collisions so most of the time this is
+        * just going to compare against one buffer. If all is well,
+        * we'll return success and the inode ref object.
+        */
+       while (cur_offset < item_size) {
+               extref = (struct btrfs_inode_extref *) (ptr + cur_offset);
+               name_ptr = (unsigned long)(&extref->name);
+               ref_name_len = btrfs_inode_extref_name_len(leaf, extref);
+
+               if (ref_name_len == name_len &&
+                   btrfs_inode_extref_parent(leaf, extref) == ref_objectid &&
+                   (memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0)) {
+                       if (extref_ret)
+                               *extref_ret = extref;
+                       return 1;
+               }
+
+               cur_offset += ref_name_len + sizeof(*extref);
+       }
+       return 0;
+}
+
+static struct btrfs_inode_ref *
 btrfs_lookup_inode_ref(struct btrfs_trans_handle *trans,
-                       struct btrfs_root *root,
-                       struct btrfs_path *path,
-                       const char *name, int name_len,
-                       u64 inode_objectid, u64 ref_objectid, int mod)
+                      struct btrfs_root *root,
+                      struct btrfs_path *path,
+                      const char *name, int name_len,
+                      u64 inode_objectid, u64 ref_objectid, int ins_len,
+                      int cow)
 {
+       int ret;
        struct btrfs_key key;
        struct btrfs_inode_ref *ref;
-       int ins_len = mod < 0 ? -1 : 0;
-       int cow = mod != 0;
-       int ret;
 
        key.objectid = inode_objectid;
        key.type = BTRFS_INODE_REF_KEY;
@@ -77,10 +117,147 @@ btrfs_lookup_inode_ref(struct btrfs_trans_handle *trans,
        return ref;
 }
 
-int btrfs_del_inode_ref(struct btrfs_trans_handle *trans,
+/* Returns NULL if no extref found */
+struct btrfs_inode_extref *
+btrfs_lookup_inode_extref(struct btrfs_trans_handle *trans,
+                         struct btrfs_root *root,
+                         struct btrfs_path *path,
+                         const char *name, int name_len,
+                         u64 inode_objectid, u64 ref_objectid, int ins_len,
+                         int cow)
+{
+       int ret;
+       struct btrfs_key key;
+       struct btrfs_inode_extref *extref;
+
+       key.objectid = inode_objectid;
+       key.type = BTRFS_INODE_EXTREF_KEY;
+       key.offset = btrfs_extref_hash(ref_objectid, name, name_len);
+
+       ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
+       if (ret < 0)
+               return ERR_PTR(ret);
+       if (ret > 0)
+               return NULL;
+       if (!btrfs_find_name_in_ext_backref(path, ref_objectid, name, name_len, &extref))
+               return NULL;
+       return extref;
+}
+
+int btrfs_get_inode_ref_index(struct btrfs_trans_handle *trans,
+                             struct btrfs_root *root,
+                             struct btrfs_path *path,
+                             const char *name, int name_len,
+                             u64 inode_objectid, u64 ref_objectid, int mod,
+                             u64 *ret_index)
+{
+       struct btrfs_inode_ref *ref;
+       struct btrfs_inode_extref *extref;
+       int ins_len = mod < 0 ? -1 : 0;
+       int cow = mod != 0;
+
+       ref = btrfs_lookup_inode_ref(trans, root, path, name, name_len,
+                                    inode_objectid, ref_objectid, ins_len,
+                                    cow);
+       if (IS_ERR(ref))
+               return PTR_ERR(ref);
+
+       if (ref != NULL) {
+               *ret_index = btrfs_inode_ref_index(path->nodes[0], ref);
+               return 0;
+       }
+
+       btrfs_release_path(path);
+
+       extref = btrfs_lookup_inode_extref(trans, root, path, name,
+                                          name_len, inode_objectid,
+                                          ref_objectid, ins_len, cow);
+       if (IS_ERR(extref))
+               return PTR_ERR(extref);
+
+       if (extref) {
+               *ret_index = btrfs_inode_extref_index(path->nodes[0], extref);
+               return 0;
+       }
+
+       return -ENOENT;
+}
+
+int btrfs_del_inode_extref(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root,
                           const char *name, int name_len,
                           u64 inode_objectid, u64 ref_objectid, u64 *index)
+{
+       struct btrfs_path *path;
+       struct btrfs_key key;
+       struct btrfs_inode_extref *extref;
+       struct extent_buffer *leaf;
+       int ret;
+       int del_len = name_len + sizeof(*extref);
+       unsigned long ptr;
+       unsigned long item_start;
+       u32 item_size;
+
+       key.objectid = inode_objectid;
+       btrfs_set_key_type(&key, BTRFS_INODE_EXTREF_KEY);
+       key.offset = btrfs_extref_hash(ref_objectid, name, name_len);
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+
+       path->leave_spinning = 1;
+
+       ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
+       if (ret > 0)
+               ret = -ENOENT;
+       if (ret < 0)
+               goto out;
+
+       /*
+        * Sanity check - did we find the right item for this name?
+        * This should always succeed so error here will make the FS
+        * readonly.
+        */
+       if (!btrfs_find_name_in_ext_backref(path, ref_objectid,
+                                           name, name_len, &extref)) {
+               btrfs_std_error(root->fs_info, -ENOENT);
+               ret = -EROFS;
+               goto out;
+       }
+
+       leaf = path->nodes[0];
+       item_size = btrfs_item_size_nr(leaf, path->slots[0]);
+       if (index)
+               *index = btrfs_inode_extref_index(leaf, extref);
+
+       if (del_len == item_size) {
+               /*
+                * Common case only one ref in the item, remove the
+                * whole item.
+                */
+               ret = btrfs_del_item(trans, root, path);
+               goto out;
+       }
+
+       ptr = (unsigned long)extref;
+       item_start = btrfs_item_ptr_offset(leaf, path->slots[0]);
+
+       memmove_extent_buffer(leaf, ptr, ptr + del_len,
+                             item_size - (ptr + del_len - item_start));
+
+       btrfs_truncate_item(trans, root, path, item_size - del_len, 1);
+
+out:
+       btrfs_free_path(path);
+
+       return ret;
+}
+
+int btrfs_del_inode_ref(struct btrfs_trans_handle *trans,
+                       struct btrfs_root *root,
+                       const char *name, int name_len,
+                       u64 inode_objectid, u64 ref_objectid, u64 *index)
 {
        struct btrfs_path *path;
        struct btrfs_key key;
@@ -91,6 +268,7 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans,
        u32 item_size;
        u32 sub_item_len;
        int ret;
+       int search_ext_refs = 0;
        int del_len = name_len + sizeof(*ref);
 
        key.objectid = inode_objectid;
@@ -106,12 +284,14 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans,
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
        if (ret > 0) {
                ret = -ENOENT;
+               search_ext_refs = 1;
                goto out;
        } else if (ret < 0) {
                goto out;
        }
        if (!find_name_in_backref(path, name, name_len, &ref)) {
                ret = -ENOENT;
+               search_ext_refs = 1;
                goto out;
        }
        leaf = path->nodes[0];
@@ -129,8 +309,78 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans,
        item_start = btrfs_item_ptr_offset(leaf, path->slots[0]);
        memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
                              item_size - (ptr + sub_item_len - item_start));
-       btrfs_truncate_item(trans, root, path,
-                                 item_size - sub_item_len, 1);
+       btrfs_truncate_item(trans, root, path, item_size - sub_item_len, 1);
+out:
+       btrfs_free_path(path);
+
+       if (search_ext_refs) {
+               /*
+                * No refs were found, or we could not find the
+                * name in our ref array. Find and remove the extended
+                * inode ref then.
+                */
+               return btrfs_del_inode_extref(trans, root, name, name_len,
+                                             inode_objectid, ref_objectid, index);
+       }
+
+       return ret;
+}
+
+/*
+ * btrfs_insert_inode_extref() - Inserts an extended inode ref into a tree.
+ *
+ * The caller must have checked against BTRFS_LINK_MAX already.
+ */
+static int btrfs_insert_inode_extref(struct btrfs_trans_handle *trans,
+                                    struct btrfs_root *root,
+                                    const char *name, int name_len,
+                                    u64 inode_objectid, u64 ref_objectid, u64 index)
+{
+       struct btrfs_inode_extref *extref;
+       int ret;
+       int ins_len = name_len + sizeof(*extref);
+       unsigned long ptr;
+       struct btrfs_path *path;
+       struct btrfs_key key;
+       struct extent_buffer *leaf;
+       struct btrfs_item *item;
+
+       key.objectid = inode_objectid;
+       key.type = BTRFS_INODE_EXTREF_KEY;
+       key.offset = btrfs_extref_hash(ref_objectid, name, name_len);
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+
+       path->leave_spinning = 1;
+       ret = btrfs_insert_empty_item(trans, root, path, &key,
+                                     ins_len);
+       if (ret == -EEXIST) {
+               if (btrfs_find_name_in_ext_backref(path, ref_objectid,
+                                                  name, name_len, NULL))
+                       goto out;
+
+               btrfs_extend_item(trans, root, path, ins_len);
+               ret = 0;
+       }
+       if (ret < 0)
+               goto out;
+
+       leaf = path->nodes[0];
+       item = btrfs_item_nr(leaf, path->slots[0]);
+       ptr = (unsigned long)btrfs_item_ptr(leaf, path->slots[0], char);
+       ptr += btrfs_item_size(leaf, item) - ins_len;
+       extref = (struct btrfs_inode_extref *)ptr;
+
+       btrfs_set_inode_extref_name_len(path->nodes[0], extref, name_len);
+       btrfs_set_inode_extref_index(path->nodes[0], extref, index);
+       btrfs_set_inode_extref_parent(path->nodes[0], extref, ref_objectid);
+
+       ptr = (unsigned long)&extref->name;
+       write_extent_buffer(path->nodes[0], name, ptr, name_len);
+       btrfs_mark_buffer_dirty(path->nodes[0]);
+
 out:
        btrfs_free_path(path);
        return ret;
@@ -191,6 +441,19 @@ int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans,
 
 out:
        btrfs_free_path(path);
+
+       if (ret == -EMLINK) {
+               struct btrfs_super_block *disk_super = root->fs_info->super_copy;
+               /* We ran out of space in the ref array. Need to
+                * add an extended ref. */
+               if (btrfs_super_incompat_flags(disk_super)
+                   & BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF)
+                       ret = btrfs_insert_inode_extref(trans, root, name,
+                                                       name_len,
+                                                       inode_objectid,
+                                                       ref_objectid, index);
+       }
+
        return ret;
 }
 
index a6ed6944e50c42eb67a659c1eda6a5f17650d97e..85a1e5053fe63a9d8df6682da38198883e00bb22 100644 (file)
@@ -230,7 +230,6 @@ static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans,
        u64 inline_len = actual_end - start;
        u64 aligned_end = (end + root->sectorsize - 1) &
                        ~((u64)root->sectorsize - 1);
-       u64 hint_byte;
        u64 data_len = inline_len;
        int ret;
 
@@ -247,8 +246,7 @@ static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans,
                return 1;
        }
 
-       ret = btrfs_drop_extents(trans, inode, start, aligned_end,
-                                &hint_byte, 1);
+       ret = btrfs_drop_extents(trans, root, inode, start, aligned_end, 1);
        if (ret)
                return ret;
 
@@ -664,7 +662,7 @@ retry:
                                           async_extent->compressed_size,
                                           async_extent->compressed_size,
                                           0, alloc_hint, &ins, 1);
-                       if (ret)
+                       if (ret && ret != -ENOSPC)
                                btrfs_abort_transaction(trans, root, ret);
                        btrfs_end_transaction(trans, root);
                }
@@ -1308,6 +1306,7 @@ out_check:
                        em->block_start = disk_bytenr;
                        em->bdev = root->fs_info->fs_devices->latest_bdev;
                        set_bit(EXTENT_FLAG_PINNED, &em->flags);
+                       set_bit(EXTENT_FLAG_PREALLOC, &em->flags);
                        while (1) {
                                write_lock(&em_tree->lock);
                                ret = add_extent_mapping(em_tree, em);
@@ -1364,11 +1363,7 @@ out_check:
        }
 
 error:
-       if (nolock) {
-               err = btrfs_end_transaction_nolock(trans, root);
-       } else {
-               err = btrfs_end_transaction(trans, root);
-       }
+       err = btrfs_end_transaction(trans, root);
        if (!ret)
                ret = err;
 
@@ -1785,7 +1780,6 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
        struct btrfs_path *path;
        struct extent_buffer *leaf;
        struct btrfs_key ins;
-       u64 hint;
        int ret;
 
        path = btrfs_alloc_path();
@@ -1803,8 +1797,8 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
         * the caller is expected to unpin it and allow it to be merged
         * with the others.
         */
-       ret = btrfs_drop_extents(trans, inode, file_pos, file_pos + num_bytes,
-                                &hint, 0);
+       ret = btrfs_drop_extents(trans, root, inode, file_pos,
+                                file_pos + num_bytes, 0);
        if (ret)
                goto out;
 
@@ -1828,10 +1822,8 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
        btrfs_set_file_extent_encryption(leaf, fi, encryption);
        btrfs_set_file_extent_other_encoding(leaf, fi, other_encoding);
 
-       btrfs_unlock_up_safe(path, 1);
-       btrfs_set_lock_blocking(leaf);
-
        btrfs_mark_buffer_dirty(leaf);
+       btrfs_release_path(path);
 
        inode_add_bytes(inode, num_bytes);
 
@@ -1929,11 +1921,10 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
                                                ordered_extent->len,
                                                compress_type, 0, 0,
                                                BTRFS_FILE_EXTENT_REG);
-               unpin_extent_cache(&BTRFS_I(inode)->extent_tree,
-                                  ordered_extent->file_offset,
-                                  ordered_extent->len);
        }
-
+       unpin_extent_cache(&BTRFS_I(inode)->extent_tree,
+                          ordered_extent->file_offset, ordered_extent->len,
+                          trans->transid);
        if (ret < 0) {
                btrfs_abort_transaction(trans, root, ret);
                goto out_unlock;
@@ -1949,6 +1940,8 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
                        btrfs_abort_transaction(trans, root, ret);
                        goto out_unlock;
                }
+       } else {
+               btrfs_set_inode_last_trans(trans, inode);
        }
        ret = 0;
 out_unlock:
@@ -1958,12 +1951,8 @@ out_unlock:
 out:
        if (root != root->fs_info->tree_root)
                btrfs_delalloc_release_metadata(inode, ordered_extent->len);
-       if (trans) {
-               if (nolock)
-                       btrfs_end_transaction_nolock(trans, root);
-               else
-                       btrfs_end_transaction(trans, root);
-       }
+       if (trans)
+               btrfs_end_transaction(trans, root);
 
        if (ret)
                clear_extent_uptodate(io_tree, ordered_extent->file_offset,
@@ -2119,7 +2108,6 @@ void btrfs_run_delayed_iputs(struct btrfs_root *root)
        if (empty)
                return;
 
-       down_read(&root->fs_info->cleanup_work_sem);
        spin_lock(&fs_info->delayed_iput_lock);
        list_splice_init(&fs_info->delayed_iputs, &list);
        spin_unlock(&fs_info->delayed_iput_lock);
@@ -2130,7 +2118,6 @@ void btrfs_run_delayed_iputs(struct btrfs_root *root)
                iput(delayed->inode);
                kfree(delayed);
        }
-       up_read(&root->fs_info->cleanup_work_sem);
 }
 
 enum btrfs_orphan_cleanup_state {
@@ -2198,7 +2185,7 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode)
        int ret;
 
        if (!root->orphan_block_rsv) {
-               block_rsv = btrfs_alloc_block_rsv(root);
+               block_rsv = btrfs_alloc_block_rsv(root, BTRFS_BLOCK_RSV_TEMP);
                if (!block_rsv)
                        return -ENOMEM;
        }
@@ -2225,7 +2212,7 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode)
                        insert = 1;
 #endif
                insert = 1;
-               atomic_dec(&root->orphan_inodes);
+               atomic_inc(&root->orphan_inodes);
        }
 
        if (!test_and_set_bit(BTRFS_INODE_ORPHAN_META_RESERVED,
@@ -2590,6 +2577,18 @@ static void btrfs_read_locked_inode(struct inode *inode)
 
        inode_set_bytes(inode, btrfs_inode_nbytes(leaf, inode_item));
        BTRFS_I(inode)->generation = btrfs_inode_generation(leaf, inode_item);
+       BTRFS_I(inode)->last_trans = btrfs_inode_transid(leaf, inode_item);
+
+       /*
+        * If we were modified in the current generation and evicted from memory
+        * and then re-read we need to do a full sync since we don't have any
+        * idea about which extents were modified before we were evicted from
+        * cache.
+        */
+       if (BTRFS_I(inode)->last_trans == root->fs_info->generation)
+               set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
+                       &BTRFS_I(inode)->runtime_flags);
+
        inode->i_version = btrfs_inode_sequence(leaf, inode_item);
        inode->i_generation = BTRFS_I(inode)->generation;
        inode->i_rdev = 0;
@@ -2894,7 +2893,6 @@ static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir,
        struct btrfs_trans_handle *trans;
        struct btrfs_root *root = BTRFS_I(dir)->root;
        struct btrfs_path *path;
-       struct btrfs_inode_ref *ref;
        struct btrfs_dir_item *di;
        struct inode *inode = dentry->d_inode;
        u64 index;
@@ -3008,17 +3006,17 @@ static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir,
        }
        btrfs_release_path(path);
 
-       ref = btrfs_lookup_inode_ref(trans, root, path,
-                               dentry->d_name.name, dentry->d_name.len,
-                               ino, dir_ino, 0);
-       if (IS_ERR(ref)) {
-               err = PTR_ERR(ref);
+       ret = btrfs_get_inode_ref_index(trans, root, path, dentry->d_name.name,
+                                       dentry->d_name.len, ino, dir_ino, 0,
+                                       &index);
+       if (ret) {
+               err = ret;
                goto out;
        }
-       BUG_ON(!ref); /* Logic error */
+
        if (check_path_shared(root, path))
                goto out;
-       index = btrfs_inode_ref_index(path->nodes[0], ref);
+
        btrfs_release_path(path);
 
        /*
@@ -3061,7 +3059,7 @@ out:
 static void __unlink_end_trans(struct btrfs_trans_handle *trans,
                               struct btrfs_root *root)
 {
-       if (trans->block_rsv == &root->fs_info->global_block_rsv) {
+       if (trans->block_rsv->type == BTRFS_BLOCK_RSV_GLOBAL) {
                btrfs_block_rsv_release(root, trans->block_rsv,
                                        trans->bytes_reserved);
                trans->block_rsv = &root->fs_info->trans_block_rsv;
@@ -3191,9 +3189,10 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
        struct btrfs_trans_handle *trans;
        unsigned long nr = 0;
 
-       if (inode->i_size > BTRFS_EMPTY_DIR_SIZE ||
-           btrfs_ino(inode) == BTRFS_FIRST_FREE_OBJECTID)
+       if (inode->i_size > BTRFS_EMPTY_DIR_SIZE)
                return -ENOTEMPTY;
+       if (btrfs_ino(inode) == BTRFS_FIRST_FREE_OBJECTID)
+               return -EPERM;
 
        trans = __unlink_start_trans(dir, dentry);
        if (IS_ERR(trans))
@@ -3267,8 +3266,13 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
                return -ENOMEM;
        path->reada = -1;
 
+       /*
+        * We want to drop from the next block forward in case this new size is
+        * not block aligned since we will be keeping the last block of the
+        * extent just the way it is.
+        */
        if (root->ref_cows || root == root->fs_info->tree_root)
-               btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0);
+               btrfs_drop_extent_cache(inode, (new_size + mask) & (~mask), (u64)-1, 0);
 
        /*
         * This function is also used to drop the items in the log tree before
@@ -3429,12 +3433,6 @@ delete:
 
                if (path->slots[0] == 0 ||
                    path->slots[0] != pending_del_slot) {
-                       if (root->ref_cows &&
-                           BTRFS_I(inode)->location.objectid !=
-                                               BTRFS_FREE_INO_OBJECTID) {
-                               err = -EAGAIN;
-                               goto out;
-                       }
                        if (pending_del_nr) {
                                ret = btrfs_del_items(trans, root, path,
                                                pending_del_slot,
@@ -3465,12 +3463,20 @@ error:
 }
 
 /*
- * taken from block_truncate_page, but does cow as it zeros out
- * any bytes left in the last page in the file.
+ * btrfs_truncate_page - read, zero a chunk and write a page
+ * @inode - inode that we're zeroing
+ * @from - the offset to start zeroing
+ * @len - the length to zero, 0 to zero the entire range respective to the
+ *     offset
+ * @front - zero up to the offset instead of from the offset on
+ *
+ * This will find the page for the "from" offset and cow the page and zero the
+ * part we want to zero.  This is used with truncate and hole punching.
  */
-static int btrfs_truncate_page(struct address_space *mapping, loff_t from)
+int btrfs_truncate_page(struct inode *inode, loff_t from, loff_t len,
+                       int front)
 {
-       struct inode *inode = mapping->host;
+       struct address_space *mapping = inode->i_mapping;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
        struct btrfs_ordered_extent *ordered;
@@ -3485,7 +3491,8 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from)
        u64 page_start;
        u64 page_end;
 
-       if ((offset & (blocksize - 1)) == 0)
+       if ((offset & (blocksize - 1)) == 0 &&
+           (!len || ((len & (blocksize - 1)) == 0)))
                goto out;
        ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE);
        if (ret)
@@ -3532,7 +3539,8 @@ again:
        }
 
        clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start, page_end,
-                         EXTENT_DIRTY | EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING,
+                         EXTENT_DIRTY | EXTENT_DELALLOC |
+                         EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
                          0, 0, &cached_state, GFP_NOFS);
 
        ret = btrfs_set_extent_delalloc(inode, page_start, page_end,
@@ -3545,8 +3553,13 @@ again:
 
        ret = 0;
        if (offset != PAGE_CACHE_SIZE) {
+               if (!len)
+                       len = PAGE_CACHE_SIZE - offset;
                kaddr = kmap(page);
-               memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
+               if (front)
+                       memset(kaddr, 0, offset);
+               else
+                       memset(kaddr + offset, 0, len);
                flush_dcache_page(page);
                kunmap(page);
        }
@@ -3577,6 +3590,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
        struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
        struct extent_map *em = NULL;
        struct extent_state *cached_state = NULL;
+       struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
        u64 mask = root->sectorsize - 1;
        u64 hole_start = (oldsize + mask) & ~mask;
        u64 block_end = (size + mask) & ~mask;
@@ -3613,7 +3627,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
                last_byte = min(extent_map_end(em), block_end);
                last_byte = (last_byte + mask) & ~mask;
                if (!test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) {
-                       u64 hint_byte = 0;
+                       struct extent_map *hole_em;
                        hole_size = last_byte - cur_offset;
 
                        trans = btrfs_start_transaction(root, 3);
@@ -3622,9 +3636,9 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
                                break;
                        }
 
-                       err = btrfs_drop_extents(trans, inode, cur_offset,
-                                                cur_offset + hole_size,
-                                                &hint_byte, 1);
+                       err = btrfs_drop_extents(trans, root, inode,
+                                                cur_offset,
+                                                cur_offset + hole_size, 1);
                        if (err) {
                                btrfs_abort_transaction(trans, root, err);
                                btrfs_end_transaction(trans, root);
@@ -3641,9 +3655,39 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
                                break;
                        }
 
-                       btrfs_drop_extent_cache(inode, hole_start,
-                                       last_byte - 1, 0);
+                       btrfs_drop_extent_cache(inode, cur_offset,
+                                               cur_offset + hole_size - 1, 0);
+                       hole_em = alloc_extent_map();
+                       if (!hole_em) {
+                               set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
+                                       &BTRFS_I(inode)->runtime_flags);
+                               goto next;
+                       }
+                       hole_em->start = cur_offset;
+                       hole_em->len = hole_size;
+                       hole_em->orig_start = cur_offset;
 
+                       hole_em->block_start = EXTENT_MAP_HOLE;
+                       hole_em->block_len = 0;
+                       hole_em->bdev = root->fs_info->fs_devices->latest_bdev;
+                       hole_em->compress_type = BTRFS_COMPRESS_NONE;
+                       hole_em->generation = trans->transid;
+
+                       while (1) {
+                               write_lock(&em_tree->lock);
+                               err = add_extent_mapping(em_tree, hole_em);
+                               if (!err)
+                                       list_move(&hole_em->list,
+                                                 &em_tree->modified_extents);
+                               write_unlock(&em_tree->lock);
+                               if (err != -EEXIST)
+                                       break;
+                               btrfs_drop_extent_cache(inode, cur_offset,
+                                                       cur_offset +
+                                                       hole_size - 1, 0);
+                       }
+                       free_extent_map(hole_em);
+next:
                        btrfs_update_inode(trans, root, inode);
                        btrfs_end_transaction(trans, root);
                }
@@ -3768,26 +3812,22 @@ void btrfs_evict_inode(struct inode *inode)
                goto no_delete;
        }
 
-       rsv = btrfs_alloc_block_rsv(root);
+       rsv = btrfs_alloc_block_rsv(root, BTRFS_BLOCK_RSV_TEMP);
        if (!rsv) {
                btrfs_orphan_del(NULL, inode);
                goto no_delete;
        }
        rsv->size = min_size;
+       rsv->failfast = 1;
        global_rsv = &root->fs_info->global_block_rsv;
 
        btrfs_i_size_write(inode, 0);
 
        /*
-        * This is a bit simpler than btrfs_truncate since
-        *
-        * 1) We've already reserved our space for our orphan item in the
-        *    unlink.
-        * 2) We're going to delete the inode item, so we don't need to update
-        *    it at all.
-        *
-        * So we just need to reserve some slack space in case we add bytes when
-        * doing the truncate.
+        * This is a bit simpler than btrfs_truncate since we've already
+        * reserved our space for our orphan item in the unlink, so we just
+        * need to reserve some slack space in case we add bytes and update
+        * inode item when doing the truncate.
         */
        while (1) {
                ret = btrfs_block_rsv_refill_noflush(root, rsv, min_size);
@@ -3808,7 +3848,7 @@ void btrfs_evict_inode(struct inode *inode)
                        goto no_delete;
                }
 
-               trans = btrfs_start_transaction(root, 0);
+               trans = btrfs_start_transaction_noflush(root, 1);
                if (IS_ERR(trans)) {
                        btrfs_orphan_del(NULL, inode);
                        btrfs_free_block_rsv(root, rsv);
@@ -3818,9 +3858,13 @@ void btrfs_evict_inode(struct inode *inode)
                trans->block_rsv = rsv;
 
                ret = btrfs_truncate_inode_items(trans, root, inode, 0, 0);
-               if (ret != -EAGAIN)
+               if (ret != -ENOSPC)
                        break;
 
+               trans->block_rsv = &root->fs_info->trans_block_rsv;
+               ret = btrfs_update_inode(trans, root, inode);
+               BUG_ON(ret);
+
                nr = trans->blocks_used;
                btrfs_end_transaction(trans, root);
                trans = NULL;
@@ -4470,10 +4514,7 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc)
                        trans = btrfs_join_transaction(root);
                if (IS_ERR(trans))
                        return PTR_ERR(trans);
-               if (nolock)
-                       ret = btrfs_end_transaction_nolock(trans, root);
-               else
-                       ret = btrfs_commit_transaction(trans, root);
+               ret = btrfs_commit_transaction(trans, root);
        }
        return ret;
 }
@@ -4671,6 +4712,14 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
        BTRFS_I(inode)->generation = trans->transid;
        inode->i_generation = BTRFS_I(inode)->generation;
 
+       /*
+        * We could have gotten an inode number from somebody who was fsynced
+        * and then removed in this same transaction, so let's just set full
+        * sync since it will be a full sync anyway and this will blow away the
+        * old info in the log.
+        */
+       set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &BTRFS_I(inode)->runtime_flags);
+
        if (S_ISDIR(mode))
                owner = 0;
        else
@@ -4680,6 +4729,12 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
        btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY);
        key[0].offset = 0;
 
+       /*
+        * Start new inodes with an inode_ref. This is slightly more
+        * efficient for small numbers of hard links since they will
+        * be packed into one item. Extended refs will kick in if we
+        * add more hard links than can fit in the ref item.
+        */
        key[1].objectid = objectid;
        btrfs_set_key_type(&key[1], BTRFS_INODE_REF_KEY);
        key[1].offset = ref_objectid;
@@ -4986,7 +5041,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
        if (root->objectid != BTRFS_I(inode)->root->objectid)
                return -EXDEV;
 
-       if (inode->i_nlink == ~0U)
+       if (inode->i_nlink >= BTRFS_LINK_MAX)
                return -EMLINK;
 
        err = btrfs_set_inode_index(dir, &index);
@@ -5450,7 +5505,8 @@ insert:
        write_unlock(&em_tree->lock);
 out:
 
-       trace_btrfs_get_extent(root, em);
+       if (em)
+               trace_btrfs_get_extent(root, em);
 
        if (path)
                btrfs_free_path(path);
@@ -5836,6 +5892,48 @@ static int lock_extent_direct(struct inode *inode, u64 lockstart, u64 lockend,
        return ret;
 }
 
+static struct extent_map *create_pinned_em(struct inode *inode, u64 start,
+                                          u64 len, u64 orig_start,
+                                          u64 block_start, u64 block_len,
+                                          int type)
+{
+       struct extent_map_tree *em_tree;
+       struct extent_map *em;
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       int ret;
+
+       em_tree = &BTRFS_I(inode)->extent_tree;
+       em = alloc_extent_map();
+       if (!em)
+               return ERR_PTR(-ENOMEM);
+
+       em->start = start;
+       em->orig_start = orig_start;
+       em->len = len;
+       em->block_len = block_len;
+       em->block_start = block_start;
+       em->bdev = root->fs_info->fs_devices->latest_bdev;
+       set_bit(EXTENT_FLAG_PINNED, &em->flags);
+       if (type == BTRFS_ORDERED_PREALLOC)
+               set_bit(EXTENT_FLAG_PREALLOC, &em->flags);
+
+       do {
+               btrfs_drop_extent_cache(inode, em->start,
+                               em->start + em->len - 1, 0);
+               write_lock(&em_tree->lock);
+               ret = add_extent_mapping(em_tree, em);
+               write_unlock(&em_tree->lock);
+       } while (ret == -EEXIST);
+
+       if (ret) {
+               free_extent_map(em);
+               return ERR_PTR(ret);
+       }
+
+       return em;
+}
+
+
 static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
                                   struct buffer_head *bh_result, int create)
 {
@@ -5950,6 +6048,19 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
                        goto must_cow;
 
                if (can_nocow_odirect(trans, inode, start, len) == 1) {
+                       u64 orig_start = em->start;
+
+                       if (type == BTRFS_ORDERED_PREALLOC) {
+                               free_extent_map(em);
+                               em = create_pinned_em(inode, start, len,
+                                                      orig_start,
+                                                      block_start, len, type);
+                               if (IS_ERR(em)) {
+                                       btrfs_end_transaction(trans, root);
+                                       goto unlock_err;
+                               }
+                       }
+
                        ret = btrfs_add_ordered_extent_dio(inode, start,
                                           block_start, len, len, type);
                        btrfs_end_transaction(trans, root);
@@ -5999,7 +6110,8 @@ unlock:
        if (lockstart < lockend) {
                if (create && len < lockend - lockstart) {
                        clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
-                                        lockstart + len - 1, unlock_bits, 1, 0,
+                                        lockstart + len - 1,
+                                        unlock_bits | EXTENT_DEFRAG, 1, 0,
                                         &cached_state, GFP_NOFS);
                        /*
                         * Beside unlock, we also need to cleanup reserved space
@@ -6007,8 +6119,8 @@ unlock:
                         */
                        clear_extent_bit(&BTRFS_I(inode)->io_tree,
                                         lockstart + len, lockend,
-                                        unlock_bits | EXTENT_DO_ACCOUNTING,
-                                        1, 0, NULL, GFP_NOFS);
+                                        unlock_bits | EXTENT_DO_ACCOUNTING |
+                                        EXTENT_DEFRAG, 1, 0, NULL, GFP_NOFS);
                } else {
                        clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
                                         lockend, unlock_bits, 1, 0,
@@ -6573,8 +6685,8 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset)
                 */
                clear_extent_bit(tree, page_start, page_end,
                                 EXTENT_DIRTY | EXTENT_DELALLOC |
-                                EXTENT_LOCKED | EXTENT_DO_ACCOUNTING, 1, 0,
-                                &cached_state, GFP_NOFS);
+                                EXTENT_LOCKED | EXTENT_DO_ACCOUNTING |
+                                EXTENT_DEFRAG, 1, 0, &cached_state, GFP_NOFS);
                /*
                 * whoever cleared the private bit is responsible
                 * for the finish_ordered_io
@@ -6590,7 +6702,8 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset)
        }
        clear_extent_bit(tree, page_start, page_end,
                 EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC |
-                EXTENT_DO_ACCOUNTING, 1, 1, &cached_state, GFP_NOFS);
+                EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 1, 1,
+                &cached_state, GFP_NOFS);
        __btrfs_releasepage(page, GFP_NOFS);
 
        ClearPageChecked(page);
@@ -6687,7 +6800,8 @@ again:
         * prepare_pages in the normal write path.
         */
        clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start, page_end,
-                         EXTENT_DIRTY | EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING,
+                         EXTENT_DIRTY | EXTENT_DELALLOC |
+                         EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
                          0, 0, &cached_state, GFP_NOFS);
 
        ret = btrfs_set_extent_delalloc(inode, page_start, page_end,
@@ -6718,6 +6832,7 @@ again:
 
        BTRFS_I(inode)->last_trans = root->fs_info->generation;
        BTRFS_I(inode)->last_sub_trans = BTRFS_I(inode)->root->log_transid;
+       BTRFS_I(inode)->last_log_commit = BTRFS_I(inode)->root->last_log_commit;
 
        unlock_extent_cached(io_tree, page_start, page_end, &cached_state, GFP_NOFS);
 
@@ -6745,7 +6860,7 @@ static int btrfs_truncate(struct inode *inode)
        u64 mask = root->sectorsize - 1;
        u64 min_size = btrfs_calc_trunc_metadata_size(root, 1);
 
-       ret = btrfs_truncate_page(inode->i_mapping, inode->i_size);
+       ret = btrfs_truncate_page(inode, inode->i_size, 0, 0);
        if (ret)
                return ret;
 
@@ -6788,10 +6903,11 @@ static int btrfs_truncate(struct inode *inode)
         * 3) fs_info->trans_block_rsv - this will have 1 items worth left for
         * updating the inode.
         */
-       rsv = btrfs_alloc_block_rsv(root);
+       rsv = btrfs_alloc_block_rsv(root, BTRFS_BLOCK_RSV_TEMP);
        if (!rsv)
                return -ENOMEM;
        rsv->size = min_size;
+       rsv->failfast = 1;
 
        /*
         * 1 for the truncate slack space
@@ -6837,36 +6953,21 @@ static int btrfs_truncate(struct inode *inode)
                                           &BTRFS_I(inode)->runtime_flags))
                btrfs_add_ordered_operation(trans, root, inode);
 
-       while (1) {
-               ret = btrfs_block_rsv_refill(root, rsv, min_size);
-               if (ret) {
-                       /*
-                        * This can only happen with the original transaction we
-                        * started above, every other time we shouldn't have a
-                        * transaction started yet.
-                        */
-                       if (ret == -EAGAIN)
-                               goto end_trans;
-                       err = ret;
-                       break;
-               }
-
-               if (!trans) {
-                       /* Just need the 1 for updating the inode */
-                       trans = btrfs_start_transaction(root, 1);
-                       if (IS_ERR(trans)) {
-                               ret = err = PTR_ERR(trans);
-                               trans = NULL;
-                               break;
-                       }
-               }
-
-               trans->block_rsv = rsv;
+       /*
+        * So if we truncate and then write and fsync we normally would just
+        * write the extents that changed, which is a problem if we need to
+        * first truncate that entire inode.  So set this flag so we write out
+        * all of the extents in the inode to the sync log so we're completely
+        * safe.
+        */
+       set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &BTRFS_I(inode)->runtime_flags);
+       trans->block_rsv = rsv;
 
+       while (1) {
                ret = btrfs_truncate_inode_items(trans, root, inode,
                                                 inode->i_size,
                                                 BTRFS_EXTENT_DATA_KEY);
-               if (ret != -EAGAIN) {
+               if (ret != -ENOSPC) {
                        err = ret;
                        break;
                }
@@ -6877,11 +6978,22 @@ static int btrfs_truncate(struct inode *inode)
                        err = ret;
                        break;
                }
-end_trans:
+
                nr = trans->blocks_used;
                btrfs_end_transaction(trans, root);
-               trans = NULL;
                btrfs_btree_balance_dirty(root, nr);
+
+               trans = btrfs_start_transaction(root, 2);
+               if (IS_ERR(trans)) {
+                       ret = err = PTR_ERR(trans);
+                       trans = NULL;
+                       break;
+               }
+
+               ret = btrfs_block_rsv_migrate(&root->fs_info->trans_block_rsv,
+                                             rsv, min_size);
+               BUG_ON(ret);    /* shouldn't happen */
+               trans->block_rsv = rsv;
        }
 
        if (ret == 0 && inode->i_nlink > 0) {
@@ -6965,6 +7077,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
        ei->csum_bytes = 0;
        ei->index_cnt = (u64)-1;
        ei->last_unlink_trans = 0;
+       ei->last_log_commit = 0;
 
        spin_lock_init(&ei->lock);
        ei->outstanding_extents = 0;
@@ -7095,31 +7208,31 @@ void btrfs_destroy_cachep(void)
 
 int btrfs_init_cachep(void)
 {
-       btrfs_inode_cachep = kmem_cache_create("btrfs_inode_cache",
+       btrfs_inode_cachep = kmem_cache_create("btrfs_inode",
                        sizeof(struct btrfs_inode), 0,
                        SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, init_once);
        if (!btrfs_inode_cachep)
                goto fail;
 
-       btrfs_trans_handle_cachep = kmem_cache_create("btrfs_trans_handle_cache",
+       btrfs_trans_handle_cachep = kmem_cache_create("btrfs_trans_handle",
                        sizeof(struct btrfs_trans_handle), 0,
                        SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
        if (!btrfs_trans_handle_cachep)
                goto fail;
 
-       btrfs_transaction_cachep = kmem_cache_create("btrfs_transaction_cache",
+       btrfs_transaction_cachep = kmem_cache_create("btrfs_transaction",
                        sizeof(struct btrfs_transaction), 0,
                        SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
        if (!btrfs_transaction_cachep)
                goto fail;
 
-       btrfs_path_cachep = kmem_cache_create("btrfs_path_cache",
+       btrfs_path_cachep = kmem_cache_create("btrfs_path",
                        sizeof(struct btrfs_path), 0,
                        SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
        if (!btrfs_path_cachep)
                goto fail;
 
-       btrfs_free_space_cachep = kmem_cache_create("btrfs_free_space_cache",
+       btrfs_free_space_cachep = kmem_cache_create("btrfs_free_space",
                        sizeof(struct btrfs_free_space), 0,
                        SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
        if (!btrfs_free_space_cachep)
@@ -7513,6 +7626,8 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
                                       loff_t actual_len, u64 *alloc_hint,
                                       struct btrfs_trans_handle *trans)
 {
+       struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
+       struct extent_map *em;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_key ins;
        u64 cur_offset = start;
@@ -7553,6 +7668,37 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
                btrfs_drop_extent_cache(inode, cur_offset,
                                        cur_offset + ins.offset -1, 0);
 
+               em = alloc_extent_map();
+               if (!em) {
+                       set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
+                               &BTRFS_I(inode)->runtime_flags);
+                       goto next;
+               }
+
+               em->start = cur_offset;
+               em->orig_start = cur_offset;
+               em->len = ins.offset;
+               em->block_start = ins.objectid;
+               em->block_len = ins.offset;
+               em->bdev = root->fs_info->fs_devices->latest_bdev;
+               set_bit(EXTENT_FLAG_PREALLOC, &em->flags);
+               em->generation = trans->transid;
+
+               while (1) {
+                       write_lock(&em_tree->lock);
+                       ret = add_extent_mapping(em_tree, em);
+                       if (!ret)
+                               list_move(&em->list,
+                                         &em_tree->modified_extents);
+                       write_unlock(&em_tree->lock);
+                       if (ret != -EEXIST)
+                               break;
+                       btrfs_drop_extent_cache(inode, cur_offset,
+                                               cur_offset + ins.offset - 1,
+                                               0);
+               }
+               free_extent_map(em);
+next:
                num_bytes -= ins.offset;
                cur_offset += ins.offset;
                *alloc_hint = ins.objectid + ins.offset;
index 47127c1bd290b5eb91023e8877176dbf3cfb7e58..61168805f175b3c50ffef99b87e97fdeb2643ebd 100644 (file)
@@ -181,6 +181,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
        int ret;
        u64 ip_oldflags;
        unsigned int i_oldflags;
+       umode_t mode;
 
        if (btrfs_root_readonly(root))
                return -EROFS;
@@ -203,6 +204,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
 
        ip_oldflags = ip->flags;
        i_oldflags = inode->i_flags;
+       mode = inode->i_mode;
 
        flags = btrfs_mask_flags(inode->i_mode, flags);
        oldflags = btrfs_flags_to_ioctl(ip->flags);
@@ -237,10 +239,31 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
                ip->flags |= BTRFS_INODE_DIRSYNC;
        else
                ip->flags &= ~BTRFS_INODE_DIRSYNC;
-       if (flags & FS_NOCOW_FL)
-               ip->flags |= BTRFS_INODE_NODATACOW;
-       else
-               ip->flags &= ~BTRFS_INODE_NODATACOW;
+       if (flags & FS_NOCOW_FL) {
+               if (S_ISREG(mode)) {
+                       /*
+                        * It's safe to turn csums off here, no extents exist.
+                        * Otherwise we want the flag to reflect the real COW
+                        * status of the file and will not set it.
+                        */
+                       if (inode->i_size == 0)
+                               ip->flags |= BTRFS_INODE_NODATACOW
+                                          | BTRFS_INODE_NODATASUM;
+               } else {
+                       ip->flags |= BTRFS_INODE_NODATACOW;
+               }
+       } else {
+               /*
+                * Revert back under same assuptions as above
+                */
+               if (S_ISREG(mode)) {
+                       if (inode->i_size == 0)
+                               ip->flags &= ~(BTRFS_INODE_NODATACOW
+                                            | BTRFS_INODE_NODATASUM);
+               } else {
+                       ip->flags &= ~BTRFS_INODE_NODATACOW;
+               }
+       }
 
        /*
         * The COMPRESS flag can only be changed by users, while the NOCOMPRESS
@@ -516,7 +539,8 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
        if (!pending_snapshot)
                return -ENOMEM;
 
-       btrfs_init_block_rsv(&pending_snapshot->block_rsv);
+       btrfs_init_block_rsv(&pending_snapshot->block_rsv,
+                            BTRFS_BLOCK_RSV_TEMP);
        pending_snapshot->dentry = dentry;
        pending_snapshot->root = root;
        pending_snapshot->readonly = readonly;
@@ -525,7 +549,7 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
                *inherit = NULL;        /* take responsibility to free it */
        }
 
-       trans = btrfs_start_transaction(root->fs_info->extent_root, 5);
+       trans = btrfs_start_transaction(root->fs_info->extent_root, 6);
        if (IS_ERR(trans)) {
                ret = PTR_ERR(trans);
                goto fail;
@@ -614,7 +638,7 @@ static int btrfs_may_delete(struct inode *dir,struct dentry *victim,int isdir)
                return -ENOENT;
 
        BUG_ON(victim->d_parent->d_inode != dir);
-       audit_inode_child(victim, dir);
+       audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
 
        error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
        if (error)
@@ -1022,8 +1046,8 @@ again:
                         page_start, page_end - 1, 0, &cached_state);
        clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start,
                          page_end - 1, EXTENT_DIRTY | EXTENT_DELALLOC |
-                         EXTENT_DO_ACCOUNTING, 0, 0, &cached_state,
-                         GFP_NOFS);
+                         EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 0, 0,
+                         &cached_state, GFP_NOFS);
 
        if (i_done != page_cnt) {
                spin_lock(&BTRFS_I(inode)->lock);
@@ -1034,8 +1058,8 @@ again:
        }
 
 
-       btrfs_set_extent_delalloc(inode, page_start, page_end - 1,
-                                 &cached_state);
+       set_extent_defrag(&BTRFS_I(inode)->io_tree, page_start, page_end - 1,
+                         &cached_state, GFP_NOFS);
 
        unlock_extent_cached(&BTRFS_I(inode)->io_tree,
                             page_start, page_end - 1, &cached_state,
@@ -2351,7 +2375,6 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
        int ret;
        u64 len = olen;
        u64 bs = root->fs_info->sb->s_blocksize;
-       u64 hint_byte;
 
        /*
         * TODO:
@@ -2456,13 +2479,13 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
           another, and lock file content */
        while (1) {
                struct btrfs_ordered_extent *ordered;
-               lock_extent(&BTRFS_I(src)->io_tree, off, off+len);
-               ordered = btrfs_lookup_first_ordered_extent(src, off+len);
+               lock_extent(&BTRFS_I(src)->io_tree, off, off + len - 1);
+               ordered = btrfs_lookup_first_ordered_extent(src, off + len - 1);
                if (!ordered &&
-                   !test_range_bit(&BTRFS_I(src)->io_tree, off, off+len,
-                                  EXTENT_DELALLOC, 0, NULL))
+                   !test_range_bit(&BTRFS_I(src)->io_tree, off, off + len - 1,
+                                   EXTENT_DELALLOC, 0, NULL))
                        break;
-               unlock_extent(&BTRFS_I(src)->io_tree, off, off+len);
+               unlock_extent(&BTRFS_I(src)->io_tree, off, off + len - 1);
                if (ordered)
                        btrfs_put_ordered_extent(ordered);
                btrfs_wait_ordered_range(src, off, len);
@@ -2536,7 +2559,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                        btrfs_release_path(path);
 
                        if (key.offset + datal <= off ||
-                           key.offset >= off+len)
+                           key.offset >= off + len - 1)
                                goto next;
 
                        memcpy(&new_key, &key, sizeof(new_key));
@@ -2574,10 +2597,10 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                                        datal -= off - key.offset;
                                }
 
-                               ret = btrfs_drop_extents(trans, inode,
+                               ret = btrfs_drop_extents(trans, root, inode,
                                                         new_key.offset,
                                                         new_key.offset + datal,
-                                                        &hint_byte, 1);
+                                                        1);
                                if (ret) {
                                        btrfs_abort_transaction(trans, root,
                                                                ret);
@@ -2637,8 +2660,8 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                                        new_key.offset += skip;
                                }
 
-                               if (key.offset + datal > off+len)
-                                       trim = key.offset + datal - (off+len);
+                               if (key.offset + datal > off + len)
+                                       trim = key.offset + datal - (off + len);
 
                                if (comp && (skip || trim)) {
                                        ret = -EINVAL;
@@ -2648,10 +2671,10 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                                size -= skip + trim;
                                datal -= skip + trim;
 
-                               ret = btrfs_drop_extents(trans, inode,
+                               ret = btrfs_drop_extents(trans, root, inode,
                                                         new_key.offset,
                                                         new_key.offset + datal,
-                                                        &hint_byte, 1);
+                                                        1);
                                if (ret) {
                                        btrfs_abort_transaction(trans, root,
                                                                ret);
@@ -2715,7 +2738,7 @@ next:
        ret = 0;
 out:
        btrfs_release_path(path);
-       unlock_extent(&BTRFS_I(src)->io_tree, off, off+len);
+       unlock_extent(&BTRFS_I(src)->io_tree, off, off + len - 1);
 out_unlock:
        mutex_unlock(&src->i_mutex);
        mutex_unlock(&inode->i_mutex);
@@ -2850,8 +2873,8 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
        return 0;
 }
 
-static void get_block_group_info(struct list_head *groups_list,
-                                struct btrfs_ioctl_space_info *space)
+void btrfs_get_block_group_info(struct list_head *groups_list,
+                               struct btrfs_ioctl_space_info *space)
 {
        struct btrfs_block_group_cache *block_group;
 
@@ -2959,8 +2982,8 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg)
                down_read(&info->groups_sem);
                for (c = 0; c < BTRFS_NR_RAID_TYPES; c++) {
                        if (!list_empty(&info->block_groups[c])) {
-                               get_block_group_info(&info->block_groups[c],
-                                                    &space);
+                               btrfs_get_block_group_info(
+                                       &info->block_groups[c], &space);
                                memcpy(dest, &space, sizeof(space));
                                dest++;
                                space_args.total_spaces++;
@@ -3208,11 +3231,9 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
 {
        int ret = 0;
        int size;
-       u64 extent_item_pos;
        struct btrfs_ioctl_logical_ino_args *loi;
        struct btrfs_data_container *inodes = NULL;
        struct btrfs_path *path = NULL;
-       struct btrfs_key key;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -3230,7 +3251,7 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
                goto out;
        }
 
-       size = min_t(u32, loi->size, 4096);
+       size = min_t(u32, loi->size, 64 * 1024);
        inodes = init_data_container(size);
        if (IS_ERR(inodes)) {
                ret = PTR_ERR(inodes);
@@ -3238,22 +3259,13 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
                goto out;
        }
 
-       ret = extent_from_logical(root->fs_info, loi->logical, path, &key);
-       btrfs_release_path(path);
-
-       if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK)
+       ret = iterate_inodes_from_logical(loi->logical, root->fs_info, path,
+                                         build_ino_list, inodes);
+       if (ret == -EINVAL)
                ret = -ENOENT;
        if (ret < 0)
                goto out;
 
-       extent_item_pos = loi->logical - key.objectid;
-       ret = iterate_extent_inodes(root->fs_info, key.objectid,
-                                       extent_item_pos, 0, build_ino_list,
-                                       inodes);
-
-       if (ret < 0)
-               goto out;
-
        ret = copy_to_user((void *)(unsigned long)loi->inodes,
                           (void *)(unsigned long)inodes, size);
        if (ret)
@@ -3261,7 +3273,7 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
 
 out:
        btrfs_free_path(path);
-       kfree(inodes);
+       vfree(inodes);
        kfree(loi);
 
        return ret;
index 051c7fe551dd38bb7e391e5abaeff992f32b90f7..7772f02ba28e6966826c0d897475961ad628c2f5 100644 (file)
@@ -25,6 +25,8 @@
 #include "btrfs_inode.h"
 #include "extent_io.h"
 
+static struct kmem_cache *btrfs_ordered_extent_cache;
+
 static u64 entry_end(struct btrfs_ordered_extent *entry)
 {
        if (entry->file_offset + entry->len < entry->file_offset)
@@ -187,7 +189,7 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
        struct btrfs_ordered_extent *entry;
 
        tree = &BTRFS_I(inode)->ordered_tree;
-       entry = kzalloc(sizeof(*entry), GFP_NOFS);
+       entry = kmem_cache_zalloc(btrfs_ordered_extent_cache, GFP_NOFS);
        if (!entry)
                return -ENOMEM;
 
@@ -421,7 +423,7 @@ void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry)
                        list_del(&sum->list);
                        kfree(sum);
                }
-               kfree(entry);
+               kmem_cache_free(btrfs_ordered_extent_cache, entry);
        }
 }
 
@@ -466,8 +468,7 @@ void btrfs_remove_ordered_extent(struct inode *inode,
  * wait for all the ordered extents in a root.  This is done when balancing
  * space between drives.
  */
-void btrfs_wait_ordered_extents(struct btrfs_root *root,
-                               int nocow_only, int delay_iput)
+void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput)
 {
        struct list_head splice;
        struct list_head *cur;
@@ -482,15 +483,6 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root,
                cur = splice.next;
                ordered = list_entry(cur, struct btrfs_ordered_extent,
                                     root_extent_list);
-               if (nocow_only &&
-                   !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags) &&
-                   !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags)) {
-                       list_move(&ordered->root_extent_list,
-                                 &root->fs_info->ordered_extents);
-                       cond_resched_lock(&root->fs_info->ordered_extent_lock);
-                       continue;
-               }
-
                list_del_init(&ordered->root_extent_list);
                atomic_inc(&ordered->refs);
 
@@ -775,7 +767,6 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
        struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree;
        u64 disk_i_size;
        u64 new_i_size;
-       u64 i_size_test;
        u64 i_size = i_size_read(inode);
        struct rb_node *node;
        struct rb_node *prev = NULL;
@@ -835,55 +826,30 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
                        break;
                if (test->file_offset >= i_size)
                        break;
-               if (test->file_offset >= disk_i_size)
+               if (test->file_offset >= disk_i_size) {
+                       /*
+                        * we don't update disk_i_size now, so record this
+                        * undealt i_size. Or we will not know the real
+                        * i_size.
+                        */
+                       if (test->outstanding_isize < offset)
+                               test->outstanding_isize = offset;
+                       if (ordered &&
+                           ordered->outstanding_isize >
+                           test->outstanding_isize)
+                               test->outstanding_isize =
+                                               ordered->outstanding_isize;
                        goto out;
-       }
-       new_i_size = min_t(u64, offset, i_size);
-
-       /*
-        * at this point, we know we can safely update i_size to at least
-        * the offset from this ordered extent.  But, we need to
-        * walk forward and see if ios from higher up in the file have
-        * finished.
-        */
-       if (ordered) {
-               node = rb_next(&ordered->rb_node);
-       } else {
-               if (prev)
-                       node = rb_next(prev);
-               else
-                       node = rb_first(&tree->tree);
-       }
-
-       /*
-        * We are looking for an area between our current extent and the next
-        * ordered extent to update the i_size to.  There are 3 cases here
-        *
-        * 1) We don't actually have anything and we can update to i_size.
-        * 2) We have stuff but they already did their i_size update so again we
-        * can just update to i_size.
-        * 3) We have an outstanding ordered extent so the most we can update
-        * our disk_i_size to is the start of the next offset.
-        */
-       i_size_test = i_size;
-       for (; node; node = rb_next(node)) {
-               test = rb_entry(node, struct btrfs_ordered_extent, rb_node);
-
-               if (test_bit(BTRFS_ORDERED_UPDATED_ISIZE, &test->flags))
-                       continue;
-               if (test->file_offset > offset) {
-                       i_size_test = test->file_offset;
-                       break;
                }
        }
+       new_i_size = min_t(u64, offset, i_size);
 
        /*
-        * i_size_test is the end of a region after this ordered
-        * extent where there are no ordered extents, we can safely set
-        * disk_i_size to this.
+        * Some ordered extents may completed before the current one, and
+        * we hold the real i_size in ->outstanding_isize.
         */
-       if (i_size_test > offset)
-               new_i_size = min_t(u64, i_size_test, i_size);
+       if (ordered && ordered->outstanding_isize > new_i_size)
+               new_i_size = min_t(u64, ordered->outstanding_isize, i_size);
        BTRFS_I(inode)->disk_i_size = new_i_size;
        ret = 0;
 out:
@@ -984,3 +950,20 @@ void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans,
        }
        spin_unlock(&root->fs_info->ordered_extent_lock);
 }
+
+int __init ordered_data_init(void)
+{
+       btrfs_ordered_extent_cache = kmem_cache_create("btrfs_ordered_extent",
+                                    sizeof(struct btrfs_ordered_extent), 0,
+                                    SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
+                                    NULL);
+       if (!btrfs_ordered_extent_cache)
+               return -ENOMEM;
+       return 0;
+}
+
+void ordered_data_exit(void)
+{
+       if (btrfs_ordered_extent_cache)
+               kmem_cache_destroy(btrfs_ordered_extent_cache);
+}
index e03c560d299732cfe2114fe41d049b691a949e61..dd27a0b46a37d1dfd878828672dfb0dbe99f5ac8 100644 (file)
@@ -96,6 +96,13 @@ struct btrfs_ordered_extent {
        /* number of bytes that still need writing */
        u64 bytes_left;
 
+       /*
+        * the end of the ordered extent which is behind it but
+        * didn't update disk_i_size. Please see the comment of
+        * btrfs_ordered_update_i_size();
+        */
+       u64 outstanding_isize;
+
        /* flags (described above) */
        unsigned long flags;
 
@@ -183,6 +190,7 @@ void btrfs_run_ordered_operations(struct btrfs_root *root, int wait);
 void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans,
                                 struct btrfs_root *root,
                                 struct inode *inode);
-void btrfs_wait_ordered_extents(struct btrfs_root *root,
-                               int nocow_only, int delay_iput);
+void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput);
+int __init ordered_data_init(void);
+void ordered_data_exit(void);
 #endif
index b65015581744a6eefb9b3ed720478673b888d336..5039686df6ae8e801ed8985eb5e821a226e18855 100644 (file)
@@ -1145,12 +1145,12 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle *trans,
 
                ulist_reinit(tmp);
                                                /* XXX id not needed */
-               ulist_add(tmp, qg->qgroupid, (unsigned long)qg, GFP_ATOMIC);
+               ulist_add(tmp, qg->qgroupid, (u64)(uintptr_t)qg, GFP_ATOMIC);
                ULIST_ITER_INIT(&tmp_uiter);
                while ((tmp_unode = ulist_next(tmp, &tmp_uiter))) {
                        struct btrfs_qgroup_list *glist;
 
-                       qg = (struct btrfs_qgroup *)tmp_unode->aux;
+                       qg = (struct btrfs_qgroup *)(uintptr_t)tmp_unode->aux;
                        if (qg->refcnt < seq)
                                qg->refcnt = seq + 1;
                        else
@@ -1158,7 +1158,7 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle *trans,
 
                        list_for_each_entry(glist, &qg->groups, next_group) {
                                ulist_add(tmp, glist->group->qgroupid,
-                                         (unsigned long)glist->group,
+                                         (u64)(uintptr_t)glist->group,
                                          GFP_ATOMIC);
                        }
                }
@@ -1168,13 +1168,13 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle *trans,
         * step 2: walk from the new root
         */
        ulist_reinit(tmp);
-       ulist_add(tmp, qgroup->qgroupid, (unsigned long)qgroup, GFP_ATOMIC);
+       ulist_add(tmp, qgroup->qgroupid, (uintptr_t)qgroup, GFP_ATOMIC);
        ULIST_ITER_INIT(&uiter);
        while ((unode = ulist_next(tmp, &uiter))) {
                struct btrfs_qgroup *qg;
                struct btrfs_qgroup_list *glist;
 
-               qg = (struct btrfs_qgroup *)unode->aux;
+               qg = (struct btrfs_qgroup *)(uintptr_t)unode->aux;
                if (qg->refcnt < seq) {
                        /* not visited by step 1 */
                        qg->rfer += sgn * node->num_bytes;
@@ -1190,7 +1190,7 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle *trans,
 
                list_for_each_entry(glist, &qg->groups, next_group) {
                        ulist_add(tmp, glist->group->qgroupid,
-                                 (unsigned long)glist->group, GFP_ATOMIC);
+                                 (uintptr_t)glist->group, GFP_ATOMIC);
                }
        }
 
@@ -1208,12 +1208,12 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle *trans,
                        continue;
 
                ulist_reinit(tmp);
-               ulist_add(tmp, qg->qgroupid, (unsigned long)qg, GFP_ATOMIC);
+               ulist_add(tmp, qg->qgroupid, (uintptr_t)qg, GFP_ATOMIC);
                ULIST_ITER_INIT(&tmp_uiter);
                while ((tmp_unode = ulist_next(tmp, &tmp_uiter))) {
                        struct btrfs_qgroup_list *glist;
 
-                       qg = (struct btrfs_qgroup *)tmp_unode->aux;
+                       qg = (struct btrfs_qgroup *)(uintptr_t)tmp_unode->aux;
                        if (qg->tag == seq)
                                continue;
 
@@ -1225,7 +1225,7 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle *trans,
 
                        list_for_each_entry(glist, &qg->groups, next_group) {
                                ulist_add(tmp, glist->group->qgroupid,
-                                         (unsigned long)glist->group,
+                                         (uintptr_t)glist->group,
                                          GFP_ATOMIC);
                        }
                }
@@ -1469,13 +1469,17 @@ int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes)
         * be exceeded
         */
        ulist = ulist_alloc(GFP_ATOMIC);
-       ulist_add(ulist, qgroup->qgroupid, (unsigned long)qgroup, GFP_ATOMIC);
+       if (!ulist) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       ulist_add(ulist, qgroup->qgroupid, (uintptr_t)qgroup, GFP_ATOMIC);
        ULIST_ITER_INIT(&uiter);
        while ((unode = ulist_next(ulist, &uiter))) {
                struct btrfs_qgroup *qg;
                struct btrfs_qgroup_list *glist;
 
-               qg = (struct btrfs_qgroup *)unode->aux;
+               qg = (struct btrfs_qgroup *)(uintptr_t)unode->aux;
 
                if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) &&
                    qg->reserved + qg->rfer + num_bytes >
@@ -1489,7 +1493,7 @@ int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes)
 
                list_for_each_entry(glist, &qg->groups, next_group) {
                        ulist_add(ulist, glist->group->qgroupid,
-                                 (unsigned long)glist->group, GFP_ATOMIC);
+                                 (uintptr_t)glist->group, GFP_ATOMIC);
                }
        }
        if (ret)
@@ -1502,7 +1506,7 @@ int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes)
        while ((unode = ulist_next(ulist, &uiter))) {
                struct btrfs_qgroup *qg;
 
-               qg = (struct btrfs_qgroup *)unode->aux;
+               qg = (struct btrfs_qgroup *)(uintptr_t)unode->aux;
 
                qg->reserved += num_bytes;
        }
@@ -1541,19 +1545,23 @@ void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes)
                goto out;
 
        ulist = ulist_alloc(GFP_ATOMIC);
-       ulist_add(ulist, qgroup->qgroupid, (unsigned long)qgroup, GFP_ATOMIC);
+       if (!ulist) {
+               btrfs_std_error(fs_info, -ENOMEM);
+               goto out;
+       }
+       ulist_add(ulist, qgroup->qgroupid, (uintptr_t)qgroup, GFP_ATOMIC);
        ULIST_ITER_INIT(&uiter);
        while ((unode = ulist_next(ulist, &uiter))) {
                struct btrfs_qgroup *qg;
                struct btrfs_qgroup_list *glist;
 
-               qg = (struct btrfs_qgroup *)unode->aux;
+               qg = (struct btrfs_qgroup *)(uintptr_t)unode->aux;
 
                qg->reserved -= num_bytes;
 
                list_for_each_entry(glist, &qg->groups, next_group) {
                        ulist_add(ulist, glist->group->qgroupid,
-                                 (unsigned long)glist->group, GFP_ATOMIC);
+                                 (uintptr_t)glist->group, GFP_ATOMIC);
                }
        }
 
index 4da08652004d5dc2803dba510c0f9b015607b4a1..776f0aa128fc56294dbed997d6a60768f05a0ee9 100644 (file)
@@ -3270,8 +3270,8 @@ static int delete_block_group_cache(struct btrfs_fs_info *fs_info,
        key.offset = 0;
 
        inode = btrfs_iget(fs_info->sb, &key, root, NULL);
-       if (IS_ERR_OR_NULL(inode) || is_bad_inode(inode)) {
-               if (inode && !IS_ERR(inode))
+       if (IS_ERR(inode) || is_bad_inode(inode)) {
+               if (!IS_ERR(inode))
                        iput(inode);
                return -ENOENT;
        }
@@ -3621,7 +3621,7 @@ next:
 
                ret = find_first_extent_bit(&rc->processed_blocks,
                                            key.objectid, &start, &end,
-                                           EXTENT_DIRTY);
+                                           EXTENT_DIRTY, NULL);
 
                if (ret == 0 && start <= key.objectid) {
                        btrfs_release_path(path);
@@ -3674,7 +3674,8 @@ int prepare_to_relocate(struct reloc_control *rc)
        struct btrfs_trans_handle *trans;
        int ret;
 
-       rc->block_rsv = btrfs_alloc_block_rsv(rc->extent_root);
+       rc->block_rsv = btrfs_alloc_block_rsv(rc->extent_root,
+                                             BTRFS_BLOCK_RSV_TEMP);
        if (!rc->block_rsv)
                return -ENOMEM;
 
@@ -4057,7 +4058,7 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
               (unsigned long long)rc->block_group->flags);
 
        btrfs_start_delalloc_inodes(fs_info->tree_root, 0);
-       btrfs_wait_ordered_extents(fs_info->tree_root, 0, 0);
+       btrfs_wait_ordered_extents(fs_info->tree_root, 0);
 
        while (1) {
                mutex_lock(&fs_info->cleaner_mutex);
index 10d8e4d88071747651afd3a875eae0fb407c22e4..eb923d087da7848d445820213d53ff3b39d7d279 100644 (file)
@@ -141,8 +141,10 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
                return -ENOMEM;
 
        ret = btrfs_search_slot(trans, root, key, path, 0, 1);
-       if (ret < 0)
-               goto out_abort;
+       if (ret < 0) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto out;
+       }
 
        if (ret != 0) {
                btrfs_print_leaf(root, path->nodes[0]);
@@ -166,16 +168,23 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
                btrfs_release_path(path);
                ret = btrfs_search_slot(trans, root, key, path,
                                -1, 1);
-               if (ret < 0)
-                       goto out_abort;
+               if (ret < 0) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       goto out;
+               }
+
                ret = btrfs_del_item(trans, root, path);
-               if (ret < 0)
-                       goto out_abort;
+               if (ret < 0) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       goto out;
+               }
                btrfs_release_path(path);
                ret = btrfs_insert_empty_item(trans, root, path,
                                key, sizeof(*item));
-               if (ret < 0)
-                       goto out_abort;
+               if (ret < 0) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       goto out;
+               }
                l = path->nodes[0];
                slot = path->slots[0];
                ptr = btrfs_item_ptr_offset(l, slot);
@@ -192,10 +201,6 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
 out:
        btrfs_free_path(path);
        return ret;
-
-out_abort:
-       btrfs_abort_transaction(trans, root, ret);
-       goto out;
 }
 
 int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
index b223620cd5a6d59aa4b707e2539e59a8244d2dd1..27892f67e69b216694299720caf31b6e19919555 100644 (file)
@@ -352,13 +352,14 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock)
        struct extent_buffer *eb;
        struct btrfs_extent_item *ei;
        struct scrub_warning swarn;
-       u32 item_size;
-       int ret;
+       unsigned long ptr = 0;
+       u64 extent_item_pos;
+       u64 flags = 0;
        u64 ref_root;
+       u32 item_size;
        u8 ref_level;
-       unsigned long ptr = 0;
        const int bufsize = 4096;
-       u64 extent_item_pos;
+       int ret;
 
        path = btrfs_alloc_path();
 
@@ -375,7 +376,8 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock)
        if (!path || !swarn.scratch_buf || !swarn.msg_buf)
                goto out;
 
-       ret = extent_from_logical(fs_info, swarn.logical, path, &found_key);
+       ret = extent_from_logical(fs_info, swarn.logical, path, &found_key,
+                                 &flags);
        if (ret < 0)
                goto out;
 
@@ -387,7 +389,7 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock)
        item_size = btrfs_item_size_nr(eb, path->slots[0]);
        btrfs_release_path(path);
 
-       if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
+       if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
                do {
                        ret = tree_backref_for_extent(&ptr, eb, ei, item_size,
                                                        &ref_root, &ref_level);
@@ -1029,6 +1031,7 @@ static int scrub_setup_recheck_block(struct scrub_dev *sdev,
                                spin_lock(&sdev->stat_lock);
                                sdev->stat.malloc_errors++;
                                spin_unlock(&sdev->stat_lock);
+                               kfree(bbio);
                                return -ENOMEM;
                        }
                        sblock->page_count++;
@@ -1666,21 +1669,6 @@ static void scrub_bio_end_io_worker(struct btrfs_work *work)
                scrub_block_put(sblock);
        }
 
-       if (sbio->err) {
-               /* what is this good for??? */
-               sbio->bio->bi_flags &= ~(BIO_POOL_MASK - 1);
-               sbio->bio->bi_flags |= 1 << BIO_UPTODATE;
-               sbio->bio->bi_phys_segments = 0;
-               sbio->bio->bi_idx = 0;
-
-               for (i = 0; i < sbio->page_count; i++) {
-                       struct bio_vec *bi;
-                       bi = &sbio->bio->bi_io_vec[i];
-                       bi->bv_offset = 0;
-                       bi->bv_len = PAGE_SIZE;
-               }
-       }
-
        bio_put(sbio->bio);
        sbio->bio = NULL;
        spin_lock(&sdev->list_lock);
index fb5ffe95f869342c6f270579c7f3556aef6f80d0..c7beb543a4a89300f1e586492b767ea8f9bef683 100644 (file)
@@ -107,7 +107,6 @@ struct send_ctx {
        int cur_inode_new;
        int cur_inode_new_gen;
        int cur_inode_deleted;
-       int cur_inode_first_ref_orphan;
        u64 cur_inode_size;
        u64 cur_inode_mode;
 
@@ -126,7 +125,15 @@ struct send_ctx {
 
 struct name_cache_entry {
        struct list_head list;
-       struct list_head use_list;
+       /*
+        * radix_tree has only 32bit entries but we need to handle 64bit inums.
+        * We use the lower 32bit of the 64bit inum to store it in the tree. If
+        * more then one inum would fall into the same entry, we use radix_list
+        * to store the additional entries. radix_list is also used to store
+        * entries where two entries have the same inum but different
+        * generations.
+        */
+       struct list_head radix_list;
        u64 ino;
        u64 gen;
        u64 parent_ino;
@@ -328,6 +335,7 @@ out:
        return ret;
 }
 
+#if 0
 static void fs_path_remove(struct fs_path *p)
 {
        BUG_ON(p->reversed);
@@ -335,6 +343,7 @@ static void fs_path_remove(struct fs_path *p)
                p->end--;
        *p->end = 0;
 }
+#endif
 
 static int fs_path_copy(struct fs_path *p, struct fs_path *from)
 {
@@ -377,7 +386,7 @@ static struct btrfs_path *alloc_path_for_send(void)
        return path;
 }
 
-static int write_buf(struct send_ctx *sctx, const void *buf, u32 len)
+int write_buf(struct file *filp, const void *buf, u32 len, loff_t *off)
 {
        int ret;
        mm_segment_t old_fs;
@@ -387,8 +396,7 @@ static int write_buf(struct send_ctx *sctx, const void *buf, u32 len)
        set_fs(KERNEL_DS);
 
        while (pos < len) {
-               ret = vfs_write(sctx->send_filp, (char *)buf + pos, len - pos,
-                               &sctx->send_off);
+               ret = vfs_write(filp, (char *)buf + pos, len - pos, off);
                /* TODO handle that correctly */
                /*if (ret == -ERESTARTSYS) {
                        continue;
@@ -544,7 +552,8 @@ static int send_header(struct send_ctx *sctx)
        strcpy(hdr.magic, BTRFS_SEND_STREAM_MAGIC);
        hdr.version = cpu_to_le32(BTRFS_SEND_STREAM_VERSION);
 
-       return write_buf(sctx, &hdr, sizeof(hdr));
+       return write_buf(sctx->send_filp, &hdr, sizeof(hdr),
+                                       &sctx->send_off);
 }
 
 /*
@@ -581,7 +590,8 @@ static int send_cmd(struct send_ctx *sctx)
        crc = crc32c(0, (unsigned char *)sctx->send_buf, sctx->send_size);
        hdr->crc = cpu_to_le32(crc);
 
-       ret = write_buf(sctx, sctx->send_buf, sctx->send_size);
+       ret = write_buf(sctx->send_filp, sctx->send_buf, sctx->send_size,
+                                       &sctx->send_off);
 
        sctx->total_send_size += sctx->send_size;
        sctx->cmd_send_size[le16_to_cpu(hdr->cmd)] += sctx->send_size;
@@ -687,7 +697,8 @@ out:
  */
 static int get_inode_info(struct btrfs_root *root,
                          u64 ino, u64 *size, u64 *gen,
-                         u64 *mode, u64 *uid, u64 *gid)
+                         u64 *mode, u64 *uid, u64 *gid,
+                         u64 *rdev)
 {
        int ret;
        struct btrfs_inode_item *ii;
@@ -721,6 +732,8 @@ static int get_inode_info(struct btrfs_root *root,
                *uid = btrfs_inode_uid(path->nodes[0], ii);
        if (gid)
                *gid = btrfs_inode_gid(path->nodes[0], ii);
+       if (rdev)
+               *rdev = btrfs_inode_rdev(path->nodes[0], ii);
 
 out:
        btrfs_free_path(path);
@@ -852,7 +865,6 @@ static int iterate_dir_item(struct send_ctx *sctx,
        struct extent_buffer *eb;
        struct btrfs_item *item;
        struct btrfs_dir_item *di;
-       struct btrfs_path *tmp_path = NULL;
        struct btrfs_key di_key;
        char *buf = NULL;
        char *buf2 = NULL;
@@ -874,12 +886,6 @@ static int iterate_dir_item(struct send_ctx *sctx,
                goto out;
        }
 
-       tmp_path = alloc_path_for_send();
-       if (!tmp_path) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
        eb = path->nodes[0];
        slot = path->slots[0];
        item = btrfs_item_nr(eb, slot);
@@ -941,7 +947,6 @@ static int iterate_dir_item(struct send_ctx *sctx,
        }
 
 out:
-       btrfs_free_path(tmp_path);
        if (buf_virtual)
                vfree(buf);
        else
@@ -1026,12 +1031,12 @@ struct backref_ctx {
        u64 extent_len;
 
        /* Just to check for bugs in backref resolving */
-       int found_in_send_root;
+       int found_itself;
 };
 
 static int __clone_root_cmp_bsearch(const void *key, const void *elt)
 {
-       u64 root = (u64)key;
+       u64 root = (u64)(uintptr_t)key;
        struct clone_root *cr = (struct clone_root *)elt;
 
        if (root < cr->root->objectid)
@@ -1055,6 +1060,7 @@ static int __clone_root_cmp_sort(const void *e1, const void *e2)
 
 /*
  * Called for every backref that is found for the current extent.
+ * Results are collected in sctx->clone_roots->ino/offset/found_refs
  */
 static int __iterate_backrefs(u64 ino, u64 offset, u64 root, void *ctx_)
 {
@@ -1064,7 +1070,7 @@ static int __iterate_backrefs(u64 ino, u64 offset, u64 root, void *ctx_)
        u64 i_size;
 
        /* First check if the root is in the list of accepted clone sources */
-       found = bsearch((void *)root, bctx->sctx->clone_roots,
+       found = bsearch((void *)(uintptr_t)root, bctx->sctx->clone_roots,
                        bctx->sctx->clone_roots_cnt,
                        sizeof(struct clone_root),
                        __clone_root_cmp_bsearch);
@@ -1074,14 +1080,15 @@ static int __iterate_backrefs(u64 ino, u64 offset, u64 root, void *ctx_)
        if (found->root == bctx->sctx->send_root &&
            ino == bctx->cur_objectid &&
            offset == bctx->cur_offset) {
-               bctx->found_in_send_root = 1;
+               bctx->found_itself = 1;
        }
 
        /*
-        * There are inodes that have extents that lie behind it's i_size. Don't
+        * There are inodes that have extents that lie behind its i_size. Don't
         * accept clones from these extents.
         */
-       ret = get_inode_info(found->root, ino, &i_size, NULL, NULL, NULL, NULL);
+       ret = get_inode_info(found->root, ino, &i_size, NULL, NULL, NULL, NULL,
+                       NULL);
        if (ret < 0)
                return ret;
 
@@ -1101,16 +1108,12 @@ static int __iterate_backrefs(u64 ino, u64 offset, u64 root, void *ctx_)
                 */
                if (ino >= bctx->cur_objectid)
                        return 0;
-               /*if (ino > ctx->cur_objectid)
+#if 0
+               if (ino > bctx->cur_objectid)
                        return 0;
-               if (offset + ctx->extent_len > ctx->cur_offset)
-                       return 0;*/
-
-               bctx->found++;
-               found->found_refs++;
-               found->ino = ino;
-               found->offset = offset;
-               return 0;
+               if (offset + bctx->extent_len > bctx->cur_offset)
+                       return 0;
+#endif
        }
 
        bctx->found++;
@@ -1130,6 +1133,12 @@ static int __iterate_backrefs(u64 ino, u64 offset, u64 root, void *ctx_)
 }
 
 /*
+ * Given an inode, offset and extent item, it finds a good clone for a clone
+ * instruction. Returns -ENOENT when none could be found. The function makes
+ * sure that the returned clone is usable at the point where sending is at the
+ * moment. This means, that no clones are accepted which lie behind the current
+ * inode+offset.
+ *
  * path must point to the extent item when called.
  */
 static int find_extent_clone(struct send_ctx *sctx,
@@ -1141,20 +1150,29 @@ static int find_extent_clone(struct send_ctx *sctx,
        int ret;
        int extent_type;
        u64 logical;
+       u64 disk_byte;
        u64 num_bytes;
        u64 extent_item_pos;
+       u64 flags = 0;
        struct btrfs_file_extent_item *fi;
        struct extent_buffer *eb = path->nodes[0];
-       struct backref_ctx backref_ctx;
+       struct backref_ctx *backref_ctx = NULL;
        struct clone_root *cur_clone_root;
        struct btrfs_key found_key;
        struct btrfs_path *tmp_path;
+       int compressed;
        u32 i;
 
        tmp_path = alloc_path_for_send();
        if (!tmp_path)
                return -ENOMEM;
 
+       backref_ctx = kmalloc(sizeof(*backref_ctx), GFP_NOFS);
+       if (!backref_ctx) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
        if (data_offset >= ino_size) {
                /*
                 * There may be extents that lie behind the file's size.
@@ -1172,22 +1190,23 @@ static int find_extent_clone(struct send_ctx *sctx,
                ret = -ENOENT;
                goto out;
        }
+       compressed = btrfs_file_extent_compression(eb, fi);
 
        num_bytes = btrfs_file_extent_num_bytes(eb, fi);
-       logical = btrfs_file_extent_disk_bytenr(eb, fi);
-       if (logical == 0) {
+       disk_byte = btrfs_file_extent_disk_bytenr(eb, fi);
+       if (disk_byte == 0) {
                ret = -ENOENT;
                goto out;
        }
-       logical += btrfs_file_extent_offset(eb, fi);
+       logical = disk_byte + btrfs_file_extent_offset(eb, fi);
 
-       ret = extent_from_logical(sctx->send_root->fs_info,
-                       logical, tmp_path, &found_key);
+       ret = extent_from_logical(sctx->send_root->fs_info, disk_byte, tmp_path,
+                                 &found_key, &flags);
        btrfs_release_path(tmp_path);
 
        if (ret < 0)
                goto out;
-       if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
+       if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
                ret = -EIO;
                goto out;
        }
@@ -1202,12 +1221,12 @@ static int find_extent_clone(struct send_ctx *sctx,
                cur_clone_root->found_refs = 0;
        }
 
-       backref_ctx.sctx = sctx;
-       backref_ctx.found = 0;
-       backref_ctx.cur_objectid = ino;
-       backref_ctx.cur_offset = data_offset;
-       backref_ctx.found_in_send_root = 0;
-       backref_ctx.extent_len = num_bytes;
+       backref_ctx->sctx = sctx;
+       backref_ctx->found = 0;
+       backref_ctx->cur_objectid = ino;
+       backref_ctx->cur_offset = data_offset;
+       backref_ctx->found_itself = 0;
+       backref_ctx->extent_len = num_bytes;
 
        /*
         * The last extent of a file may be too large due to page alignment.
@@ -1215,25 +1234,31 @@ static int find_extent_clone(struct send_ctx *sctx,
         * __iterate_backrefs work.
         */
        if (data_offset + num_bytes >= ino_size)
-               backref_ctx.extent_len = ino_size - data_offset;
+               backref_ctx->extent_len = ino_size - data_offset;
 
        /*
         * Now collect all backrefs.
         */
+       if (compressed == BTRFS_COMPRESS_NONE)
+               extent_item_pos = logical - found_key.objectid;
+       else
+               extent_item_pos = 0;
+
        extent_item_pos = logical - found_key.objectid;
        ret = iterate_extent_inodes(sctx->send_root->fs_info,
                                        found_key.objectid, extent_item_pos, 1,
-                                       __iterate_backrefs, &backref_ctx);
+                                       __iterate_backrefs, backref_ctx);
+
        if (ret < 0)
                goto out;
 
-       if (!backref_ctx.found_in_send_root) {
+       if (!backref_ctx->found_itself) {
                /* found a bug in backref code? */
                ret = -EIO;
                printk(KERN_ERR "btrfs: ERROR did not find backref in "
                                "send_root. inode=%llu, offset=%llu, "
-                               "logical=%llu\n",
-                               ino, data_offset, logical);
+                               "disk_byte=%llu found extent=%llu\n",
+                               ino, data_offset, disk_byte, found_key.objectid);
                goto out;
        }
 
@@ -1242,7 +1267,7 @@ verbose_printk(KERN_DEBUG "btrfs: find_extent_clone: data_offset=%llu, "
                "num_bytes=%llu, logical=%llu\n",
                data_offset, ino, num_bytes, logical);
 
-       if (!backref_ctx.found)
+       if (!backref_ctx->found)
                verbose_printk("btrfs:    no clones found\n");
 
        cur_clone_root = NULL;
@@ -1253,7 +1278,6 @@ verbose_printk(KERN_DEBUG "btrfs: find_extent_clone: data_offset=%llu, "
                        else if (sctx->clone_roots[i].root == sctx->send_root)
                                /* prefer clones from send_root over others */
                                cur_clone_root = sctx->clone_roots + i;
-                       break;
                }
 
        }
@@ -1267,6 +1291,7 @@ verbose_printk(KERN_DEBUG "btrfs: find_extent_clone: data_offset=%llu, "
 
 out:
        btrfs_free_path(tmp_path);
+       kfree(backref_ctx);
        return ret;
 }
 
@@ -1307,8 +1332,6 @@ static int read_symlink(struct send_ctx *sctx,
        len = btrfs_file_extent_inline_len(path->nodes[0], ei);
 
        ret = fs_path_add_from_extent_buffer(dest, path->nodes[0], off, len);
-       if (ret < 0)
-               goto out;
 
 out:
        btrfs_free_path(path);
@@ -1404,7 +1427,7 @@ static int get_cur_inode_state(struct send_ctx *sctx, u64 ino, u64 gen)
        u64 right_gen;
 
        ret = get_inode_info(sctx->send_root, ino, NULL, &left_gen, NULL, NULL,
-                       NULL);
+                       NULL, NULL);
        if (ret < 0 && ret != -ENOENT)
                goto out;
        left_ret = ret;
@@ -1413,16 +1436,16 @@ static int get_cur_inode_state(struct send_ctx *sctx, u64 ino, u64 gen)
                right_ret = -ENOENT;
        } else {
                ret = get_inode_info(sctx->parent_root, ino, NULL, &right_gen,
-                               NULL, NULL, NULL);
+                               NULL, NULL, NULL, NULL);
                if (ret < 0 && ret != -ENOENT)
                        goto out;
                right_ret = ret;
        }
 
        if (!left_ret && !right_ret) {
-               if (left_gen == gen && right_gen == gen)
+               if (left_gen == gen && right_gen == gen) {
                        ret = inode_state_no_change;
-               else if (left_gen == gen) {
+               else if (left_gen == gen) {
                        if (ino < sctx->send_progress)
                                ret = inode_state_did_create;
                        else
@@ -1516,6 +1539,10 @@ out:
        return ret;
 }
 
+/*
+ * Looks up the first btrfs_inode_ref of a given ino. It returns the parent dir,
+ * generation of the parent dir and the name of the dir entry.
+ */
 static int get_first_ref(struct send_ctx *sctx,
                         struct btrfs_root *root, u64 ino,
                         u64 *dir, u64 *dir_gen, struct fs_path *name)
@@ -1557,7 +1584,7 @@ static int get_first_ref(struct send_ctx *sctx,
        btrfs_release_path(path);
 
        ret = get_inode_info(root, found_key.offset, NULL, dir_gen, NULL, NULL,
-                       NULL);
+                       NULL, NULL);
        if (ret < 0)
                goto out;
 
@@ -1586,22 +1613,28 @@ static int is_first_ref(struct send_ctx *sctx,
        if (ret < 0)
                goto out;
 
-       if (name_len != fs_path_len(tmp_name)) {
+       if (dir != tmp_dir || name_len != fs_path_len(tmp_name)) {
                ret = 0;
                goto out;
        }
 
-       ret = memcmp(tmp_name->start, name, name_len);
-       if (ret)
-               ret = 0;
-       else
-               ret = 1;
+       ret = !memcmp(tmp_name->start, name, name_len);
 
 out:
        fs_path_free(sctx, tmp_name);
        return ret;
 }
 
+/*
+ * Used by process_recorded_refs to determine if a new ref would overwrite an
+ * already existing ref. In case it detects an overwrite, it returns the
+ * inode/gen in who_ino/who_gen.
+ * When an overwrite is detected, process_recorded_refs does proper orphanizing
+ * to make sure later references to the overwritten inode are possible.
+ * Orphanizing is however only required for the first ref of an inode.
+ * process_recorded_refs does an additional is_first_ref check to see if
+ * orphanizing is really required.
+ */
 static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen,
                              const char *name, int name_len,
                              u64 *who_ino, u64 *who_gen)
@@ -1626,9 +1659,14 @@ static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen,
                goto out;
        }
 
+       /*
+        * Check if the overwritten ref was already processed. If yes, the ref
+        * was already unlinked/moved, so we can safely assume that we will not
+        * overwrite anything at this point in time.
+        */
        if (other_inode > sctx->send_progress) {
                ret = get_inode_info(sctx->parent_root, other_inode, NULL,
-                               who_gen, NULL, NULL, NULL);
+                               who_gen, NULL, NULL, NULL, NULL);
                if (ret < 0)
                        goto out;
 
@@ -1642,6 +1680,13 @@ out:
        return ret;
 }
 
+/*
+ * Checks if the ref was overwritten by an already processed inode. This is
+ * used by __get_cur_name_and_parent to find out if the ref was orphanized and
+ * thus the orphan name needs be used.
+ * process_recorded_refs also uses it to avoid unlinking of refs that were
+ * overwritten.
+ */
 static int did_overwrite_ref(struct send_ctx *sctx,
                            u64 dir, u64 dir_gen,
                            u64 ino, u64 ino_gen,
@@ -1671,7 +1716,7 @@ static int did_overwrite_ref(struct send_ctx *sctx,
        }
 
        ret = get_inode_info(sctx->send_root, ow_inode, NULL, &gen, NULL, NULL,
-                       NULL);
+                       NULL, NULL);
        if (ret < 0)
                goto out;
 
@@ -1690,6 +1735,11 @@ out:
        return ret;
 }
 
+/*
+ * Same as did_overwrite_ref, but also checks if it is the first ref of an inode
+ * that got overwritten. This is used by process_recorded_refs to determine
+ * if it has to use the path as returned by get_cur_path or the orphan name.
+ */
 static int did_overwrite_first_ref(struct send_ctx *sctx, u64 ino, u64 gen)
 {
        int ret = 0;
@@ -1710,39 +1760,40 @@ static int did_overwrite_first_ref(struct send_ctx *sctx, u64 ino, u64 gen)
 
        ret = did_overwrite_ref(sctx, dir, dir_gen, ino, gen,
                        name->start, fs_path_len(name));
-       if (ret < 0)
-               goto out;
 
 out:
        fs_path_free(sctx, name);
        return ret;
 }
 
+/*
+ * Insert a name cache entry. On 32bit kernels the radix tree index is 32bit,
+ * so we need to do some special handling in case we have clashes. This function
+ * takes care of this with the help of name_cache_entry::radix_list.
+ * In case of error, nce is kfreed.
+ */
 static int name_cache_insert(struct send_ctx *sctx,
                             struct name_cache_entry *nce)
 {
        int ret = 0;
-       struct name_cache_entry **ncea;
-
-       ncea = radix_tree_lookup(&sctx->name_cache, nce->ino);
-       if (ncea) {
-               if (!ncea[0])
-                       ncea[0] = nce;
-               else if (!ncea[1])
-                       ncea[1] = nce;
-               else
-                       BUG();
-       } else {
-               ncea = kmalloc(sizeof(void *) * 2, GFP_NOFS);
-               if (!ncea)
+       struct list_head *nce_head;
+
+       nce_head = radix_tree_lookup(&sctx->name_cache,
+                       (unsigned long)nce->ino);
+       if (!nce_head) {
+               nce_head = kmalloc(sizeof(*nce_head), GFP_NOFS);
+               if (!nce_head)
                        return -ENOMEM;
+               INIT_LIST_HEAD(nce_head);
 
-               ncea[0] = nce;
-               ncea[1] = NULL;
-               ret = radix_tree_insert(&sctx->name_cache, nce->ino, ncea);
-               if (ret < 0)
+               ret = radix_tree_insert(&sctx->name_cache, nce->ino, nce_head);
+               if (ret < 0) {
+                       kfree(nce_head);
+                       kfree(nce);
                        return ret;
+               }
        }
+       list_add_tail(&nce->radix_list, nce_head);
        list_add_tail(&nce->list, &sctx->name_cache_list);
        sctx->name_cache_size++;
 
@@ -1752,50 +1803,52 @@ static int name_cache_insert(struct send_ctx *sctx,
 static void name_cache_delete(struct send_ctx *sctx,
                              struct name_cache_entry *nce)
 {
-       struct name_cache_entry **ncea;
-
-       ncea = radix_tree_lookup(&sctx->name_cache, nce->ino);
-       BUG_ON(!ncea);
-
-       if (ncea[0] == nce)
-               ncea[0] = NULL;
-       else if (ncea[1] == nce)
-               ncea[1] = NULL;
-       else
-               BUG();
+       struct list_head *nce_head;
 
-       if (!ncea[0] && !ncea[1]) {
-               radix_tree_delete(&sctx->name_cache, nce->ino);
-               kfree(ncea);
-       }
+       nce_head = radix_tree_lookup(&sctx->name_cache,
+                       (unsigned long)nce->ino);
+       BUG_ON(!nce_head);
 
+       list_del(&nce->radix_list);
        list_del(&nce->list);
-
        sctx->name_cache_size--;
+
+       if (list_empty(nce_head)) {
+               radix_tree_delete(&sctx->name_cache, (unsigned long)nce->ino);
+               kfree(nce_head);
+       }
 }
 
 static struct name_cache_entry *name_cache_search(struct send_ctx *sctx,
                                                    u64 ino, u64 gen)
 {
-       struct name_cache_entry **ncea;
+       struct list_head *nce_head;
+       struct name_cache_entry *cur;
 
-       ncea = radix_tree_lookup(&sctx->name_cache, ino);
-       if (!ncea)
+       nce_head = radix_tree_lookup(&sctx->name_cache, (unsigned long)ino);
+       if (!nce_head)
                return NULL;
 
-       if (ncea[0] && ncea[0]->gen == gen)
-               return ncea[0];
-       else if (ncea[1] && ncea[1]->gen == gen)
-               return ncea[1];
+       list_for_each_entry(cur, nce_head, radix_list) {
+               if (cur->ino == ino && cur->gen == gen)
+                       return cur;
+       }
        return NULL;
 }
 
+/*
+ * Removes the entry from the list and adds it back to the end. This marks the
+ * entry as recently used so that name_cache_clean_unused does not remove it.
+ */
 static void name_cache_used(struct send_ctx *sctx, struct name_cache_entry *nce)
 {
        list_del(&nce->list);
        list_add_tail(&nce->list, &sctx->name_cache_list);
 }
 
+/*
+ * Remove some entries from the beginning of name_cache_list.
+ */
 static void name_cache_clean_unused(struct send_ctx *sctx)
 {
        struct name_cache_entry *nce;
@@ -1814,13 +1867,23 @@ static void name_cache_clean_unused(struct send_ctx *sctx)
 static void name_cache_free(struct send_ctx *sctx)
 {
        struct name_cache_entry *nce;
-       struct name_cache_entry *tmp;
 
-       list_for_each_entry_safe(nce, tmp, &sctx->name_cache_list, list) {
+       while (!list_empty(&sctx->name_cache_list)) {
+               nce = list_entry(sctx->name_cache_list.next,
+                               struct name_cache_entry, list);
                name_cache_delete(sctx, nce);
+               kfree(nce);
        }
 }
 
+/*
+ * Used by get_cur_path for each ref up to the root.
+ * Returns 0 if it succeeded.
+ * Returns 1 if the inode is not existent or got overwritten. In that case, the
+ * name is an orphan name. This instructs get_cur_path to stop iterating. If 1
+ * is returned, parent_ino/parent_gen are not guaranteed to be valid.
+ * Returns <0 in case of error.
+ */
 static int __get_cur_name_and_parent(struct send_ctx *sctx,
                                     u64 ino, u64 gen,
                                     u64 *parent_ino,
@@ -1832,6 +1895,11 @@ static int __get_cur_name_and_parent(struct send_ctx *sctx,
        struct btrfs_path *path = NULL;
        struct name_cache_entry *nce = NULL;
 
+       /*
+        * First check if we already did a call to this function with the same
+        * ino/gen. If yes, check if the cache entry is still up-to-date. If yes
+        * return the cached result.
+        */
        nce = name_cache_search(sctx, ino, gen);
        if (nce) {
                if (ino < sctx->send_progress && nce->need_later_update) {
@@ -1854,6 +1922,11 @@ static int __get_cur_name_and_parent(struct send_ctx *sctx,
        if (!path)
                return -ENOMEM;
 
+       /*
+        * If the inode is not existent yet, add the orphan name and return 1.
+        * This should only happen for the parent dir that we determine in
+        * __record_new_ref
+        */
        ret = is_inode_existent(sctx, ino, gen);
        if (ret < 0)
                goto out;
@@ -1866,6 +1939,10 @@ static int __get_cur_name_and_parent(struct send_ctx *sctx,
                goto out_cache;
        }
 
+       /*
+        * Depending on whether the inode was already processed or not, use
+        * send_root or parent_root for ref lookup.
+        */
        if (ino < sctx->send_progress)
                ret = get_first_ref(sctx, sctx->send_root, ino,
                                parent_ino, parent_gen, dest);
@@ -1875,6 +1952,10 @@ static int __get_cur_name_and_parent(struct send_ctx *sctx,
        if (ret < 0)
                goto out;
 
+       /*
+        * Check if the ref was overwritten by an inode's ref that was processed
+        * earlier. If yes, treat as orphan and return 1.
+        */
        ret = did_overwrite_ref(sctx, *parent_ino, *parent_gen, ino, gen,
                        dest->start, dest->end - dest->start);
        if (ret < 0)
@@ -1888,6 +1969,9 @@ static int __get_cur_name_and_parent(struct send_ctx *sctx,
        }
 
 out_cache:
+       /*
+        * Store the result of the lookup in the name cache.
+        */
        nce = kmalloc(sizeof(*nce) + fs_path_len(dest) + 1, GFP_NOFS);
        if (!nce) {
                ret = -ENOMEM;
@@ -1901,7 +1985,6 @@ out_cache:
        nce->name_len = fs_path_len(dest);
        nce->ret = ret;
        strcpy(nce->name, dest->start);
-       memset(&nce->use_list, 0, sizeof(nce->use_list));
 
        if (ino < sctx->send_progress)
                nce->need_later_update = 0;
@@ -2107,9 +2190,6 @@ static int send_subvol_begin(struct send_ctx *sctx)
        read_extent_buffer(leaf, name, (unsigned long)(ref + 1), namelen);
        btrfs_release_path(path);
 
-       if (ret < 0)
-               goto out;
-
        if (parent_root) {
                ret = begin_cmd(sctx, BTRFS_SEND_C_SNAPSHOT);
                if (ret < 0)
@@ -2276,7 +2356,7 @@ verbose_printk("btrfs: send_utimes %llu\n", ino);
                        btrfs_inode_mtime(ii));
        TLV_PUT_BTRFS_TIMESPEC(sctx, BTRFS_SEND_A_CTIME, eb,
                        btrfs_inode_ctime(ii));
-       /* TODO otime? */
+       /* TODO Add otime support when the otime patches get into upstream */
 
        ret = send_cmd(sctx);
 
@@ -2292,39 +2372,39 @@ out:
  * a valid path yet because we did not process the refs yet. So, the inode
  * is created as orphan.
  */
-static int send_create_inode(struct send_ctx *sctx, struct btrfs_path *path,
-                            struct btrfs_key *key)
+static int send_create_inode(struct send_ctx *sctx, u64 ino)
 {
        int ret = 0;
-       struct extent_buffer *eb = path->nodes[0];
-       struct btrfs_inode_item *ii;
        struct fs_path *p;
-       int slot = path->slots[0];
        int cmd;
+       u64 gen;
        u64 mode;
+       u64 rdev;
 
-verbose_printk("btrfs: send_create_inode %llu\n", sctx->cur_ino);
+verbose_printk("btrfs: send_create_inode %llu\n", ino);
 
        p = fs_path_alloc(sctx);
        if (!p)
                return -ENOMEM;
 
-       ii = btrfs_item_ptr(eb, slot, struct btrfs_inode_item);
-       mode = btrfs_inode_mode(eb, ii);
+       ret = get_inode_info(sctx->send_root, ino, NULL, &gen, &mode, NULL,
+                       NULL, &rdev);
+       if (ret < 0)
+               goto out;
 
-       if (S_ISREG(mode))
+       if (S_ISREG(mode)) {
                cmd = BTRFS_SEND_C_MKFILE;
-       else if (S_ISDIR(mode))
+       } else if (S_ISDIR(mode)) {
                cmd = BTRFS_SEND_C_MKDIR;
-       else if (S_ISLNK(mode))
+       } else if (S_ISLNK(mode)) {
                cmd = BTRFS_SEND_C_SYMLINK;
-       else if (S_ISCHR(mode) || S_ISBLK(mode))
+       } else if (S_ISCHR(mode) || S_ISBLK(mode)) {
                cmd = BTRFS_SEND_C_MKNOD;
-       else if (S_ISFIFO(mode))
+       } else if (S_ISFIFO(mode)) {
                cmd = BTRFS_SEND_C_MKFIFO;
-       else if (S_ISSOCK(mode))
+       } else if (S_ISSOCK(mode)) {
                cmd = BTRFS_SEND_C_MKSOCK;
-       else {
+       else {
                printk(KERN_WARNING "btrfs: unexpected inode type %o",
                                (int)(mode & S_IFMT));
                ret = -ENOTSUPP;
@@ -2335,22 +2415,22 @@ verbose_printk("btrfs: send_create_inode %llu\n", sctx->cur_ino);
        if (ret < 0)
                goto out;
 
-       ret = gen_unique_name(sctx, sctx->cur_ino, sctx->cur_inode_gen, p);
+       ret = gen_unique_name(sctx, ino, gen, p);
        if (ret < 0)
                goto out;
 
        TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p);
-       TLV_PUT_U64(sctx, BTRFS_SEND_A_INO, sctx->cur_ino);
+       TLV_PUT_U64(sctx, BTRFS_SEND_A_INO, ino);
 
        if (S_ISLNK(mode)) {
                fs_path_reset(p);
-               ret = read_symlink(sctx, sctx->send_root, sctx->cur_ino, p);
+               ret = read_symlink(sctx, sctx->send_root, ino, p);
                if (ret < 0)
                        goto out;
                TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_LINK, p);
        } else if (S_ISCHR(mode) || S_ISBLK(mode) ||
                   S_ISFIFO(mode) || S_ISSOCK(mode)) {
-               TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, btrfs_inode_rdev(eb, ii));
+               TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, rdev);
        }
 
        ret = send_cmd(sctx);
@@ -2364,6 +2444,92 @@ out:
        return ret;
 }
 
+/*
+ * We need some special handling for inodes that get processed before the parent
+ * directory got created. See process_recorded_refs for details.
+ * This function does the check if we already created the dir out of order.
+ */
+static int did_create_dir(struct send_ctx *sctx, u64 dir)
+{
+       int ret = 0;
+       struct btrfs_path *path = NULL;
+       struct btrfs_key key;
+       struct btrfs_key found_key;
+       struct btrfs_key di_key;
+       struct extent_buffer *eb;
+       struct btrfs_dir_item *di;
+       int slot;
+
+       path = alloc_path_for_send();
+       if (!path) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       key.objectid = dir;
+       key.type = BTRFS_DIR_INDEX_KEY;
+       key.offset = 0;
+       while (1) {
+               ret = btrfs_search_slot_for_read(sctx->send_root, &key, path,
+                               1, 0);
+               if (ret < 0)
+                       goto out;
+               if (!ret) {
+                       eb = path->nodes[0];
+                       slot = path->slots[0];
+                       btrfs_item_key_to_cpu(eb, &found_key, slot);
+               }
+               if (ret || found_key.objectid != key.objectid ||
+                   found_key.type != key.type) {
+                       ret = 0;
+                       goto out;
+               }
+
+               di = btrfs_item_ptr(eb, slot, struct btrfs_dir_item);
+               btrfs_dir_item_key_to_cpu(eb, di, &di_key);
+
+               if (di_key.objectid < sctx->send_progress) {
+                       ret = 1;
+                       goto out;
+               }
+
+               key.offset = found_key.offset + 1;
+               btrfs_release_path(path);
+       }
+
+out:
+       btrfs_free_path(path);
+       return ret;
+}
+
+/*
+ * Only creates the inode if it is:
+ * 1. Not a directory
+ * 2. Or a directory which was not created already due to out of order
+ *    directories. See did_create_dir and process_recorded_refs for details.
+ */
+static int send_create_inode_if_needed(struct send_ctx *sctx)
+{
+       int ret;
+
+       if (S_ISDIR(sctx->cur_inode_mode)) {
+               ret = did_create_dir(sctx, sctx->cur_ino);
+               if (ret < 0)
+                       goto out;
+               if (ret) {
+                       ret = 0;
+                       goto out;
+               }
+       }
+
+       ret = send_create_inode(sctx, sctx->cur_ino);
+       if (ret < 0)
+               goto out;
+
+out:
+       return ret;
+}
+
 struct recorded_ref {
        struct list_head list;
        char *dir_path;
@@ -2416,13 +2582,13 @@ static int record_ref(struct list_head *head, u64 dir,
 static void __free_recorded_refs(struct send_ctx *sctx, struct list_head *head)
 {
        struct recorded_ref *cur;
-       struct recorded_ref *tmp;
 
-       list_for_each_entry_safe(cur, tmp, head, list) {
+       while (!list_empty(head)) {
+               cur = list_entry(head->next, struct recorded_ref, list);
                fs_path_free(sctx, cur->full_path);
+               list_del(&cur->list);
                kfree(cur);
        }
-       INIT_LIST_HEAD(head);
 }
 
 static void free_recorded_refs(struct send_ctx *sctx)
@@ -2432,7 +2598,7 @@ static void free_recorded_refs(struct send_ctx *sctx)
 }
 
 /*
- * Renames/moves a file/dir to it's orphan name. Used when the first
+ * Renames/moves a file/dir to its orphan name. Used when the first
  * ref of an unprocessed inode gets overwritten and for all non empty
  * directories.
  */
@@ -2472,6 +2638,12 @@ static int can_rmdir(struct send_ctx *sctx, u64 dir, u64 send_progress)
        struct btrfs_key loc;
        struct btrfs_dir_item *di;
 
+       /*
+        * Don't try to rmdir the top/root subvolume dir.
+        */
+       if (dir == BTRFS_FIRST_FREE_OBJECTID)
+               return 0;
+
        path = alloc_path_for_send();
        if (!path)
                return -ENOMEM;
@@ -2513,160 +2685,6 @@ out:
        return ret;
 }
 
-struct finish_unordered_dir_ctx {
-       struct send_ctx *sctx;
-       struct fs_path *cur_path;
-       struct fs_path *dir_path;
-       u64 dir_ino;
-       int need_delete;
-       int delete_pass;
-};
-
-int __finish_unordered_dir(int num, struct btrfs_key *di_key,
-                          const char *name, int name_len,
-                          const char *data, int data_len,
-                          u8 type, void *ctx)
-{
-       int ret = 0;
-       struct finish_unordered_dir_ctx *fctx = ctx;
-       struct send_ctx *sctx = fctx->sctx;
-       u64 di_gen;
-       u64 di_mode;
-       int is_orphan = 0;
-
-       if (di_key->objectid >= fctx->dir_ino)
-               goto out;
-
-       fs_path_reset(fctx->cur_path);
-
-       ret = get_inode_info(sctx->send_root, di_key->objectid,
-                       NULL, &di_gen, &di_mode, NULL, NULL);
-       if (ret < 0)
-               goto out;
-
-       ret = is_first_ref(sctx, sctx->send_root, di_key->objectid,
-                       fctx->dir_ino, name, name_len);
-       if (ret < 0)
-               goto out;
-       if (ret) {
-               is_orphan = 1;
-               ret = gen_unique_name(sctx, di_key->objectid, di_gen,
-                               fctx->cur_path);
-       } else {
-               ret = get_cur_path(sctx, di_key->objectid, di_gen,
-                               fctx->cur_path);
-       }
-       if (ret < 0)
-               goto out;
-
-       ret = fs_path_add(fctx->dir_path, name, name_len);
-       if (ret < 0)
-               goto out;
-
-       if (!fctx->delete_pass) {
-               if (S_ISDIR(di_mode)) {
-                       ret = send_rename(sctx, fctx->cur_path,
-                                       fctx->dir_path);
-               } else {
-                       ret = send_link(sctx, fctx->dir_path,
-                                       fctx->cur_path);
-                       if (is_orphan)
-                               fctx->need_delete = 1;
-               }
-       } else if (!S_ISDIR(di_mode)) {
-               ret = send_unlink(sctx, fctx->cur_path);
-       } else {
-               ret = 0;
-       }
-
-       fs_path_remove(fctx->dir_path);
-
-out:
-       return ret;
-}
-
-/*
- * Go through all dir items and see if we find refs which could not be created
- * in the past because the dir did not exist at that time.
- */
-static int finish_outoforder_dir(struct send_ctx *sctx, u64 dir, u64 dir_gen)
-{
-       int ret = 0;
-       struct btrfs_path *path = NULL;
-       struct btrfs_key key;
-       struct btrfs_key found_key;
-       struct extent_buffer *eb;
-       struct finish_unordered_dir_ctx fctx;
-       int slot;
-
-       path = alloc_path_for_send();
-       if (!path) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       memset(&fctx, 0, sizeof(fctx));
-       fctx.sctx = sctx;
-       fctx.cur_path = fs_path_alloc(sctx);
-       fctx.dir_path = fs_path_alloc(sctx);
-       if (!fctx.cur_path || !fctx.dir_path) {
-               ret = -ENOMEM;
-               goto out;
-       }
-       fctx.dir_ino = dir;
-
-       ret = get_cur_path(sctx, dir, dir_gen, fctx.dir_path);
-       if (ret < 0)
-               goto out;
-
-       /*
-        * We do two passes. The first links in the new refs and the second
-        * deletes orphans if required. Deletion of orphans is not required for
-        * directory inodes, as we always have only one ref and use rename
-        * instead of link for those.
-        */
-
-again:
-       key.objectid = dir;
-       key.type = BTRFS_DIR_ITEM_KEY;
-       key.offset = 0;
-       while (1) {
-               ret = btrfs_search_slot_for_read(sctx->send_root, &key, path,
-                               1, 0);
-               if (ret < 0)
-                       goto out;
-               eb = path->nodes[0];
-               slot = path->slots[0];
-               btrfs_item_key_to_cpu(eb, &found_key, slot);
-
-               if (found_key.objectid != key.objectid ||
-                   found_key.type != key.type) {
-                       btrfs_release_path(path);
-                       break;
-               }
-
-               ret = iterate_dir_item(sctx, sctx->send_root, path,
-                               &found_key, __finish_unordered_dir,
-                               &fctx);
-               if (ret < 0)
-                       goto out;
-
-               key.offset = found_key.offset + 1;
-               btrfs_release_path(path);
-       }
-
-       if (!fctx.delete_pass && fctx.need_delete) {
-               fctx.delete_pass = 1;
-               goto again;
-       }
-
-out:
-       btrfs_free_path(path);
-       fs_path_free(sctx, fctx.cur_path);
-       fs_path_free(sctx, fctx.dir_path);
-       return ret;
-}
-
 /*
  * This does all the move/link/unlink/rmdir magic.
  */
@@ -2674,6 +2692,7 @@ static int process_recorded_refs(struct send_ctx *sctx)
 {
        int ret = 0;
        struct recorded_ref *cur;
+       struct recorded_ref *cur2;
        struct ulist *check_dirs = NULL;
        struct ulist_iterator uit;
        struct ulist_node *un;
@@ -2685,6 +2704,12 @@ static int process_recorded_refs(struct send_ctx *sctx)
 
 verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
 
+       /*
+        * This should never happen as the root dir always has the same ref
+        * which is always '..'
+        */
+       BUG_ON(sctx->cur_ino <= BTRFS_FIRST_FREE_OBJECTID);
+
        valid_path = fs_path_alloc(sctx);
        if (!valid_path) {
                ret = -ENOMEM;
@@ -2730,6 +2755,46 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
        }
 
        list_for_each_entry(cur, &sctx->new_refs, list) {
+               /*
+                * We may have refs where the parent directory does not exist
+                * yet. This happens if the parent directories inum is higher
+                * the the current inum. To handle this case, we create the
+                * parent directory out of order. But we need to check if this
+                * did already happen before due to other refs in the same dir.
+                */
+               ret = get_cur_inode_state(sctx, cur->dir, cur->dir_gen);
+               if (ret < 0)
+                       goto out;
+               if (ret == inode_state_will_create) {
+                       ret = 0;
+                       /*
+                        * First check if any of the current inodes refs did
+                        * already create the dir.
+                        */
+                       list_for_each_entry(cur2, &sctx->new_refs, list) {
+                               if (cur == cur2)
+                                       break;
+                               if (cur2->dir == cur->dir) {
+                                       ret = 1;
+                                       break;
+                               }
+                       }
+
+                       /*
+                        * If that did not happen, check if a previous inode
+                        * did already create the dir.
+                        */
+                       if (!ret)
+                               ret = did_create_dir(sctx, cur->dir);
+                       if (ret < 0)
+                               goto out;
+                       if (!ret) {
+                               ret = send_create_inode(sctx, cur->dir);
+                               if (ret < 0)
+                                       goto out;
+                       }
+               }
+
                /*
                 * Check if this new ref would overwrite the first ref of
                 * another unprocessed inode. If yes, orphanize the
@@ -2764,7 +2829,7 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
                 * inode, move it and update valid_path. If not, link or move
                 * it depending on the inode mode.
                 */
-               if (is_orphan && !sctx->cur_inode_first_ref_orphan) {
+               if (is_orphan) {
                        ret = send_rename(sctx, valid_path, cur->full_path);
                        if (ret < 0)
                                goto out;
@@ -2827,6 +2892,17 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
                        if (ret < 0)
                                goto out;
                }
+       } else if (S_ISDIR(sctx->cur_inode_mode) &&
+                  !list_empty(&sctx->deleted_refs)) {
+               /*
+                * We have a moved dir. Add the old parent to check_dirs
+                */
+               cur = list_entry(sctx->deleted_refs.next, struct recorded_ref,
+                               list);
+               ret = ulist_add(check_dirs, cur->dir, cur->dir_gen,
+                               GFP_NOFS);
+               if (ret < 0)
+                       goto out;
        } else if (!S_ISDIR(sctx->cur_inode_mode)) {
                /*
                 * We have a non dir inode. Go through all deleted refs and
@@ -2840,35 +2916,9 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
                        if (ret < 0)
                                goto out;
                        if (!ret) {
-                               /*
-                                * In case the inode was moved to a directory
-                                * that was not created yet (see
-                                * __record_new_ref), we can not unlink the ref
-                                * as it will be needed later when the parent
-                                * directory is created, so that we can move in
-                                * the inode to the new dir.
-                                */
-                               if (!is_orphan &&
-                                   sctx->cur_inode_first_ref_orphan) {
-                                       ret = orphanize_inode(sctx,
-                                                       sctx->cur_ino,
-                                                       sctx->cur_inode_gen,
-                                                       cur->full_path);
-                                       if (ret < 0)
-                                               goto out;
-                                       ret = gen_unique_name(sctx,
-                                                       sctx->cur_ino,
-                                                       sctx->cur_inode_gen,
-                                                       valid_path);
-                                       if (ret < 0)
-                                               goto out;
-                                       is_orphan = 1;
-
-                               } else {
-                                       ret = send_unlink(sctx, cur->full_path);
-                                       if (ret < 0)
-                                               goto out;
-                               }
+                               ret = send_unlink(sctx, cur->full_path);
+                               if (ret < 0)
+                                       goto out;
                        }
                        ret = ulist_add(check_dirs, cur->dir, cur->dir_gen,
                                        GFP_NOFS);
@@ -2880,12 +2930,11 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
                 * If the inode is still orphan, unlink the orphan. This may
                 * happen when a previous inode did overwrite the first ref
                 * of this inode and no new refs were added for the current
-                * inode.
-                * We can however not delete the orphan in case the inode relies
-                * in a directory that was not created yet (see
-                * __record_new_ref)
+                * inode. Unlinking does not mean that the inode is deleted in
+                * all cases. There may still be links to this inode in other
+                * places.
                 */
-               if (is_orphan && !sctx->cur_inode_first_ref_orphan) {
+               if (is_orphan) {
                        ret = send_unlink(sctx, valid_path);
                        if (ret < 0)
                                goto out;
@@ -2900,6 +2949,11 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
         */
        ULIST_ITER_INIT(&uit);
        while ((un = ulist_next(check_dirs, &uit))) {
+               /*
+                * In case we had refs into dirs that were not processed yet,
+                * we don't need to do the utime and rmdir logic for these dirs.
+                * The dir will be processed later.
+                */
                if (un->val > sctx->cur_ino)
                        continue;
 
@@ -2929,25 +2983,6 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
                }
        }
 
-       /*
-        * Current inode is now at it's new position, so we must increase
-        * send_progress
-        */
-       sctx->send_progress = sctx->cur_ino + 1;
-
-       /*
-        * We may have a directory here that has pending refs which could not
-        * be created before (because the dir did not exist before, see
-        * __record_new_ref). finish_outoforder_dir will link/move the pending
-        * refs.
-        */
-       if (S_ISDIR(sctx->cur_inode_mode) && sctx->cur_inode_new) {
-               ret = finish_outoforder_dir(sctx, sctx->cur_ino,
-                               sctx->cur_inode_gen);
-               if (ret < 0)
-                       goto out;
-       }
-
        ret = 0;
 
 out:
@@ -2971,34 +3006,9 @@ static int __record_new_ref(int num, u64 dir, int index,
                return -ENOMEM;
 
        ret = get_inode_info(sctx->send_root, dir, NULL, &gen, NULL, NULL,
-                       NULL);
-       if (ret < 0)
-               goto out;
-
-       /*
-        * The parent may be non-existent at this point in time. This happens
-        * if the ino of the parent dir is higher then the current ino. In this
-        * case, we can not process this ref until the parent dir is finally
-        * created. If we reach the parent dir later, process_recorded_refs
-        * will go through all dir items and process the refs that could not be
-        * processed before. In case this is the first ref, we set
-        * cur_inode_first_ref_orphan to 1 to inform process_recorded_refs to
-        * keep an orphan of the inode so that it later can be used for
-        * link/move
-        */
-       ret = is_inode_existent(sctx, dir, gen);
+                       NULL, NULL);
        if (ret < 0)
                goto out;
-       if (!ret) {
-               ret = is_first_ref(sctx, sctx->send_root, sctx->cur_ino, dir,
-                               name->start, fs_path_len(name));
-               if (ret < 0)
-                       goto out;
-               if (ret)
-                       sctx->cur_inode_first_ref_orphan = 1;
-               ret = 0;
-               goto out;
-       }
 
        ret = get_cur_path(sctx, dir, gen, p);
        if (ret < 0)
@@ -3029,7 +3039,7 @@ static int __record_deleted_ref(int num, u64 dir, int index,
                return -ENOMEM;
 
        ret = get_inode_info(sctx->parent_root, dir, NULL, &gen, NULL, NULL,
-                       NULL);
+                       NULL, NULL);
        if (ret < 0)
                goto out;
 
@@ -3206,33 +3216,28 @@ static int process_all_refs(struct send_ctx *sctx,
        key.offset = 0;
        while (1) {
                ret = btrfs_search_slot_for_read(root, &key, path, 1, 0);
-               if (ret < 0) {
-                       btrfs_release_path(path);
+               if (ret < 0)
                        goto out;
-               }
-               if (ret) {
-                       btrfs_release_path(path);
+               if (ret)
                        break;
-               }
 
                eb = path->nodes[0];
                slot = path->slots[0];
                btrfs_item_key_to_cpu(eb, &found_key, slot);
 
                if (found_key.objectid != key.objectid ||
-                   found_key.type != key.type) {
-                       btrfs_release_path(path);
+                   found_key.type != key.type)
                        break;
-               }
 
-               ret = iterate_inode_ref(sctx, sctx->parent_root, path,
-                               &found_key, 0, cb, sctx);
+               ret = iterate_inode_ref(sctx, root, path, &found_key, 0, cb,
+                               sctx);
                btrfs_release_path(path);
                if (ret < 0)
                        goto out;
 
                key.offset = found_key.offset + 1;
        }
+       btrfs_release_path(path);
 
        ret = process_recorded_refs(sctx);
 
@@ -3555,7 +3560,7 @@ static int send_write(struct send_ctx *sctx, u64 offset, u32 len)
        int ret = 0;
        struct fs_path *p;
        loff_t pos = offset;
-       int readed = 0;
+       int num_read = 0;
        mm_segment_t old_fs;
 
        p = fs_path_alloc(sctx);
@@ -3580,8 +3585,8 @@ verbose_printk("btrfs: send_write offset=%llu, len=%d\n", offset, len);
        ret = vfs_read(sctx->cur_inode_filp, sctx->read_buf, len, &pos);
        if (ret < 0)
                goto out;
-       readed = ret;
-       if (!readed)
+       num_read = ret;
+       if (!num_read)
                goto out;
 
        ret = begin_cmd(sctx, BTRFS_SEND_C_WRITE);
@@ -3594,7 +3599,7 @@ verbose_printk("btrfs: send_write offset=%llu, len=%d\n", offset, len);
 
        TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p);
        TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset);
-       TLV_PUT(sctx, BTRFS_SEND_A_DATA, sctx->read_buf, readed);
+       TLV_PUT(sctx, BTRFS_SEND_A_DATA, sctx->read_buf, num_read);
 
        ret = send_cmd(sctx);
 
@@ -3604,7 +3609,7 @@ out:
        set_fs(old_fs);
        if (ret < 0)
                return ret;
-       return readed;
+       return num_read;
 }
 
 /*
@@ -3615,7 +3620,6 @@ static int send_clone(struct send_ctx *sctx,
                      struct clone_root *clone_root)
 {
        int ret = 0;
-       struct btrfs_root *clone_root2 = clone_root->root;
        struct fs_path *p;
        u64 gen;
 
@@ -3640,22 +3644,23 @@ verbose_printk("btrfs: send_clone offset=%llu, len=%d, clone_root=%llu, "
        TLV_PUT_U64(sctx, BTRFS_SEND_A_CLONE_LEN, len);
        TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p);
 
-       if (clone_root2 == sctx->send_root) {
+       if (clone_root->root == sctx->send_root) {
                ret = get_inode_info(sctx->send_root, clone_root->ino, NULL,
-                               &gen, NULL, NULL, NULL);
+                               &gen, NULL, NULL, NULL, NULL);
                if (ret < 0)
                        goto out;
                ret = get_cur_path(sctx, clone_root->ino, gen, p);
        } else {
-               ret = get_inode_path(sctx, clone_root2, clone_root->ino, p);
+               ret = get_inode_path(sctx, clone_root->root,
+                               clone_root->ino, p);
        }
        if (ret < 0)
                goto out;
 
        TLV_PUT_UUID(sctx, BTRFS_SEND_A_CLONE_UUID,
-                       clone_root2->root_item.uuid);
+                       clone_root->root->root_item.uuid);
        TLV_PUT_U64(sctx, BTRFS_SEND_A_CLONE_CTRANSID,
-                       clone_root2->root_item.ctransid);
+                       clone_root->root->root_item.ctransid);
        TLV_PUT_PATH(sctx, BTRFS_SEND_A_CLONE_PATH, p);
        TLV_PUT_U64(sctx, BTRFS_SEND_A_CLONE_OFFSET,
                        clone_root->offset);
@@ -3684,10 +3689,17 @@ static int send_write_or_clone(struct send_ctx *sctx,
        ei = btrfs_item_ptr(path->nodes[0], path->slots[0],
                        struct btrfs_file_extent_item);
        type = btrfs_file_extent_type(path->nodes[0], ei);
-       if (type == BTRFS_FILE_EXTENT_INLINE)
+       if (type == BTRFS_FILE_EXTENT_INLINE) {
                len = btrfs_file_extent_inline_len(path->nodes[0], ei);
-       else
+               /*
+                * it is possible the inline item won't cover the whole page,
+                * but there may be items after this page.  Make
+                * sure to send the whole thing
+                */
+               len = PAGE_CACHE_ALIGN(len);
+       } else {
                len = btrfs_file_extent_num_bytes(path->nodes[0], ei);
+       }
 
        if (offset + len > sctx->cur_inode_size)
                len = sctx->cur_inode_size - offset;
@@ -3735,6 +3747,8 @@ static int is_extent_unchanged(struct send_ctx *sctx,
        u64 left_offset_fixed;
        u64 left_len;
        u64 right_len;
+       u64 left_gen;
+       u64 right_gen;
        u8 left_type;
        u8 right_type;
 
@@ -3744,17 +3758,17 @@ static int is_extent_unchanged(struct send_ctx *sctx,
 
        eb = left_path->nodes[0];
        slot = left_path->slots[0];
-
        ei = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
        left_type = btrfs_file_extent_type(eb, ei);
-       left_disknr = btrfs_file_extent_disk_bytenr(eb, ei);
-       left_len = btrfs_file_extent_num_bytes(eb, ei);
-       left_offset = btrfs_file_extent_offset(eb, ei);
 
        if (left_type != BTRFS_FILE_EXTENT_REG) {
                ret = 0;
                goto out;
        }
+       left_disknr = btrfs_file_extent_disk_bytenr(eb, ei);
+       left_len = btrfs_file_extent_num_bytes(eb, ei);
+       left_offset = btrfs_file_extent_offset(eb, ei);
+       left_gen = btrfs_file_extent_generation(eb, ei);
 
        /*
         * Following comments will refer to these graphics. L is the left
@@ -3810,6 +3824,7 @@ static int is_extent_unchanged(struct send_ctx *sctx,
                right_disknr = btrfs_file_extent_disk_bytenr(eb, ei);
                right_len = btrfs_file_extent_num_bytes(eb, ei);
                right_offset = btrfs_file_extent_offset(eb, ei);
+               right_gen = btrfs_file_extent_generation(eb, ei);
 
                if (right_type != BTRFS_FILE_EXTENT_REG) {
                        ret = 0;
@@ -3820,7 +3835,7 @@ static int is_extent_unchanged(struct send_ctx *sctx,
                 * Are we at extent 8? If yes, we know the extent is changed.
                 * This may only happen on the first iteration.
                 */
-               if (found_key.offset + right_len < ekey->offset) {
+               if (found_key.offset + right_len <= ekey->offset) {
                        ret = 0;
                        goto out;
                }
@@ -3837,8 +3852,9 @@ static int is_extent_unchanged(struct send_ctx *sctx,
                /*
                 * Check if we have the same extent.
                 */
-               if (left_disknr + left_offset_fixed !=
-                               right_disknr + right_offset) {
+               if (left_disknr != right_disknr ||
+                   left_offset_fixed != right_offset ||
+                   left_gen != right_gen) {
                        ret = 0;
                        goto out;
                }
@@ -3977,6 +3993,15 @@ static int process_recorded_refs_if_needed(struct send_ctx *sctx, int at_end)
                goto out;
 
        ret = process_recorded_refs(sctx);
+       if (ret < 0)
+               goto out;
+
+       /*
+        * We have processed the refs and thus need to advance send_progress.
+        * Now, calls to get_cur_xxx will take the updated refs of the current
+        * inode into account.
+        */
+       sctx->send_progress = sctx->cur_ino + 1;
 
 out:
        return ret;
@@ -4004,7 +4029,7 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
                goto out;
 
        ret = get_inode_info(sctx->send_root, sctx->cur_ino, NULL, NULL,
-                       &left_mode, &left_uid, &left_gid);
+                       &left_mode, &left_uid, &left_gid, NULL);
        if (ret < 0)
                goto out;
 
@@ -4015,7 +4040,7 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
                } else {
                        ret = get_inode_info(sctx->parent_root, sctx->cur_ino,
                                        NULL, NULL, &right_mode, &right_uid,
-                                       &right_gid);
+                                       &right_gid, NULL);
                        if (ret < 0)
                                goto out;
 
@@ -4074,7 +4099,12 @@ static int changed_inode(struct send_ctx *sctx,
 
        sctx->cur_ino = key->objectid;
        sctx->cur_inode_new_gen = 0;
-       sctx->cur_inode_first_ref_orphan = 0;
+
+       /*
+        * Set send_progress to current inode. This will tell all get_cur_xxx
+        * functions that the current inode's refs are not updated yet. Later,
+        * when process_recorded_refs is finished, it is set to cur_ino + 1.
+        */
        sctx->send_progress = sctx->cur_ino;
 
        if (result == BTRFS_COMPARE_TREE_NEW ||
@@ -4098,7 +4128,14 @@ static int changed_inode(struct send_ctx *sctx,
 
                right_gen = btrfs_inode_generation(sctx->right_path->nodes[0],
                                right_ii);
-               if (left_gen != right_gen)
+
+               /*
+                * The cur_ino = root dir case is special here. We can't treat
+                * the inode as deleted+reused because it would generate a
+                * stream that tries to delete/mkdir the root dir.
+                */
+               if (left_gen != right_gen &&
+                   sctx->cur_ino != BTRFS_FIRST_FREE_OBJECTID)
                        sctx->cur_inode_new_gen = 1;
        }
 
@@ -4111,8 +4148,7 @@ static int changed_inode(struct send_ctx *sctx,
                sctx->cur_inode_mode = btrfs_inode_mode(
                                sctx->left_path->nodes[0], left_ii);
                if (sctx->cur_ino != BTRFS_FIRST_FREE_OBJECTID)
-                       ret = send_create_inode(sctx, sctx->left_path,
-                                       sctx->cmp_key);
+                       ret = send_create_inode_if_needed(sctx);
        } else if (result == BTRFS_COMPARE_TREE_DELETED) {
                sctx->cur_inode_gen = right_gen;
                sctx->cur_inode_new = 0;
@@ -4122,7 +4158,17 @@ static int changed_inode(struct send_ctx *sctx,
                sctx->cur_inode_mode = btrfs_inode_mode(
                                sctx->right_path->nodes[0], right_ii);
        } else if (result == BTRFS_COMPARE_TREE_CHANGED) {
+               /*
+                * We need to do some special handling in case the inode was
+                * reported as changed with a changed generation number. This
+                * means that the original inode was deleted and new inode
+                * reused the same inum. So we have to treat the old inode as
+                * deleted and the new one as new.
+                */
                if (sctx->cur_inode_new_gen) {
+                       /*
+                        * First, process the inode as if it was deleted.
+                        */
                        sctx->cur_inode_gen = right_gen;
                        sctx->cur_inode_new = 0;
                        sctx->cur_inode_deleted = 1;
@@ -4135,6 +4181,9 @@ static int changed_inode(struct send_ctx *sctx,
                        if (ret < 0)
                                goto out;
 
+                       /*
+                        * Now process the inode as if it was new.
+                        */
                        sctx->cur_inode_gen = left_gen;
                        sctx->cur_inode_new = 1;
                        sctx->cur_inode_deleted = 0;
@@ -4142,14 +4191,23 @@ static int changed_inode(struct send_ctx *sctx,
                                        sctx->left_path->nodes[0], left_ii);
                        sctx->cur_inode_mode = btrfs_inode_mode(
                                        sctx->left_path->nodes[0], left_ii);
-                       ret = send_create_inode(sctx, sctx->left_path,
-                                       sctx->cmp_key);
+                       ret = send_create_inode_if_needed(sctx);
                        if (ret < 0)
                                goto out;
 
                        ret = process_all_refs(sctx, BTRFS_COMPARE_TREE_NEW);
                        if (ret < 0)
                                goto out;
+                       /*
+                        * Advance send_progress now as we did not get into
+                        * process_recorded_refs_if_needed in the new_gen case.
+                        */
+                       sctx->send_progress = sctx->cur_ino + 1;
+
+                       /*
+                        * Now process all extents and xattrs of the inode as if
+                        * they were all new.
+                        */
                        ret = process_all_extents(sctx);
                        if (ret < 0)
                                goto out;
@@ -4172,6 +4230,16 @@ out:
        return ret;
 }
 
+/*
+ * We have to process new refs before deleted refs, but compare_trees gives us
+ * the new and deleted refs mixed. To fix this, we record the new/deleted refs
+ * first and later process them in process_recorded_refs.
+ * For the cur_inode_new_gen case, we skip recording completely because
+ * changed_inode did already initiate processing of refs. The reason for this is
+ * that in this case, compare_tree actually compares the refs of 2 different
+ * inodes. To fix this, process_all_refs is used in changed_inode to handle all
+ * refs of the right tree as deleted and all refs of the left tree as new.
+ */
 static int changed_ref(struct send_ctx *sctx,
                       enum btrfs_compare_tree_result result)
 {
@@ -4192,6 +4260,11 @@ static int changed_ref(struct send_ctx *sctx,
        return ret;
 }
 
+/*
+ * Process new/deleted/changed xattrs. We skip processing in the
+ * cur_inode_new_gen case because changed_inode did already initiate processing
+ * of xattrs. The reason is the same as in changed_ref
+ */
 static int changed_xattr(struct send_ctx *sctx,
                         enum btrfs_compare_tree_result result)
 {
@@ -4211,6 +4284,11 @@ static int changed_xattr(struct send_ctx *sctx,
        return ret;
 }
 
+/*
+ * Process new/deleted/changed extents. We skip processing in the
+ * cur_inode_new_gen case because changed_inode did already initiate processing
+ * of extents. The reason is the same as in changed_ref
+ */
 static int changed_extent(struct send_ctx *sctx,
                          enum btrfs_compare_tree_result result)
 {
@@ -4227,7 +4305,10 @@ static int changed_extent(struct send_ctx *sctx,
        return ret;
 }
 
-
+/*
+ * Updates compare related fields in sctx and simply forwards to the actual
+ * changed_xxx functions.
+ */
 static int changed_cb(struct btrfs_root *left_root,
                      struct btrfs_root *right_root,
                      struct btrfs_path *left_path,
@@ -4247,6 +4328,11 @@ static int changed_cb(struct btrfs_root *left_root,
        if (ret < 0)
                goto out;
 
+       /* Ignore non-FS objects */
+       if (key->objectid == BTRFS_FREE_INO_OBJECTID ||
+           key->objectid == BTRFS_FREE_SPACE_OBJECTID)
+               goto out;
+
        if (key->type == BTRFS_INODE_ITEM_KEY)
                ret = changed_inode(sctx, result);
        else if (key->type == BTRFS_INODE_REF_KEY)
@@ -4299,7 +4385,8 @@ join_trans:
        }
 
        /*
-        * Make sure the tree has not changed
+        * Make sure the tree has not changed after re-joining. We detect this
+        * by comparing start_ctransid and ctransid. They should always match.
         */
        spin_lock(&send_root->root_times_lock);
        ctransid = btrfs_root_ctransid(&send_root->root_item);
index 9934e948e57f91067f5a5e3f9cdf9720939af151..1bf4f32fd4ef28582c6d2401571bf2f7f37617a6 100644 (file)
@@ -130,4 +130,5 @@ enum {
 
 #ifdef __KERNEL__
 long btrfs_ioctl_send(struct file *mnt_file, void __user *arg);
+int write_buf(struct file *filp, const void *buf, u32 len, loff_t *off);
 #endif
index 83d6f9f9c2209861efdec86dec9ad54d629deeb9..915ac14c20642ec619ec159d90d0fbed2a02b0da 100644 (file)
@@ -243,12 +243,18 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
                               struct btrfs_root *root, const char *function,
                               unsigned int line, int errno)
 {
-       WARN_ONCE(1, KERN_DEBUG "btrfs: Transaction aborted");
+       WARN_ONCE(1, KERN_DEBUG "btrfs: Transaction aborted\n");
        trans->aborted = errno;
        /* Nothing used. The other threads that have joined this
         * transaction may be able to continue. */
        if (!trans->blocks_used) {
-               btrfs_printk(root->fs_info, "Aborting unused transaction.\n");
+               char nbuf[16];
+               const char *errstr;
+
+               errstr = btrfs_decode_error(root->fs_info, errno, nbuf);
+               btrfs_printk(root->fs_info,
+                            "%s:%d: Aborting unused transaction(%s).\n",
+                            function, line, errstr);
                return;
        }
        trans->transaction->aborted = errno;
@@ -407,7 +413,15 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                        btrfs_set_opt(info->mount_opt, NODATASUM);
                        break;
                case Opt_nodatacow:
-                       printk(KERN_INFO "btrfs: setting nodatacow\n");
+                       if (!btrfs_test_opt(root, COMPRESS) ||
+                               !btrfs_test_opt(root, FORCE_COMPRESS)) {
+                                       printk(KERN_INFO "btrfs: setting nodatacow, compression disabled\n");
+                       } else {
+                               printk(KERN_INFO "btrfs: setting nodatacow\n");
+                       }
+                       info->compress_type = BTRFS_COMPRESS_NONE;
+                       btrfs_clear_opt(info->mount_opt, COMPRESS);
+                       btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
                        btrfs_set_opt(info->mount_opt, NODATACOW);
                        btrfs_set_opt(info->mount_opt, NODATASUM);
                        break;
@@ -422,10 +436,14 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                                compress_type = "zlib";
                                info->compress_type = BTRFS_COMPRESS_ZLIB;
                                btrfs_set_opt(info->mount_opt, COMPRESS);
+                               btrfs_clear_opt(info->mount_opt, NODATACOW);
+                               btrfs_clear_opt(info->mount_opt, NODATASUM);
                        } else if (strcmp(args[0].from, "lzo") == 0) {
                                compress_type = "lzo";
                                info->compress_type = BTRFS_COMPRESS_LZO;
                                btrfs_set_opt(info->mount_opt, COMPRESS);
+                               btrfs_clear_opt(info->mount_opt, NODATACOW);
+                               btrfs_clear_opt(info->mount_opt, NODATASUM);
                                btrfs_set_fs_incompat(info, COMPRESS_LZO);
                        } else if (strncmp(args[0].from, "no", 2) == 0) {
                                compress_type = "no";
@@ -543,11 +561,11 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                        btrfs_set_opt(info->mount_opt, ENOSPC_DEBUG);
                        break;
                case Opt_defrag:
-                       printk(KERN_INFO "btrfs: enabling auto defrag");
+                       printk(KERN_INFO "btrfs: enabling auto defrag\n");
                        btrfs_set_opt(info->mount_opt, AUTO_DEFRAG);
                        break;
                case Opt_recovery:
-                       printk(KERN_INFO "btrfs: enabling auto recovery");
+                       printk(KERN_INFO "btrfs: enabling auto recovery\n");
                        btrfs_set_opt(info->mount_opt, RECOVERY);
                        break;
                case Opt_skip_balance:
@@ -846,18 +864,15 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
                return 0;
        }
 
-       btrfs_wait_ordered_extents(root, 0, 0);
-
-       spin_lock(&fs_info->trans_lock);
-       if (!fs_info->running_transaction) {
-               spin_unlock(&fs_info->trans_lock);
-               return 0;
-       }
-       spin_unlock(&fs_info->trans_lock);
+       btrfs_wait_ordered_extents(root, 0);
 
-       trans = btrfs_join_transaction(root);
-       if (IS_ERR(trans))
+       trans = btrfs_attach_transaction(root);
+       if (IS_ERR(trans)) {
+               /* no transaction, don't bother */
+               if (PTR_ERR(trans) == -ENOENT)
+                       return 0;
                return PTR_ERR(trans);
+       }
        return btrfs_commit_transaction(trans, root);
 }
 
@@ -1508,17 +1523,21 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
 
 static int btrfs_freeze(struct super_block *sb)
 {
-       struct btrfs_fs_info *fs_info = btrfs_sb(sb);
-       mutex_lock(&fs_info->transaction_kthread_mutex);
-       mutex_lock(&fs_info->cleaner_mutex);
-       return 0;
+       struct btrfs_trans_handle *trans;
+       struct btrfs_root *root = btrfs_sb(sb)->tree_root;
+
+       trans = btrfs_attach_transaction(root);
+       if (IS_ERR(trans)) {
+               /* no transaction, don't bother */
+               if (PTR_ERR(trans) == -ENOENT)
+                       return 0;
+               return PTR_ERR(trans);
+       }
+       return btrfs_commit_transaction(trans, root);
 }
 
 static int btrfs_unfreeze(struct super_block *sb)
 {
-       struct btrfs_fs_info *fs_info = btrfs_sb(sb);
-       mutex_unlock(&fs_info->cleaner_mutex);
-       mutex_unlock(&fs_info->transaction_kthread_mutex);
        return 0;
 }
 
@@ -1595,7 +1614,7 @@ static int btrfs_interface_init(void)
 static void btrfs_interface_exit(void)
 {
        if (misc_deregister(&btrfs_misc) < 0)
-               printk(KERN_INFO "misc_deregister failed for control device");
+               printk(KERN_INFO "btrfs: misc_deregister failed for control device\n");
 }
 
 static int __init init_btrfs_fs(void)
@@ -1620,10 +1639,14 @@ static int __init init_btrfs_fs(void)
        if (err)
                goto free_extent_io;
 
-       err = btrfs_delayed_inode_init();
+       err = ordered_data_init();
        if (err)
                goto free_extent_map;
 
+       err = btrfs_delayed_inode_init();
+       if (err)
+               goto free_ordered_data;
+
        err = btrfs_interface_init();
        if (err)
                goto free_delayed_inode;
@@ -1641,6 +1664,8 @@ unregister_ioctl:
        btrfs_interface_exit();
 free_delayed_inode:
        btrfs_delayed_inode_exit();
+free_ordered_data:
+       ordered_data_exit();
 free_extent_map:
        extent_map_exit();
 free_extent_io:
@@ -1657,6 +1682,7 @@ static void __exit exit_btrfs_fs(void)
 {
        btrfs_destroy_cachep();
        btrfs_delayed_inode_exit();
+       ordered_data_exit();
        extent_map_exit();
        extent_io_exit();
        btrfs_interface_exit();
index 27c26004e050a33211674363cfd80c02c98d1063..77db875b511638b7ff94854c6b1482942da2b3fb 100644 (file)
@@ -53,7 +53,7 @@ static noinline void switch_commit_root(struct btrfs_root *root)
 /*
  * either allocate a new transaction or hop into the existing one
  */
-static noinline int join_transaction(struct btrfs_root *root, int nofail)
+static noinline int join_transaction(struct btrfs_root *root, int type)
 {
        struct btrfs_transaction *cur_trans;
        struct btrfs_fs_info *fs_info = root->fs_info;
@@ -67,7 +67,13 @@ loop:
        }
 
        if (fs_info->trans_no_join) {
-               if (!nofail) {
+               /* 
+                * If we are JOIN_NOLOCK we're already committing a current
+                * transaction, we just need a handle to deal with something
+                * when committing the transaction, such as inode cache and
+                * space cache. It is a special case.
+                */
+               if (type != TRANS_JOIN_NOLOCK) {
                        spin_unlock(&fs_info->trans_lock);
                        return -EBUSY;
                }
@@ -87,6 +93,13 @@ loop:
        }
        spin_unlock(&fs_info->trans_lock);
 
+       /*
+        * If we are ATTACH, we just want to catch the current transaction,
+        * and commit it. If there is no transaction, just return ENOENT.
+        */
+       if (type == TRANS_ATTACH)
+               return -ENOENT;
+
        cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, GFP_NOFS);
        if (!cur_trans)
                return -ENOMEM;
@@ -267,13 +280,6 @@ static void wait_current_trans(struct btrfs_root *root)
        }
 }
 
-enum btrfs_trans_type {
-       TRANS_START,
-       TRANS_JOIN,
-       TRANS_USERSPACE,
-       TRANS_JOIN_NOLOCK,
-};
-
 static int may_wait_transaction(struct btrfs_root *root, int type)
 {
        if (root->fs_info->log_root_recovering)
@@ -290,7 +296,8 @@ static int may_wait_transaction(struct btrfs_root *root, int type)
 }
 
 static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
-                                                   u64 num_items, int type)
+                                                   u64 num_items, int type,
+                                                   int noflush)
 {
        struct btrfs_trans_handle *h;
        struct btrfs_transaction *cur_trans;
@@ -324,9 +331,14 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
                }
 
                num_bytes = btrfs_calc_trans_metadata_size(root, num_items);
-               ret = btrfs_block_rsv_add(root,
-                                         &root->fs_info->trans_block_rsv,
-                                         num_bytes);
+               if (noflush)
+                       ret = btrfs_block_rsv_add_noflush(root,
+                                               &root->fs_info->trans_block_rsv,
+                                               num_bytes);
+               else
+                       ret = btrfs_block_rsv_add(root,
+                                               &root->fs_info->trans_block_rsv,
+                                               num_bytes);
                if (ret)
                        return ERR_PTR(ret);
        }
@@ -335,19 +347,34 @@ again:
        if (!h)
                return ERR_PTR(-ENOMEM);
 
-       sb_start_intwrite(root->fs_info->sb);
+       /*
+        * If we are JOIN_NOLOCK we're already committing a transaction and
+        * waiting on this guy, so we don't need to do the sb_start_intwrite
+        * because we're already holding a ref.  We need this because we could
+        * have raced in and did an fsync() on a file which can kick a commit
+        * and then we deadlock with somebody doing a freeze.
+        *
+        * If we are ATTACH, it means we just want to catch the current
+        * transaction and commit it, so we needn't do sb_start_intwrite(). 
+        */
+       if (type < TRANS_JOIN_NOLOCK)
+               sb_start_intwrite(root->fs_info->sb);
 
        if (may_wait_transaction(root, type))
                wait_current_trans(root);
 
        do {
-               ret = join_transaction(root, type == TRANS_JOIN_NOLOCK);
+               ret = join_transaction(root, type);
                if (ret == -EBUSY)
                        wait_current_trans(root);
        } while (ret == -EBUSY);
 
        if (ret < 0) {
-               sb_end_intwrite(root->fs_info->sb);
+               /* We must get the transaction if we are JOIN_NOLOCK. */
+               BUG_ON(type == TRANS_JOIN_NOLOCK);
+
+               if (type < TRANS_JOIN_NOLOCK)
+                       sb_end_intwrite(root->fs_info->sb);
                kmem_cache_free(btrfs_trans_handle_cachep, h);
                return ERR_PTR(ret);
        }
@@ -367,7 +394,9 @@ again:
        h->aborted = 0;
        h->qgroup_reserved = qgroup_reserved;
        h->delayed_ref_elem.seq = 0;
+       h->type = type;
        INIT_LIST_HEAD(&h->qgroup_ref_list);
+       INIT_LIST_HEAD(&h->new_bgs);
 
        smp_mb();
        if (cur_trans->blocked && may_wait_transaction(root, type)) {
@@ -393,21 +422,33 @@ got_it:
 struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
                                                   int num_items)
 {
-       return start_transaction(root, num_items, TRANS_START);
+       return start_transaction(root, num_items, TRANS_START, 0);
+}
+
+struct btrfs_trans_handle *btrfs_start_transaction_noflush(
+                                       struct btrfs_root *root, int num_items)
+{
+       return start_transaction(root, num_items, TRANS_START, 1);
 }
+
 struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root)
 {
-       return start_transaction(root, 0, TRANS_JOIN);
+       return start_transaction(root, 0, TRANS_JOIN, 0);
 }
 
 struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root)
 {
-       return start_transaction(root, 0, TRANS_JOIN_NOLOCK);
+       return start_transaction(root, 0, TRANS_JOIN_NOLOCK, 0);
 }
 
 struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root)
 {
-       return start_transaction(root, 0, TRANS_USERSPACE);
+       return start_transaction(root, 0, TRANS_USERSPACE, 0);
+}
+
+struct btrfs_trans_handle *btrfs_attach_transaction(struct btrfs_root *root)
+{
+       return start_transaction(root, 0, TRANS_ATTACH, 0);
 }
 
 /* wait for a transaction commit to be fully complete */
@@ -506,11 +547,12 @@ int btrfs_should_end_transaction(struct btrfs_trans_handle *trans,
 }
 
 static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
-                         struct btrfs_root *root, int throttle, int lock)
+                         struct btrfs_root *root, int throttle)
 {
        struct btrfs_transaction *cur_trans = trans->transaction;
        struct btrfs_fs_info *info = root->fs_info;
        int count = 0;
+       int lock = (trans->type != TRANS_JOIN_NOLOCK);
        int err = 0;
 
        if (--trans->use_count) {
@@ -536,6 +578,9 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
                trans->qgroup_reserved = 0;
        }
 
+       if (!list_empty(&trans->new_bgs))
+               btrfs_create_pending_block_groups(trans, root);
+
        while (count < 2) {
                unsigned long cur = trans->delayed_ref_updates;
                trans->delayed_ref_updates = 0;
@@ -551,7 +596,8 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
        btrfs_trans_release_metadata(trans, root);
        trans->block_rsv = NULL;
 
-       sb_end_intwrite(root->fs_info->sb);
+       if (!list_empty(&trans->new_bgs))
+               btrfs_create_pending_block_groups(trans, root);
 
        if (lock && !atomic_read(&root->fs_info->open_ioctl_trans) &&
            should_end_transaction(trans, root)) {
@@ -573,6 +619,9 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
                }
        }
 
+       if (trans->type < TRANS_JOIN_NOLOCK)
+               sb_end_intwrite(root->fs_info->sb);
+
        WARN_ON(cur_trans != info->running_transaction);
        WARN_ON(atomic_read(&cur_trans->num_writers) < 1);
        atomic_dec(&cur_trans->num_writers);
@@ -604,7 +653,7 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans,
 {
        int ret;
 
-       ret = __btrfs_end_transaction(trans, root, 0, 1);
+       ret = __btrfs_end_transaction(trans, root, 0);
        if (ret)
                return ret;
        return 0;
@@ -615,18 +664,7 @@ int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans,
 {
        int ret;
 
-       ret = __btrfs_end_transaction(trans, root, 1, 1);
-       if (ret)
-               return ret;
-       return 0;
-}
-
-int btrfs_end_transaction_nolock(struct btrfs_trans_handle *trans,
-                                struct btrfs_root *root)
-{
-       int ret;
-
-       ret = __btrfs_end_transaction(trans, root, 0, 0);
+       ret = __btrfs_end_transaction(trans, root, 1);
        if (ret)
                return ret;
        return 0;
@@ -635,7 +673,7 @@ int btrfs_end_transaction_nolock(struct btrfs_trans_handle *trans,
 int btrfs_end_transaction_dmeta(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root)
 {
-       return __btrfs_end_transaction(trans, root, 1, 1);
+       return __btrfs_end_transaction(trans, root, 1);
 }
 
 /*
@@ -649,13 +687,15 @@ int btrfs_write_marked_extents(struct btrfs_root *root,
        int err = 0;
        int werr = 0;
        struct address_space *mapping = root->fs_info->btree_inode->i_mapping;
+       struct extent_state *cached_state = NULL;
        u64 start = 0;
        u64 end;
 
        while (!find_first_extent_bit(dirty_pages, start, &start, &end,
-                                     mark)) {
-               convert_extent_bit(dirty_pages, start, end, EXTENT_NEED_WAIT, mark,
-                                  GFP_NOFS);
+                                     mark, &cached_state)) {
+               convert_extent_bit(dirty_pages, start, end, EXTENT_NEED_WAIT,
+                                  mark, &cached_state, GFP_NOFS);
+               cached_state = NULL;
                err = filemap_fdatawrite_range(mapping, start, end);
                if (err)
                        werr = err;
@@ -679,12 +719,14 @@ int btrfs_wait_marked_extents(struct btrfs_root *root,
        int err = 0;
        int werr = 0;
        struct address_space *mapping = root->fs_info->btree_inode->i_mapping;
+       struct extent_state *cached_state = NULL;
        u64 start = 0;
        u64 end;
 
        while (!find_first_extent_bit(dirty_pages, start, &start, &end,
-                                     EXTENT_NEED_WAIT)) {
-               clear_extent_bits(dirty_pages, start, end, EXTENT_NEED_WAIT, GFP_NOFS);
+                                     EXTENT_NEED_WAIT, &cached_state)) {
+               clear_extent_bit(dirty_pages, start, end, EXTENT_NEED_WAIT,
+                                0, 0, &cached_state, GFP_NOFS);
                err = filemap_fdatawait_range(mapping, start, end);
                if (err)
                        werr = err;
@@ -955,6 +997,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        struct btrfs_root *parent_root;
        struct btrfs_block_rsv *rsv;
        struct inode *parent_inode;
+       struct btrfs_path *path;
+       struct btrfs_dir_item *dir_item;
        struct dentry *parent;
        struct dentry *dentry;
        struct extent_buffer *tmp;
@@ -967,18 +1011,22 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        u64 root_flags;
        uuid_le new_uuid;
 
-       rsv = trans->block_rsv;
+       path = btrfs_alloc_path();
+       if (!path) {
+               ret = pending->error = -ENOMEM;
+               goto path_alloc_fail;
+       }
 
        new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);
        if (!new_root_item) {
                ret = pending->error = -ENOMEM;
-               goto fail;
+               goto root_item_alloc_fail;
        }
 
        ret = btrfs_find_free_objectid(tree_root, &objectid);
        if (ret) {
                pending->error = ret;
-               goto fail;
+               goto no_free_objectid;
        }
 
        btrfs_reloc_pre_snapshot(trans, pending, &to_reserve);
@@ -988,22 +1036,22 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
                                                  to_reserve);
                if (ret) {
                        pending->error = ret;
-                       goto fail;
+                       goto no_free_objectid;
                }
        }
 
        ret = btrfs_qgroup_inherit(trans, fs_info, root->root_key.objectid,
                                   objectid, pending->inherit);
-       kfree(pending->inherit);
        if (ret) {
                pending->error = ret;
-               goto fail;
+               goto no_free_objectid;
        }
 
        key.objectid = objectid;
        key.offset = (u64)-1;
        key.type = BTRFS_ROOT_ITEM_KEY;
 
+       rsv = trans->block_rsv;
        trans->block_rsv = &pending->block_rsv;
 
        dentry = pending->dentry;
@@ -1017,24 +1065,21 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
         */
        ret = btrfs_set_inode_index(parent_inode, &index);
        BUG_ON(ret); /* -ENOMEM */
-       ret = btrfs_insert_dir_item(trans, parent_root,
-                               dentry->d_name.name, dentry->d_name.len,
-                               parent_inode, &key,
-                               BTRFS_FT_DIR, index);
-       if (ret == -EEXIST) {
+
+       /* check if there is a file/dir which has the same name. */
+       dir_item = btrfs_lookup_dir_item(NULL, parent_root, path,
+                                        btrfs_ino(parent_inode),
+                                        dentry->d_name.name,
+                                        dentry->d_name.len, 0);
+       if (dir_item != NULL && !IS_ERR(dir_item)) {
                pending->error = -EEXIST;
-               dput(parent);
                goto fail;
-       } else if (ret) {
-               goto abort_trans_dput;
+       } else if (IS_ERR(dir_item)) {
+               ret = PTR_ERR(dir_item);
+               btrfs_abort_transaction(trans, root, ret);
+               goto fail;
        }
-
-       btrfs_i_size_write(parent_inode, parent_inode->i_size +
-                                        dentry->d_name.len * 2);
-       parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
-       ret = btrfs_update_inode(trans, parent_root, parent_inode);
-       if (ret)
-               goto abort_trans_dput;
+       btrfs_release_path(path);
 
        /*
         * pull in the delayed directory update
@@ -1043,8 +1088,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
         * snapshot
         */
        ret = btrfs_run_delayed_items(trans, root);
-       if (ret) { /* Transaction aborted */
-               dput(parent);
+       if (ret) {      /* Transaction aborted */
+               btrfs_abort_transaction(trans, root, ret);
                goto fail;
        }
 
@@ -1079,7 +1124,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        if (ret) {
                btrfs_tree_unlock(old);
                free_extent_buffer(old);
-               goto abort_trans_dput;
+               btrfs_abort_transaction(trans, root, ret);
+               goto fail;
        }
 
        btrfs_set_lock_blocking(old);
@@ -1088,8 +1134,10 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        /* clean up in any case */
        btrfs_tree_unlock(old);
        free_extent_buffer(old);
-       if (ret)
-               goto abort_trans_dput;
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto fail;
+       }
 
        /* see comments in should_cow_block() */
        root->force_cow = 1;
@@ -1101,8 +1149,10 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        ret = btrfs_insert_root(trans, tree_root, &key, new_root_item);
        btrfs_tree_unlock(tmp);
        free_extent_buffer(tmp);
-       if (ret)
-               goto abort_trans_dput;
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto fail;
+       }
 
        /*
         * insert root back/forward references
@@ -1111,32 +1161,58 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
                                 parent_root->root_key.objectid,
                                 btrfs_ino(parent_inode), index,
                                 dentry->d_name.name, dentry->d_name.len);
-       dput(parent);
-       if (ret)
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
                goto fail;
+       }
 
        key.offset = (u64)-1;
        pending->snap = btrfs_read_fs_root_no_name(root->fs_info, &key);
        if (IS_ERR(pending->snap)) {
                ret = PTR_ERR(pending->snap);
-               goto abort_trans;
+               btrfs_abort_transaction(trans, root, ret);
+               goto fail;
        }
 
        ret = btrfs_reloc_post_snapshot(trans, pending);
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto fail;
+       }
+
+       ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto fail;
+       }
+
+       ret = btrfs_insert_dir_item(trans, parent_root,
+                                   dentry->d_name.name, dentry->d_name.len,
+                                   parent_inode, &key,
+                                   BTRFS_FT_DIR, index);
+       /* We have check then name at the beginning, so it is impossible. */
+       BUG_ON(ret == -EEXIST);
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto fail;
+       }
+
+       btrfs_i_size_write(parent_inode, parent_inode->i_size +
+                                        dentry->d_name.len * 2);
+       parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
+       ret = btrfs_update_inode(trans, parent_root, parent_inode);
        if (ret)
-               goto abort_trans;
-       ret = 0;
+               btrfs_abort_transaction(trans, root, ret);
 fail:
-       kfree(new_root_item);
+       dput(parent);
        trans->block_rsv = rsv;
+no_free_objectid:
+       kfree(new_root_item);
+root_item_alloc_fail:
+       btrfs_free_path(path);
+path_alloc_fail:
        btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1);
        return ret;
-
-abort_trans_dput:
-       dput(parent);
-abort_trans:
-       btrfs_abort_transaction(trans, root, ret);
-       goto fail;
 }
 
 /*
@@ -1229,6 +1305,16 @@ static void do_async_commit(struct work_struct *work)
        struct btrfs_async_commit *ac =
                container_of(work, struct btrfs_async_commit, work.work);
 
+       /*
+        * We've got freeze protection passed with the transaction.
+        * Tell lockdep about it.
+        */
+       rwsem_acquire_read(
+               &ac->root->fs_info->sb->s_writers.lock_map[SB_FREEZE_FS-1],
+               0, 1, _THIS_IP_);
+
+       current->journal_info = ac->newtrans;
+
        btrfs_commit_transaction(ac->newtrans, ac->root);
        kfree(ac);
 }
@@ -1258,6 +1344,14 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans,
        atomic_inc(&cur_trans->use_count);
 
        btrfs_end_transaction(trans, root);
+
+       /*
+        * Tell lockdep we've released the freeze rwsem, since the
+        * async commit thread will be the one to unlock it.
+        */
+       rwsem_release(&root->fs_info->sb->s_writers.lock_map[SB_FREEZE_FS-1],
+                     1, _THIS_IP_);
+
        schedule_delayed_work(&ac->work, 0);
 
        /* wait for transaction to start and unblock */
@@ -1348,6 +1442,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
         */
        cur_trans->delayed_refs.flushing = 1;
 
+       if (!list_empty(&trans->new_bgs))
+               btrfs_create_pending_block_groups(trans, root);
+
        ret = btrfs_run_delayed_refs(trans, root, 0);
        if (ret)
                goto cleanup_transaction;
@@ -1403,7 +1500,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 
                if (flush_on_commit || snap_pending) {
                        btrfs_start_delalloc_inodes(root, 1);
-                       btrfs_wait_ordered_extents(root, 0, 1);
+                       btrfs_wait_ordered_extents(root, 1);
                }
 
                ret = btrfs_run_delayed_items(trans, root);
@@ -1456,13 +1553,28 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
         */
        mutex_lock(&root->fs_info->reloc_mutex);
 
-       ret = btrfs_run_delayed_items(trans, root);
+       /*
+        * We needn't worry about the delayed items because we will
+        * deal with them in create_pending_snapshot(), which is the
+        * core function of the snapshot creation.
+        */
+       ret = create_pending_snapshots(trans, root->fs_info);
        if (ret) {
                mutex_unlock(&root->fs_info->reloc_mutex);
                goto cleanup_transaction;
        }
 
-       ret = create_pending_snapshots(trans, root->fs_info);
+       /*
+        * We insert the dir indexes of the snapshots and update the inode
+        * of the snapshots' parents after the snapshot creation, so there
+        * are some delayed items which are not dealt with. Now deal with
+        * them.
+        *
+        * We needn't worry that this operation will corrupt the snapshots,
+        * because all the tree which are snapshoted will be forced to COW
+        * the nodes and leaves.
+        */
+       ret = btrfs_run_delayed_items(trans, root);
        if (ret) {
                mutex_unlock(&root->fs_info->reloc_mutex);
                goto cleanup_transaction;
@@ -1584,7 +1696,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
        put_transaction(cur_trans);
        put_transaction(cur_trans);
 
-       sb_end_intwrite(root->fs_info->sb);
+       if (trans->type < TRANS_JOIN_NOLOCK)
+               sb_end_intwrite(root->fs_info->sb);
 
        trace_btrfs_transaction_commit(root);
 
index e8b8416c688b2a7b5d6c4f79c844bb07953cb3b5..80961947a6b27df59273f080f9f19316c8d98ffc 100644 (file)
@@ -47,6 +47,14 @@ struct btrfs_transaction {
        int aborted;
 };
 
+enum btrfs_trans_type {
+       TRANS_START,
+       TRANS_JOIN,
+       TRANS_USERSPACE,
+       TRANS_JOIN_NOLOCK,
+       TRANS_ATTACH,
+};
+
 struct btrfs_trans_handle {
        u64 transid;
        u64 bytes_reserved;
@@ -58,8 +66,9 @@ struct btrfs_trans_handle {
        struct btrfs_transaction *transaction;
        struct btrfs_block_rsv *block_rsv;
        struct btrfs_block_rsv *orig_rsv;
-       int aborted;
-       int adding_csums;
+       short aborted;
+       short adding_csums;
+       enum btrfs_trans_type type;
        /*
         * this root is only needed to validate that the root passed to
         * start_transaction is the same as the one passed to end_transaction.
@@ -68,6 +77,7 @@ struct btrfs_trans_handle {
        struct btrfs_root *root;
        struct seq_list delayed_ref_elem;
        struct list_head qgroup_ref_list;
+       struct list_head new_bgs;
 };
 
 struct btrfs_pending_snapshot {
@@ -88,16 +98,18 @@ static inline void btrfs_set_inode_last_trans(struct btrfs_trans_handle *trans,
 {
        BTRFS_I(inode)->last_trans = trans->transaction->transid;
        BTRFS_I(inode)->last_sub_trans = BTRFS_I(inode)->root->log_transid;
+       BTRFS_I(inode)->last_log_commit = BTRFS_I(inode)->root->last_log_commit;
 }
 
 int btrfs_end_transaction(struct btrfs_trans_handle *trans,
                          struct btrfs_root *root);
-int btrfs_end_transaction_nolock(struct btrfs_trans_handle *trans,
-                                struct btrfs_root *root);
 struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
                                                   int num_items);
+struct btrfs_trans_handle *btrfs_start_transaction_noflush(
+                                       struct btrfs_root *root, int num_items);
 struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root);
 struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root);
+struct btrfs_trans_handle *btrfs_attach_transaction(struct btrfs_root *root);
 struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root);
 int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid);
 int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
index c86670f4f2855ef3ee2f8252c54d5bd4c37f1ec6..e9ebb472b28ba6d5bb9e077e8b1a2f877797adb0 100644 (file)
 
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/list_sort.h>
 #include "ctree.h"
 #include "transaction.h"
 #include "disk-io.h"
 #include "locking.h"
 #include "print-tree.h"
+#include "backref.h"
 #include "compat.h"
 #include "tree-log.h"
+#include "hash.h"
 
 /* magic values for the inode_only field in btrfs_log_inode:
  *
@@ -146,7 +149,7 @@ static int start_log_trans(struct btrfs_trans_handle *trans,
                        root->log_multiple_pids = true;
                }
 
-               root->log_batch++;
+               atomic_inc(&root->log_batch);
                atomic_inc(&root->log_writers);
                mutex_unlock(&root->log_mutex);
                return 0;
@@ -165,7 +168,7 @@ static int start_log_trans(struct btrfs_trans_handle *trans,
                        err = ret;
        }
        mutex_unlock(&root->fs_info->tree_log_mutex);
-       root->log_batch++;
+       atomic_inc(&root->log_batch);
        atomic_inc(&root->log_writers);
        mutex_unlock(&root->log_mutex);
        return err;
@@ -484,7 +487,6 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
        int found_type;
        u64 mask = root->sectorsize - 1;
        u64 extent_end;
-       u64 alloc_hint;
        u64 start = key->offset;
        u64 saved_nbytes;
        struct btrfs_file_extent_item *item;
@@ -550,8 +552,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
 
        saved_nbytes = inode_get_bytes(inode);
        /* drop any overlapping extents */
-       ret = btrfs_drop_extents(trans, inode, start, extent_end,
-                                &alloc_hint, 1);
+       ret = btrfs_drop_extents(trans, root, inode, start, extent_end, 1);
        BUG_ON(ret);
 
        if (found_type == BTRFS_FILE_EXTENT_REG ||
@@ -744,6 +745,7 @@ out:
  */
 static noinline int backref_in_log(struct btrfs_root *log,
                                   struct btrfs_key *key,
+                                  u64 ref_objectid,
                                   char *name, int namelen)
 {
        struct btrfs_path *path;
@@ -764,8 +766,17 @@ static noinline int backref_in_log(struct btrfs_root *log,
        if (ret != 0)
                goto out;
 
-       item_size = btrfs_item_size_nr(path->nodes[0], path->slots[0]);
        ptr = btrfs_item_ptr_offset(path->nodes[0], path->slots[0]);
+
+       if (key->type == BTRFS_INODE_EXTREF_KEY) {
+               if (btrfs_find_name_in_ext_backref(path, ref_objectid,
+                                                  name, namelen, NULL))
+                       match = 1;
+
+               goto out;
+       }
+
+       item_size = btrfs_item_size_nr(path->nodes[0], path->slots[0]);
        ptr_end = ptr + item_size;
        while (ptr < ptr_end) {
                ref = (struct btrfs_inode_ref *)ptr;
@@ -786,91 +797,42 @@ out:
        return match;
 }
 
-
-/*
- * replay one inode back reference item found in the log tree.
- * eb, slot and key refer to the buffer and key found in the log tree.
- * root is the destination we are replaying into, and path is for temp
- * use by this function.  (it should be released on return).
- */
-static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
+static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
                                  struct btrfs_root *root,
-                                 struct btrfs_root *log,
                                  struct btrfs_path *path,
-                                 struct extent_buffer *eb, int slot,
-                                 struct btrfs_key *key)
+                                 struct btrfs_root *log_root,
+                                 struct inode *dir, struct inode *inode,
+                                 struct extent_buffer *eb,
+                                 u64 inode_objectid, u64 parent_objectid,
+                                 u64 ref_index, char *name, int namelen,
+                                 int *search_done)
 {
-       struct btrfs_inode_ref *ref;
-       struct btrfs_dir_item *di;
-       struct inode *dir;
-       struct inode *inode;
-       unsigned long ref_ptr;
-       unsigned long ref_end;
-       char *name;
-       int namelen;
        int ret;
-       int search_done = 0;
-
-       /*
-        * it is possible that we didn't log all the parent directories
-        * for a given inode.  If we don't find the dir, just don't
-        * copy the back ref in.  The link count fixup code will take
-        * care of the rest
-        */
-       dir = read_one_inode(root, key->offset);
-       if (!dir)
-               return -ENOENT;
-
-       inode = read_one_inode(root, key->objectid);
-       if (!inode) {
-               iput(dir);
-               return -EIO;
-       }
-
-       ref_ptr = btrfs_item_ptr_offset(eb, slot);
-       ref_end = ref_ptr + btrfs_item_size_nr(eb, slot);
+       char *victim_name;
+       int victim_name_len;
+       struct extent_buffer *leaf;
+       struct btrfs_dir_item *di;
+       struct btrfs_key search_key;
+       struct btrfs_inode_extref *extref;
 
 again:
-       ref = (struct btrfs_inode_ref *)ref_ptr;
-
-       namelen = btrfs_inode_ref_name_len(eb, ref);
-       name = kmalloc(namelen, GFP_NOFS);
-       BUG_ON(!name);
-
-       read_extent_buffer(eb, name, (unsigned long)(ref + 1), namelen);
-
-       /* if we already have a perfect match, we're done */
-       if (inode_in_dir(root, path, btrfs_ino(dir), btrfs_ino(inode),
-                        btrfs_inode_ref_index(eb, ref),
-                        name, namelen)) {
-               goto out;
-       }
-
-       /*
-        * look for a conflicting back reference in the metadata.
-        * if we find one we have to unlink that name of the file
-        * before we add our new link.  Later on, we overwrite any
-        * existing back reference, and we don't want to create
-        * dangling pointers in the directory.
-        */
-
-       if (search_done)
-               goto insert;
-
-       ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
+       /* Search old style refs */
+       search_key.objectid = inode_objectid;
+       search_key.type = BTRFS_INODE_REF_KEY;
+       search_key.offset = parent_objectid;
+       ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
        if (ret == 0) {
-               char *victim_name;
-               int victim_name_len;
                struct btrfs_inode_ref *victim_ref;
                unsigned long ptr;
                unsigned long ptr_end;
-               struct extent_buffer *leaf = path->nodes[0];
+
+               leaf = path->nodes[0];
 
                /* are we trying to overwrite a back ref for the root directory
                 * if so, just jump out, we're done
                 */
-               if (key->objectid == key->offset)
-                       goto out_nowrite;
+               if (search_key.objectid == search_key.offset)
+                       return 1;
 
                /* check all the names in this back reference to see
                 * if they are in the log.  if so, we allow them to stay
@@ -889,7 +851,9 @@ again:
                                           (unsigned long)(victim_ref + 1),
                                           victim_name_len);
 
-                       if (!backref_in_log(log, key, victim_name,
+                       if (!backref_in_log(log_root, &search_key,
+                                           parent_objectid,
+                                           victim_name,
                                            victim_name_len)) {
                                btrfs_inc_nlink(inode);
                                btrfs_release_path(path);
@@ -897,9 +861,14 @@ again:
                                ret = btrfs_unlink_inode(trans, root, dir,
                                                         inode, victim_name,
                                                         victim_name_len);
+                               BUG_ON(ret);
                                btrfs_run_delayed_items(trans, root);
+                               kfree(victim_name);
+                               *search_done = 1;
+                               goto again;
                        }
                        kfree(victim_name);
+
                        ptr = (unsigned long)(victim_ref + 1) + victim_name_len;
                }
                BUG_ON(ret);
@@ -908,14 +877,78 @@ again:
                 * NOTE: we have searched root tree and checked the
                 * coresponding ref, it does not need to check again.
                 */
-               search_done = 1;
+               *search_done = 1;
+       }
+       btrfs_release_path(path);
+
+       /* Same search but for extended refs */
+       extref = btrfs_lookup_inode_extref(NULL, root, path, name, namelen,
+                                          inode_objectid, parent_objectid, 0,
+                                          0);
+       if (!IS_ERR_OR_NULL(extref)) {
+               u32 item_size;
+               u32 cur_offset = 0;
+               unsigned long base;
+               struct inode *victim_parent;
+
+               leaf = path->nodes[0];
+
+               item_size = btrfs_item_size_nr(leaf, path->slots[0]);
+               base = btrfs_item_ptr_offset(leaf, path->slots[0]);
+
+               while (cur_offset < item_size) {
+                       extref = (struct btrfs_inode_extref *)base + cur_offset;
+
+                       victim_name_len = btrfs_inode_extref_name_len(leaf, extref);
+
+                       if (btrfs_inode_extref_parent(leaf, extref) != parent_objectid)
+                               goto next;
+
+                       victim_name = kmalloc(victim_name_len, GFP_NOFS);
+                       read_extent_buffer(leaf, victim_name, (unsigned long)&extref->name,
+                                          victim_name_len);
+
+                       search_key.objectid = inode_objectid;
+                       search_key.type = BTRFS_INODE_EXTREF_KEY;
+                       search_key.offset = btrfs_extref_hash(parent_objectid,
+                                                             victim_name,
+                                                             victim_name_len);
+                       ret = 0;
+                       if (!backref_in_log(log_root, &search_key,
+                                           parent_objectid, victim_name,
+                                           victim_name_len)) {
+                               ret = -ENOENT;
+                               victim_parent = read_one_inode(root,
+                                                              parent_objectid);
+                               if (victim_parent) {
+                                       btrfs_inc_nlink(inode);
+                                       btrfs_release_path(path);
+
+                                       ret = btrfs_unlink_inode(trans, root,
+                                                                victim_parent,
+                                                                inode,
+                                                                victim_name,
+                                                                victim_name_len);
+                                       btrfs_run_delayed_items(trans, root);
+                               }
+                               BUG_ON(ret);
+                               iput(victim_parent);
+                               kfree(victim_name);
+                               *search_done = 1;
+                               goto again;
+                       }
+                       kfree(victim_name);
+                       BUG_ON(ret);
+next:
+                       cur_offset += victim_name_len + sizeof(*extref);
+               }
+               *search_done = 1;
        }
        btrfs_release_path(path);
 
        /* look for a conflicting sequence number */
        di = btrfs_lookup_dir_index_item(trans, root, path, btrfs_ino(dir),
-                                        btrfs_inode_ref_index(eb, ref),
-                                        name, namelen, 0);
+                                        ref_index, name, namelen, 0);
        if (di && !IS_ERR(di)) {
                ret = drop_one_dir_item(trans, root, path, dir, di);
                BUG_ON(ret);
@@ -931,25 +964,173 @@ again:
        }
        btrfs_release_path(path);
 
-insert:
-       /* insert our name */
-       ret = btrfs_add_link(trans, dir, inode, name, namelen, 0,
-                            btrfs_inode_ref_index(eb, ref));
-       BUG_ON(ret);
+       return 0;
+}
 
-       btrfs_update_inode(trans, root, inode);
+static int extref_get_fields(struct extent_buffer *eb, unsigned long ref_ptr,
+                            u32 *namelen, char **name, u64 *index,
+                            u64 *parent_objectid)
+{
+       struct btrfs_inode_extref *extref;
 
-out:
-       ref_ptr = (unsigned long)(ref + 1) + namelen;
-       kfree(name);
-       if (ref_ptr < ref_end)
-               goto again;
+       extref = (struct btrfs_inode_extref *)ref_ptr;
+
+       *namelen = btrfs_inode_extref_name_len(eb, extref);
+       *name = kmalloc(*namelen, GFP_NOFS);
+       if (*name == NULL)
+               return -ENOMEM;
+
+       read_extent_buffer(eb, *name, (unsigned long)&extref->name,
+                          *namelen);
+
+       *index = btrfs_inode_extref_index(eb, extref);
+       if (parent_objectid)
+               *parent_objectid = btrfs_inode_extref_parent(eb, extref);
+
+       return 0;
+}
+
+static int ref_get_fields(struct extent_buffer *eb, unsigned long ref_ptr,
+                         u32 *namelen, char **name, u64 *index)
+{
+       struct btrfs_inode_ref *ref;
+
+       ref = (struct btrfs_inode_ref *)ref_ptr;
+
+       *namelen = btrfs_inode_ref_name_len(eb, ref);
+       *name = kmalloc(*namelen, GFP_NOFS);
+       if (*name == NULL)
+               return -ENOMEM;
+
+       read_extent_buffer(eb, *name, (unsigned long)(ref + 1), *namelen);
+
+       *index = btrfs_inode_ref_index(eb, ref);
+
+       return 0;
+}
+
+/*
+ * replay one inode back reference item found in the log tree.
+ * eb, slot and key refer to the buffer and key found in the log tree.
+ * root is the destination we are replaying into, and path is for temp
+ * use by this function.  (it should be released on return).
+ */
+static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
+                                 struct btrfs_root *root,
+                                 struct btrfs_root *log,
+                                 struct btrfs_path *path,
+                                 struct extent_buffer *eb, int slot,
+                                 struct btrfs_key *key)
+{
+       struct inode *dir;
+       struct inode *inode;
+       unsigned long ref_ptr;
+       unsigned long ref_end;
+       char *name;
+       int namelen;
+       int ret;
+       int search_done = 0;
+       int log_ref_ver = 0;
+       u64 parent_objectid;
+       u64 inode_objectid;
+       u64 ref_index = 0;
+       int ref_struct_size;
+
+       ref_ptr = btrfs_item_ptr_offset(eb, slot);
+       ref_end = ref_ptr + btrfs_item_size_nr(eb, slot);
+
+       if (key->type == BTRFS_INODE_EXTREF_KEY) {
+               struct btrfs_inode_extref *r;
+
+               ref_struct_size = sizeof(struct btrfs_inode_extref);
+               log_ref_ver = 1;
+               r = (struct btrfs_inode_extref *)ref_ptr;
+               parent_objectid = btrfs_inode_extref_parent(eb, r);
+       } else {
+               ref_struct_size = sizeof(struct btrfs_inode_ref);
+               parent_objectid = key->offset;
+       }
+       inode_objectid = key->objectid;
+
+       /*
+        * it is possible that we didn't log all the parent directories
+        * for a given inode.  If we don't find the dir, just don't
+        * copy the back ref in.  The link count fixup code will take
+        * care of the rest
+        */
+       dir = read_one_inode(root, parent_objectid);
+       if (!dir)
+               return -ENOENT;
+
+       inode = read_one_inode(root, inode_objectid);
+       if (!inode) {
+               iput(dir);
+               return -EIO;
+       }
+
+       while (ref_ptr < ref_end) {
+               if (log_ref_ver) {
+                       ret = extref_get_fields(eb, ref_ptr, &namelen, &name,
+                                               &ref_index, &parent_objectid);
+                       /*
+                        * parent object can change from one array
+                        * item to another.
+                        */
+                       if (!dir)
+                               dir = read_one_inode(root, parent_objectid);
+                       if (!dir)
+                               return -ENOENT;
+               } else {
+                       ret = ref_get_fields(eb, ref_ptr, &namelen, &name,
+                                            &ref_index);
+               }
+               if (ret)
+                       return ret;
+
+               /* if we already have a perfect match, we're done */
+               if (!inode_in_dir(root, path, btrfs_ino(dir), btrfs_ino(inode),
+                                 ref_index, name, namelen)) {
+                       /*
+                        * look for a conflicting back reference in the
+                        * metadata. if we find one we have to unlink that name
+                        * of the file before we add our new link.  Later on, we
+                        * overwrite any existing back reference, and we don't
+                        * want to create dangling pointers in the directory.
+                        */
+
+                       if (!search_done) {
+                               ret = __add_inode_ref(trans, root, path, log,
+                                                     dir, inode, eb,
+                                                     inode_objectid,
+                                                     parent_objectid,
+                                                     ref_index, name, namelen,
+                                                     &search_done);
+                               if (ret == 1)
+                                       goto out;
+                               BUG_ON(ret);
+                       }
+
+                       /* insert our name */
+                       ret = btrfs_add_link(trans, dir, inode, name, namelen,
+                                            0, ref_index);
+                       BUG_ON(ret);
+
+                       btrfs_update_inode(trans, root, inode);
+               }
+
+               ref_ptr = (unsigned long)(ref_ptr + ref_struct_size) + namelen;
+               kfree(name);
+               if (log_ref_ver) {
+                       iput(dir);
+                       dir = NULL;
+               }
+       }
 
        /* finally write the back reference in the inode */
        ret = overwrite_item(trans, root, path, eb, slot, key);
        BUG_ON(ret);
 
-out_nowrite:
+out:
        btrfs_release_path(path);
        iput(dir);
        iput(inode);
@@ -966,25 +1147,55 @@ static int insert_orphan_item(struct btrfs_trans_handle *trans,
        return ret;
 }
 
+static int count_inode_extrefs(struct btrfs_root *root,
+                              struct inode *inode, struct btrfs_path *path)
+{
+       int ret = 0;
+       int name_len;
+       unsigned int nlink = 0;
+       u32 item_size;
+       u32 cur_offset = 0;
+       u64 inode_objectid = btrfs_ino(inode);
+       u64 offset = 0;
+       unsigned long ptr;
+       struct btrfs_inode_extref *extref;
+       struct extent_buffer *leaf;
 
-/*
- * There are a few corners where the link count of the file can't
- * be properly maintained during replay.  So, instead of adding
- * lots of complexity to the log code, we just scan the backrefs
- * for any file that has been through replay.
- *
- * The scan will update the link count on the inode to reflect the
- * number of back refs found.  If it goes down to zero, the iput
- * will free the inode.
- */
-static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans,
-                                          struct btrfs_root *root,
-                                          struct inode *inode)
+       while (1) {
+               ret = btrfs_find_one_extref(root, inode_objectid, offset, path,
+                                           &extref, &offset);
+               if (ret)
+                       break;
+
+               leaf = path->nodes[0];
+               item_size = btrfs_item_size_nr(leaf, path->slots[0]);
+               ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
+
+               while (cur_offset < item_size) {
+                       extref = (struct btrfs_inode_extref *) (ptr + cur_offset);
+                       name_len = btrfs_inode_extref_name_len(leaf, extref);
+
+                       nlink++;
+
+                       cur_offset += name_len + sizeof(*extref);
+               }
+
+               offset++;
+               btrfs_release_path(path);
+       }
+       btrfs_release_path(path);
+
+       if (ret < 0)
+               return ret;
+       return nlink;
+}
+
+static int count_inode_refs(struct btrfs_root *root,
+                              struct inode *inode, struct btrfs_path *path)
 {
-       struct btrfs_path *path;
        int ret;
        struct btrfs_key key;
-       u64 nlink = 0;
+       unsigned int nlink = 0;
        unsigned long ptr;
        unsigned long ptr_end;
        int name_len;
@@ -994,10 +1205,6 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans,
        key.type = BTRFS_INODE_REF_KEY;
        key.offset = (u64)-1;
 
-       path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
-
        while (1) {
                ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
                if (ret < 0)
@@ -1031,6 +1238,50 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans,
                btrfs_release_path(path);
        }
        btrfs_release_path(path);
+
+       return nlink;
+}
+
+/*
+ * There are a few corners where the link count of the file can't
+ * be properly maintained during replay.  So, instead of adding
+ * lots of complexity to the log code, we just scan the backrefs
+ * for any file that has been through replay.
+ *
+ * The scan will update the link count on the inode to reflect the
+ * number of back refs found.  If it goes down to zero, the iput
+ * will free the inode.
+ */
+static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans,
+                                          struct btrfs_root *root,
+                                          struct inode *inode)
+{
+       struct btrfs_path *path;
+       int ret;
+       u64 nlink = 0;
+       u64 ino = btrfs_ino(inode);
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+
+       ret = count_inode_refs(root, inode, path);
+       if (ret < 0)
+               goto out;
+
+       nlink = ret;
+
+       ret = count_inode_extrefs(root, inode, path);
+       if (ret == -ENOENT)
+               ret = 0;
+
+       if (ret < 0)
+               goto out;
+
+       nlink += ret;
+
+       ret = 0;
+
        if (nlink != inode->i_nlink) {
                set_nlink(inode, nlink);
                btrfs_update_inode(trans, root, inode);
@@ -1046,9 +1297,10 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans,
                ret = insert_orphan_item(trans, root, ino);
                BUG_ON(ret);
        }
-       btrfs_free_path(path);
 
-       return 0;
+out:
+       btrfs_free_path(path);
+       return ret;
 }
 
 static noinline int fixup_inode_link_counts(struct btrfs_trans_handle *trans,
@@ -1695,6 +1947,10 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
                        ret = add_inode_ref(wc->trans, root, log, path,
                                            eb, i, &key);
                        BUG_ON(ret && ret != -ENOENT);
+               } else if (key.type == BTRFS_INODE_EXTREF_KEY) {
+                       ret = add_inode_ref(wc->trans, root, log, path,
+                                           eb, i, &key);
+                       BUG_ON(ret && ret != -ENOENT);
                } else if (key.type == BTRFS_EXTENT_DATA_KEY) {
                        ret = replay_one_extent(wc->trans, root, path,
                                                eb, i, &key);
@@ -2037,7 +2293,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
        if (atomic_read(&root->log_commit[(index1 + 1) % 2]))
                wait_log_commit(trans, root, root->log_transid - 1);
        while (1) {
-               unsigned long batch = root->log_batch;
+               int batch = atomic_read(&root->log_batch);
                /* when we're on an ssd, just kick the log commit out */
                if (!btrfs_test_opt(root, SSD) && root->log_multiple_pids) {
                        mutex_unlock(&root->log_mutex);
@@ -2045,7 +2301,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
                        mutex_lock(&root->log_mutex);
                }
                wait_for_writer(trans, root);
-               if (batch == root->log_batch)
+               if (batch == atomic_read(&root->log_batch))
                        break;
        }
 
@@ -2074,7 +2330,6 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
 
        btrfs_set_root_node(&log->root_item, log->node);
 
-       root->log_batch = 0;
        root->log_transid++;
        log->log_transid = root->log_transid;
        root->log_start_pid = 0;
@@ -2087,7 +2342,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
        mutex_unlock(&root->log_mutex);
 
        mutex_lock(&log_root_tree->log_mutex);
-       log_root_tree->log_batch++;
+       atomic_inc(&log_root_tree->log_batch);
        atomic_inc(&log_root_tree->log_writers);
        mutex_unlock(&log_root_tree->log_mutex);
 
@@ -2157,7 +2412,6 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
        btrfs_set_super_log_root_level(root->fs_info->super_for_commit,
                                btrfs_header_level(log_root_tree->node));
 
-       log_root_tree->log_batch = 0;
        log_root_tree->log_transid++;
        smp_mb();
 
@@ -2171,9 +2425,12 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
         * in and cause problems either.
         */
        btrfs_scrub_pause_super(root);
-       write_ctree_super(trans, root->fs_info->tree_root, 1);
+       ret = write_ctree_super(trans, root->fs_info->tree_root, 1);
        btrfs_scrub_continue_super(root);
-       ret = 0;
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto out_wake_log_root;
+       }
 
        mutex_lock(&root->log_mutex);
        if (root->last_log_commit < log_transid)
@@ -2209,7 +2466,8 @@ static void free_log_tree(struct btrfs_trans_handle *trans,
 
        while (1) {
                ret = find_first_extent_bit(&log->dirty_log_pages,
-                               0, &start, &end, EXTENT_DIRTY | EXTENT_NEW);
+                               0, &start, &end, EXTENT_DIRTY | EXTENT_NEW,
+                               NULL);
                if (ret)
                        break;
 
@@ -2646,6 +2904,7 @@ static int drop_objectid_items(struct btrfs_trans_handle *trans,
        int ret;
        struct btrfs_key key;
        struct btrfs_key found_key;
+       int start_slot;
 
        key.objectid = objectid;
        key.type = max_key_type;
@@ -2667,8 +2926,18 @@ static int drop_objectid_items(struct btrfs_trans_handle *trans,
                if (found_key.objectid != objectid)
                        break;
 
-               ret = btrfs_del_item(trans, log, path);
-               if (ret)
+               found_key.offset = 0;
+               found_key.type = 0;
+               ret = btrfs_bin_search(path->nodes[0], &found_key, 0,
+                                      &start_slot);
+
+               ret = btrfs_del_items(trans, log, path, start_slot,
+                                     path->slots[0] - start_slot + 1);
+               /*
+                * If start slot isn't 0 then we don't need to re-search, we've
+                * found the last guy with the objectid in this tree.
+                */
+               if (ret || start_slot != 0)
                        break;
                btrfs_release_path(path);
        }
@@ -2678,14 +2947,64 @@ static int drop_objectid_items(struct btrfs_trans_handle *trans,
        return ret;
 }
 
+static void fill_inode_item(struct btrfs_trans_handle *trans,
+                           struct extent_buffer *leaf,
+                           struct btrfs_inode_item *item,
+                           struct inode *inode, int log_inode_only)
+{
+       btrfs_set_inode_uid(leaf, item, inode->i_uid);
+       btrfs_set_inode_gid(leaf, item, inode->i_gid);
+       btrfs_set_inode_mode(leaf, item, inode->i_mode);
+       btrfs_set_inode_nlink(leaf, item, inode->i_nlink);
+
+       btrfs_set_timespec_sec(leaf, btrfs_inode_atime(item),
+                              inode->i_atime.tv_sec);
+       btrfs_set_timespec_nsec(leaf, btrfs_inode_atime(item),
+                               inode->i_atime.tv_nsec);
+
+       btrfs_set_timespec_sec(leaf, btrfs_inode_mtime(item),
+                              inode->i_mtime.tv_sec);
+       btrfs_set_timespec_nsec(leaf, btrfs_inode_mtime(item),
+                               inode->i_mtime.tv_nsec);
+
+       btrfs_set_timespec_sec(leaf, btrfs_inode_ctime(item),
+                              inode->i_ctime.tv_sec);
+       btrfs_set_timespec_nsec(leaf, btrfs_inode_ctime(item),
+                               inode->i_ctime.tv_nsec);
+
+       btrfs_set_inode_nbytes(leaf, item, inode_get_bytes(inode));
+
+       btrfs_set_inode_sequence(leaf, item, inode->i_version);
+       btrfs_set_inode_transid(leaf, item, trans->transid);
+       btrfs_set_inode_rdev(leaf, item, inode->i_rdev);
+       btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags);
+       btrfs_set_inode_block_group(leaf, item, 0);
+
+       if (log_inode_only) {
+               /* set the generation to zero so the recover code
+                * can tell the difference between an logging
+                * just to say 'this inode exists' and a logging
+                * to say 'update this inode with these values'
+                */
+               btrfs_set_inode_generation(leaf, item, 0);
+               btrfs_set_inode_size(leaf, item, 0);
+       } else {
+               btrfs_set_inode_generation(leaf, item,
+                                          BTRFS_I(inode)->generation);
+               btrfs_set_inode_size(leaf, item, inode->i_size);
+       }
+
+}
+
 static noinline int copy_items(struct btrfs_trans_handle *trans,
-                              struct btrfs_root *log,
+                              struct inode *inode,
                               struct btrfs_path *dst_path,
                               struct extent_buffer *src,
                               int start_slot, int nr, int inode_only)
 {
        unsigned long src_offset;
        unsigned long dst_offset;
+       struct btrfs_root *log = BTRFS_I(inode)->root->log_root;
        struct btrfs_file_extent_item *extent;
        struct btrfs_inode_item *inode_item;
        int ret;
@@ -2694,6 +3013,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
        char *ins_data;
        int i;
        struct list_head ordered_sums;
+       int skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
 
        INIT_LIST_HEAD(&ordered_sums);
 
@@ -2722,29 +3042,23 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
 
                src_offset = btrfs_item_ptr_offset(src, start_slot + i);
 
-               copy_extent_buffer(dst_path->nodes[0], src, dst_offset,
-                                  src_offset, ins_sizes[i]);
-
-               if (inode_only == LOG_INODE_EXISTS &&
-                   ins_keys[i].type == BTRFS_INODE_ITEM_KEY) {
+               if (ins_keys[i].type == BTRFS_INODE_ITEM_KEY) {
                        inode_item = btrfs_item_ptr(dst_path->nodes[0],
                                                    dst_path->slots[0],
                                                    struct btrfs_inode_item);
-                       btrfs_set_inode_size(dst_path->nodes[0], inode_item, 0);
-
-                       /* set the generation to zero so the recover code
-                        * can tell the difference between an logging
-                        * just to say 'this inode exists' and a logging
-                        * to say 'update this inode with these values'
-                        */
-                       btrfs_set_inode_generation(dst_path->nodes[0],
-                                                  inode_item, 0);
+                       fill_inode_item(trans, dst_path->nodes[0], inode_item,
+                                       inode, inode_only == LOG_INODE_EXISTS);
+               } else {
+                       copy_extent_buffer(dst_path->nodes[0], src, dst_offset,
+                                          src_offset, ins_sizes[i]);
                }
+
                /* take a reference on file data extents so that truncates
                 * or deletes of this inode don't have to relog the inode
                 * again
                 */
-               if (btrfs_key_type(ins_keys + i) == BTRFS_EXTENT_DATA_KEY) {
+               if (btrfs_key_type(ins_keys + i) == BTRFS_EXTENT_DATA_KEY &&
+                   !skip_csum) {
                        int found_type;
                        extent = btrfs_item_ptr(src, start_slot + i,
                                                struct btrfs_file_extent_item);
@@ -2753,8 +3067,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
                                continue;
 
                        found_type = btrfs_file_extent_type(src, extent);
-                       if (found_type == BTRFS_FILE_EXTENT_REG ||
-                           found_type == BTRFS_FILE_EXTENT_PREALLOC) {
+                       if (found_type == BTRFS_FILE_EXTENT_REG) {
                                u64 ds, dl, cs, cl;
                                ds = btrfs_file_extent_disk_bytenr(src,
                                                                extent);
@@ -2803,6 +3116,239 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
        return ret;
 }
 
+static int extent_cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+       struct extent_map *em1, *em2;
+
+       em1 = list_entry(a, struct extent_map, list);
+       em2 = list_entry(b, struct extent_map, list);
+
+       if (em1->start < em2->start)
+               return -1;
+       else if (em1->start > em2->start)
+               return 1;
+       return 0;
+}
+
+struct log_args {
+       struct extent_buffer *src;
+       u64 next_offset;
+       int start_slot;
+       int nr;
+};
+
+static int log_one_extent(struct btrfs_trans_handle *trans,
+                         struct inode *inode, struct btrfs_root *root,
+                         struct extent_map *em, struct btrfs_path *path,
+                         struct btrfs_path *dst_path, struct log_args *args)
+{
+       struct btrfs_root *log = root->log_root;
+       struct btrfs_file_extent_item *fi;
+       struct btrfs_key key;
+       u64 start = em->mod_start;
+       u64 search_start = start;
+       u64 len = em->mod_len;
+       u64 num_bytes;
+       int nritems;
+       int ret;
+
+       if (BTRFS_I(inode)->logged_trans == trans->transid) {
+               ret = __btrfs_drop_extents(trans, log, inode, dst_path, start,
+                                          start + len, NULL, 0);
+               if (ret)
+                       return ret;
+       }
+
+       while (len) {
+               if (args->nr)
+                       goto next_slot;
+again:
+               key.objectid = btrfs_ino(inode);
+               key.type = BTRFS_EXTENT_DATA_KEY;
+               key.offset = search_start;
+
+               ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+               if (ret < 0)
+                       return ret;
+
+               if (ret) {
+                       /*
+                        * A rare case were we can have an em for a section of a
+                        * larger extent so we need to make sure that this em
+                        * falls within the extent we've found.  If not we just
+                        * bail and go back to ye-olde way of doing things but
+                        * it happens often enough in testing that we need to do
+                        * this dance to make sure.
+                        */
+                       do {
+                               if (path->slots[0] == 0) {
+                                       btrfs_release_path(path);
+                                       if (search_start == 0)
+                                               return -ENOENT;
+                                       search_start--;
+                                       goto again;
+                               }
+
+                               path->slots[0]--;
+                               btrfs_item_key_to_cpu(path->nodes[0], &key,
+                                                     path->slots[0]);
+                               if (key.objectid != btrfs_ino(inode) ||
+                                   key.type != BTRFS_EXTENT_DATA_KEY) {
+                                       btrfs_release_path(path);
+                                       return -ENOENT;
+                               }
+                       } while (key.offset > start);
+
+                       fi = btrfs_item_ptr(path->nodes[0], path->slots[0],
+                                           struct btrfs_file_extent_item);
+                       num_bytes = btrfs_file_extent_num_bytes(path->nodes[0],
+                                                               fi);
+                       if (key.offset + num_bytes <= start) {
+                               btrfs_release_path(path);
+                               return -ENOENT;
+                       }
+               }
+               args->src = path->nodes[0];
+next_slot:
+               btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
+               fi = btrfs_item_ptr(args->src, path->slots[0],
+                                   struct btrfs_file_extent_item);
+               if (args->nr &&
+                   args->start_slot + args->nr == path->slots[0]) {
+                       args->nr++;
+               } else if (args->nr) {
+                       ret = copy_items(trans, inode, dst_path, args->src,
+                                        args->start_slot, args->nr,
+                                        LOG_INODE_ALL);
+                       if (ret)
+                               return ret;
+                       args->nr = 1;
+                       args->start_slot = path->slots[0];
+               } else if (!args->nr) {
+                       args->nr = 1;
+                       args->start_slot = path->slots[0];
+               }
+               nritems = btrfs_header_nritems(path->nodes[0]);
+               path->slots[0]++;
+               num_bytes = btrfs_file_extent_num_bytes(args->src, fi);
+               if (len < num_bytes) {
+                       /* I _think_ this is ok, envision we write to a
+                        * preallocated space that is adjacent to a previously
+                        * written preallocated space that gets merged when we
+                        * mark this preallocated space written.  If we do not
+                        * have the adjacent extent in cache then when we copy
+                        * this extent it could end up being larger than our EM
+                        * thinks it is, which is a-ok, so just set len to 0.
+                        */
+                       len = 0;
+               } else {
+                       len -= num_bytes;
+               }
+               start = key.offset + num_bytes;
+               args->next_offset = start;
+               search_start = start;
+
+               if (path->slots[0] < nritems) {
+                       if (len)
+                               goto next_slot;
+                       break;
+               }
+
+               if (args->nr) {
+                       ret = copy_items(trans, inode, dst_path, args->src,
+                                        args->start_slot, args->nr,
+                                        LOG_INODE_ALL);
+                       if (ret)
+                               return ret;
+                       args->nr = 0;
+                       btrfs_release_path(path);
+               }
+       }
+
+       return 0;
+}
+
+static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
+                                    struct btrfs_root *root,
+                                    struct inode *inode,
+                                    struct btrfs_path *path,
+                                    struct btrfs_path *dst_path)
+{
+       struct log_args args;
+       struct extent_map *em, *n;
+       struct list_head extents;
+       struct extent_map_tree *tree = &BTRFS_I(inode)->extent_tree;
+       u64 test_gen;
+       int ret = 0;
+
+       INIT_LIST_HEAD(&extents);
+
+       memset(&args, 0, sizeof(args));
+
+       write_lock(&tree->lock);
+       test_gen = root->fs_info->last_trans_committed;
+
+       list_for_each_entry_safe(em, n, &tree->modified_extents, list) {
+               list_del_init(&em->list);
+               if (em->generation <= test_gen)
+                       continue;
+               /* Need a ref to keep it from getting evicted from cache */
+               atomic_inc(&em->refs);
+               set_bit(EXTENT_FLAG_LOGGING, &em->flags);
+               list_add_tail(&em->list, &extents);
+       }
+
+       list_sort(NULL, &extents, extent_cmp);
+
+       while (!list_empty(&extents)) {
+               em = list_entry(extents.next, struct extent_map, list);
+
+               list_del_init(&em->list);
+               clear_bit(EXTENT_FLAG_LOGGING, &em->flags);
+
+               /*
+                * If we had an error we just need to delete everybody from our
+                * private list.
+                */
+               if (ret) {
+                       free_extent_map(em);
+                       continue;
+               }
+
+               write_unlock(&tree->lock);
+
+               /*
+                * If the previous EM and the last extent we left off on aren't
+                * sequential then we need to copy the items we have and redo
+                * our search
+                */
+               if (args.nr && em->mod_start != args.next_offset) {
+                       ret = copy_items(trans, inode, dst_path, args.src,
+                                        args.start_slot, args.nr,
+                                        LOG_INODE_ALL);
+                       if (ret) {
+                               free_extent_map(em);
+                               write_lock(&tree->lock);
+                               continue;
+                       }
+                       btrfs_release_path(path);
+                       args.nr = 0;
+               }
+
+               ret = log_one_extent(trans, inode, root, em, path, dst_path, &args);
+               free_extent_map(em);
+               write_lock(&tree->lock);
+       }
+       WARN_ON(!list_empty(&extents));
+       write_unlock(&tree->lock);
+
+       if (!ret && args.nr)
+               ret = copy_items(trans, inode, dst_path, args.src,
+                                args.start_slot, args.nr, LOG_INODE_ALL);
+       btrfs_release_path(path);
+       return ret;
+}
+
 /* log a single inode in the tree log.
  * At least one parent directory for this inode must exist in the tree
  * or be logged already.
@@ -2832,6 +3378,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
        int nritems;
        int ins_start_slot = 0;
        int ins_nr;
+       bool fast_search = false;
        u64 ino = btrfs_ino(inode);
 
        log = root->log_root;
@@ -2851,21 +3398,23 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
 
        max_key.objectid = ino;
 
-       /* today the code can only do partial logging of directories */
-       if (!S_ISDIR(inode->i_mode))
-           inode_only = LOG_INODE_ALL;
 
+       /* today the code can only do partial logging of directories */
        if (inode_only == LOG_INODE_EXISTS || S_ISDIR(inode->i_mode))
                max_key.type = BTRFS_XATTR_ITEM_KEY;
        else
                max_key.type = (u8)-1;
        max_key.offset = (u64)-1;
 
-       ret = btrfs_commit_inode_delayed_items(trans, inode);
-       if (ret) {
-               btrfs_free_path(path);
-               btrfs_free_path(dst_path);
-               return ret;
+       /* Only run delayed items if we are a dir or a new file */
+       if (S_ISDIR(inode->i_mode) ||
+           BTRFS_I(inode)->generation > root->fs_info->last_trans_committed) {
+               ret = btrfs_commit_inode_delayed_items(trans, inode);
+               if (ret) {
+                       btrfs_free_path(path);
+                       btrfs_free_path(dst_path);
+                       return ret;
+               }
        }
 
        mutex_lock(&BTRFS_I(inode)->log_mutex);
@@ -2881,7 +3430,16 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
                        max_key_type = BTRFS_XATTR_ITEM_KEY;
                ret = drop_objectid_items(trans, log, path, ino, max_key_type);
        } else {
-               ret = btrfs_truncate_inode_items(trans, log, inode, 0, 0);
+               if (test_and_clear_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
+                                      &BTRFS_I(inode)->runtime_flags)) {
+                       ret = btrfs_truncate_inode_items(trans, log,
+                                                        inode, 0, 0);
+               } else {
+                       fast_search = true;
+                       max_key.type = BTRFS_XATTR_ITEM_KEY;
+                       ret = drop_objectid_items(trans, log, path, ino,
+                                                 BTRFS_XATTR_ITEM_KEY);
+               }
        }
        if (ret) {
                err = ret;
@@ -2912,7 +3470,7 @@ again:
                        goto next_slot;
                }
 
-               ret = copy_items(trans, log, dst_path, src, ins_start_slot,
+               ret = copy_items(trans, inode, dst_path, src, ins_start_slot,
                                 ins_nr, inode_only);
                if (ret) {
                        err = ret;
@@ -2930,7 +3488,7 @@ next_slot:
                        goto again;
                }
                if (ins_nr) {
-                       ret = copy_items(trans, log, dst_path, src,
+                       ret = copy_items(trans, inode, dst_path, src,
                                         ins_start_slot,
                                         ins_nr, inode_only);
                        if (ret) {
@@ -2951,8 +3509,7 @@ next_slot:
                        break;
        }
        if (ins_nr) {
-               ret = copy_items(trans, log, dst_path, src,
-                                ins_start_slot,
+               ret = copy_items(trans, inode, dst_path, src, ins_start_slot,
                                 ins_nr, inode_only);
                if (ret) {
                        err = ret;
@@ -2960,7 +3517,24 @@ next_slot:
                }
                ins_nr = 0;
        }
-       WARN_ON(ins_nr);
+
+       if (fast_search) {
+               btrfs_release_path(path);
+               btrfs_release_path(dst_path);
+               ret = btrfs_log_changed_extents(trans, root, inode, path,
+                                               dst_path);
+               if (ret) {
+                       err = ret;
+                       goto out_unlock;
+               }
+       } else {
+               struct extent_map_tree *tree = &BTRFS_I(inode)->extent_tree;
+               struct extent_map *em, *n;
+
+               list_for_each_entry_safe(em, n, &tree->modified_extents, list)
+                       list_del_init(&em->list);
+       }
+
        if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode)) {
                btrfs_release_path(path);
                btrfs_release_path(dst_path);
@@ -2971,6 +3545,7 @@ next_slot:
                }
        }
        BTRFS_I(inode)->logged_trans = trans->transid;
+       BTRFS_I(inode)->last_log_commit = BTRFS_I(inode)->last_sub_trans;
 out_unlock:
        mutex_unlock(&BTRFS_I(inode)->log_mutex);
 
@@ -3138,7 +3713,7 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
 end_trans:
        dput(old_parent);
        if (ret < 0) {
-               BUG_ON(ret != -ENOSPC);
+               WARN_ON(ret != -ENOSPC);
                root->fs_info->last_trans_log_full_commit = trans->transid;
                ret = 1;
        }
index ab942f46b3dd81e06348c4950901f3e4eef87016..99be4c138db6dac51fbcb7afefc6931ce3cf583d 100644 (file)
@@ -143,14 +143,13 @@ EXPORT_SYMBOL(ulist_free);
  * In case of allocation failure -ENOMEM is returned and the ulist stays
  * unaltered.
  */
-int ulist_add(struct ulist *ulist, u64 val, unsigned long aux,
-             gfp_t gfp_mask)
+int ulist_add(struct ulist *ulist, u64 val, u64 aux, gfp_t gfp_mask)
 {
        return ulist_add_merge(ulist, val, aux, NULL, gfp_mask);
 }
 
-int ulist_add_merge(struct ulist *ulist, u64 val, unsigned long aux,
-                   unsigned long *old_aux, gfp_t gfp_mask)
+int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux,
+                   u64 *old_aux, gfp_t gfp_mask)
 {
        int i;
 
index 21bdc8ec813046ac56e3c7db0739bcdba7ac188a..21a1963439c3030c0146a1994f47a38fd43e0a95 100644 (file)
@@ -33,7 +33,7 @@ struct ulist_iterator {
  */
 struct ulist_node {
        u64 val;                /* value to store */
-       unsigned long aux;      /* auxiliary value saved along with the val */
+       u64 aux;                /* auxiliary value saved along with the val */
 };
 
 struct ulist {
@@ -65,10 +65,9 @@ void ulist_fini(struct ulist *ulist);
 void ulist_reinit(struct ulist *ulist);
 struct ulist *ulist_alloc(gfp_t gfp_mask);
 void ulist_free(struct ulist *ulist);
-int ulist_add(struct ulist *ulist, u64 val, unsigned long aux,
-             gfp_t gfp_mask);
-int ulist_add_merge(struct ulist *ulist, u64 val, unsigned long aux,
-                   unsigned long *old_aux, gfp_t gfp_mask);
+int ulist_add(struct ulist *ulist, u64 val, u64 aux, gfp_t gfp_mask);
+int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux,
+                   u64 *old_aux, gfp_t gfp_mask);
 struct ulist_node *ulist_next(struct ulist *ulist,
                              struct ulist_iterator *uiter);
 
index 88b969aeeb71a53128ae941e569ad19f7b1038c3..029b903a4ae3797322e05090790b86c9e8596c43 100644 (file)
@@ -639,7 +639,7 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
 
                bdev = blkdev_get_by_path(device->name->str, flags, holder);
                if (IS_ERR(bdev)) {
-                       printk(KERN_INFO "open %s failed\n", device->name->str);
+                       printk(KERN_INFO "btrfs: open %s failed\n", device->name->str);
                        goto error;
                }
                filemap_write_and_wait(bdev->bd_inode->i_mapping);
@@ -1475,6 +1475,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
                free_fs_devices(cur_devices);
        }
 
+       root->fs_info->num_tolerated_disk_barrier_failures =
+               btrfs_calc_num_tolerated_disk_barrier_failures(root->fs_info);
+
        /*
         * at this point, the device is zero sized.  We want to
         * remove it from the devices list and zero out the old super
@@ -1775,15 +1778,21 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
 
        if (seeding_dev) {
                ret = init_first_rw_device(trans, root, device);
-               if (ret)
+               if (ret) {
+                       btrfs_abort_transaction(trans, root, ret);
                        goto error_trans;
+               }
                ret = btrfs_finish_sprout(trans, root);
-               if (ret)
+               if (ret) {
+                       btrfs_abort_transaction(trans, root, ret);
                        goto error_trans;
+               }
        } else {
                ret = btrfs_add_device(trans, root, device);
-               if (ret)
+               if (ret) {
+                       btrfs_abort_transaction(trans, root, ret);
                        goto error_trans;
+               }
        }
 
        /*
@@ -1793,6 +1802,8 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
        btrfs_clear_space_info_full(root->fs_info);
 
        unlock_chunks(root);
+       root->fs_info->num_tolerated_disk_barrier_failures =
+               btrfs_calc_num_tolerated_disk_barrier_failures(root->fs_info);
        ret = btrfs_commit_transaction(trans, root);
 
        if (seeding_dev) {
@@ -1814,7 +1825,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
 
 error_trans:
        unlock_chunks(root);
-       btrfs_abort_transaction(trans, root, ret);
        btrfs_end_transaction(trans, root);
        rcu_string_free(device->name);
        kfree(device);
@@ -2804,6 +2814,26 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
                }
        }
 
+       if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
+               int num_tolerated_disk_barrier_failures;
+               u64 target = bctl->sys.target;
+
+               num_tolerated_disk_barrier_failures =
+                       btrfs_calc_num_tolerated_disk_barrier_failures(fs_info);
+               if (num_tolerated_disk_barrier_failures > 0 &&
+                   (target &
+                    (BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID0 |
+                     BTRFS_AVAIL_ALLOC_BIT_SINGLE)))
+                       num_tolerated_disk_barrier_failures = 0;
+               else if (num_tolerated_disk_barrier_failures > 1 &&
+                        (target &
+                         (BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10)))
+                       num_tolerated_disk_barrier_failures = 1;
+
+               fs_info->num_tolerated_disk_barrier_failures =
+                       num_tolerated_disk_barrier_failures;
+       }
+
        ret = insert_balance_item(fs_info->tree_root, bctl);
        if (ret && ret != -EEXIST)
                goto out;
@@ -2836,6 +2866,11 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
                __cancel_balance(fs_info);
        }
 
+       if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
+               fs_info->num_tolerated_disk_barrier_failures =
+                       btrfs_calc_num_tolerated_disk_barrier_failures(fs_info);
+       }
+
        wake_up(&fs_info->balance_wait_q);
 
        return ret;
@@ -3608,12 +3643,16 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans,
        ret = __btrfs_alloc_chunk(trans, extent_root, &sys_map,
                                  &sys_chunk_size, &sys_stripe_size,
                                  sys_chunk_offset, alloc_profile);
-       if (ret)
-               goto abort;
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto out;
+       }
 
        ret = btrfs_add_device(trans, fs_info->chunk_root, device);
-       if (ret)
-               goto abort;
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto out;
+       }
 
        /*
         * Modifying chunk tree needs allocating new blocks from both
@@ -3623,19 +3662,19 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans,
         */
        ret = __finish_chunk_alloc(trans, extent_root, map, chunk_offset,
                                   chunk_size, stripe_size);
-       if (ret)
-               goto abort;
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto out;
+       }
 
        ret = __finish_chunk_alloc(trans, extent_root, sys_map,
                                   sys_chunk_offset, sys_chunk_size,
                                   sys_stripe_size);
        if (ret)
-               goto abort;
+               btrfs_abort_transaction(trans, root, ret);
 
-       return 0;
+out:
 
-abort:
-       btrfs_abort_transaction(trans, root, ret);
        return ret;
 }
 
@@ -3760,7 +3799,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
        read_unlock(&em_tree->lock);
 
        if (!em) {
-               printk(KERN_CRIT "unable to find logical %llu len %llu\n",
+               printk(KERN_CRIT "btrfs: unable to find logical %llu len %llu\n",
                       (unsigned long long)logical,
                       (unsigned long long)*length);
                BUG();
@@ -4217,7 +4256,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
 
        total_devs = bbio->num_stripes;
        if (map_length < length) {
-               printk(KERN_CRIT "mapping failed logical %llu bio len %llu "
+               printk(KERN_CRIT "btrfs: mapping failed logical %llu bio len %llu "
                       "len %llu\n", (unsigned long long)logical,
                       (unsigned long long)length,
                       (unsigned long long)map_length);
index 92c20654cc55b18d77630104eca7085ecde66793..9acb846c3e7f775e78684d2117c861c70b9890bc 100644 (file)
@@ -97,7 +97,7 @@ static int zlib_compress_pages(struct list_head *ws,
        *total_in = 0;
 
        if (Z_OK != zlib_deflateInit(&workspace->def_strm, 3)) {
-               printk(KERN_WARNING "deflateInit failed\n");
+               printk(KERN_WARNING "btrfs: deflateInit failed\n");
                ret = -1;
                goto out;
        }
@@ -125,7 +125,7 @@ static int zlib_compress_pages(struct list_head *ws,
        while (workspace->def_strm.total_in < len) {
                ret = zlib_deflate(&workspace->def_strm, Z_SYNC_FLUSH);
                if (ret != Z_OK) {
-                       printk(KERN_DEBUG "btrfs deflate in loop returned %d\n",
+                       printk(KERN_DEBUG "btrfs: deflate in loop returned %d\n",
                               ret);
                        zlib_deflateEnd(&workspace->def_strm);
                        ret = -1;
@@ -252,7 +252,7 @@ static int zlib_decompress_biovec(struct list_head *ws, struct page **pages_in,
        }
 
        if (Z_OK != zlib_inflateInit2(&workspace->inf_strm, wbits)) {
-               printk(KERN_WARNING "inflateInit failed\n");
+               printk(KERN_WARNING "btrfs: inflateInit failed\n");
                return -1;
        }
        while (workspace->inf_strm.total_in < srclen) {
@@ -336,7 +336,7 @@ static int zlib_decompress(struct list_head *ws, unsigned char *data_in,
        }
 
        if (Z_OK != zlib_inflateInit2(&workspace->inf_strm, wbits)) {
-               printk(KERN_WARNING "inflateInit failed\n");
+               printk(KERN_WARNING "btrfs: inflateInit failed\n");
                return -1;
        }
 
index 8e1b60e557b65bea0df86a881376456658a9cffd..02ce90972d81ca6e8b60ed580931c676c441fc2c 100644 (file)
@@ -99,7 +99,7 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
  * FIXME: we should try harder by querying the mds for the ino.
  */
 static struct dentry *__fh_to_dentry(struct super_block *sb,
-                                    struct ceph_nfs_fh *fh)
+                                    struct ceph_nfs_fh *fh, int fh_len)
 {
        struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
        struct inode *inode;
@@ -107,6 +107,9 @@ static struct dentry *__fh_to_dentry(struct super_block *sb,
        struct ceph_vino vino;
        int err;
 
+       if (fh_len < sizeof(*fh) / 4)
+               return ERR_PTR(-ESTALE);
+
        dout("__fh_to_dentry %llx\n", fh->ino);
        vino.ino = fh->ino;
        vino.snap = CEPH_NOSNAP;
@@ -150,7 +153,7 @@ static struct dentry *__fh_to_dentry(struct super_block *sb,
  * convert connectable fh to dentry
  */
 static struct dentry *__cfh_to_dentry(struct super_block *sb,
-                                     struct ceph_nfs_confh *cfh)
+                                     struct ceph_nfs_confh *cfh, int fh_len)
 {
        struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
        struct inode *inode;
@@ -158,6 +161,9 @@ static struct dentry *__cfh_to_dentry(struct super_block *sb,
        struct ceph_vino vino;
        int err;
 
+       if (fh_len < sizeof(*cfh) / 4)
+               return ERR_PTR(-ESTALE);
+
        dout("__cfh_to_dentry %llx (%llx/%x)\n",
             cfh->ino, cfh->parent_ino, cfh->parent_name_hash);
 
@@ -207,9 +213,11 @@ static struct dentry *ceph_fh_to_dentry(struct super_block *sb, struct fid *fid,
                                        int fh_len, int fh_type)
 {
        if (fh_type == 1)
-               return __fh_to_dentry(sb, (struct ceph_nfs_fh *)fid->raw);
+               return __fh_to_dentry(sb, (struct ceph_nfs_fh *)fid->raw,
+                                                               fh_len);
        else
-               return __cfh_to_dentry(sb, (struct ceph_nfs_confh *)fid->raw);
+               return __cfh_to_dentry(sb, (struct ceph_nfs_confh *)fid->raw,
+                                                               fh_len);
 }
 
 /*
@@ -230,6 +238,8 @@ static struct dentry *ceph_fh_to_parent(struct super_block *sb,
 
        if (fh_type == 1)
                return ERR_PTR(-ESTALE);
+       if (fh_len < sizeof(*cfh) / 4)
+               return ERR_PTR(-ESTALE);
 
        pr_debug("fh_to_parent %llx/%d\n", cfh->parent_ino,
                 cfh->parent_name_hash);
index 53cf2aabce877ce2a8e15844ab667cf6f26a2d63..71d5d0a5f6b2fcc8487e0e3e575bf158f6922bd7 100644 (file)
@@ -203,6 +203,27 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len,
        int i;
        wchar_t wchar_to; /* needed to quiet sparse */
 
+       /* special case for utf8 to handle no plane0 chars */
+       if (!strcmp(codepage->charset, "utf8")) {
+               /*
+                * convert utf8 -> utf16, we assume we have enough space
+                * as caller should have assumed conversion does not overflow
+                * in destination len is length in wchar_t units (16bits)
+                */
+               i  = utf8s_to_utf16s(from, len, UTF16_LITTLE_ENDIAN,
+                                      (wchar_t *) to, len);
+
+               /* if success terminate and exit */
+               if (i >= 0)
+                       goto success;
+               /*
+                * if fails fall back to UCS encoding as this
+                * function should not return negative values
+                * currently can fail only if source contains
+                * invalid encoded characters
+                */
+       }
+
        for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
                charlen = codepage->char2uni(from, len, &wchar_to);
                if (charlen < 1) {
@@ -215,6 +236,7 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len,
                put_unaligned_le16(wchar_to, &to[i]);
        }
 
+success:
        put_unaligned_le16(0, &to[i]);
        return i;
 }
index 2fdbe08a7a23f44bd4cccd8ab5c276cf1d981fc3..5c670b998ffbebb3e9743ab66c8125711ab8e421 100644 (file)
@@ -67,6 +67,7 @@ enum {
        /* Mount options that take no arguments */
        Opt_user_xattr, Opt_nouser_xattr,
        Opt_forceuid, Opt_noforceuid,
+       Opt_forcegid, Opt_noforcegid,
        Opt_noblocksend, Opt_noautotune,
        Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
        Opt_mapchars, Opt_nomapchars, Opt_sfu,
@@ -117,6 +118,8 @@ static const match_table_t cifs_mount_option_tokens = {
        { Opt_nouser_xattr, "nouser_xattr" },
        { Opt_forceuid, "forceuid" },
        { Opt_noforceuid, "noforceuid" },
+       { Opt_forcegid, "forcegid" },
+       { Opt_noforcegid, "noforcegid" },
        { Opt_noblocksend, "noblocksend" },
        { Opt_noautotune, "noautotune" },
        { Opt_hard, "hard" },
@@ -1195,6 +1198,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                case Opt_noforceuid:
                        override_uid = 0;
                        break;
+               case Opt_forcegid:
+                       override_gid = 1;
+                       break;
+               case Opt_noforcegid:
+                       override_gid = 0;
+                       break;
                case Opt_noblocksend:
                        vol->noblocksnd = 1;
                        break;
index 2126ab185045a1314a4f16d93e948fff847a7e5d..76d974c952fe93126a31d437dc0e362ffef6087c 100644 (file)
@@ -183,6 +183,12 @@ smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec,
                rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
                                    n_vec - first_vec, remaining);
                if (rc == -ENOSPC || rc == -EAGAIN) {
+                       /*
+                        * Catch if a low level driver returns -ENOSPC. This
+                        * WARN_ON will be removed by 3.10 if no one reports
+                        * seeing this.
+                        */
+                       WARN_ON_ONCE(rc == -ENOSPC);
                        i++;
                        if (i >= 14 || (!server->noblocksnd && (i > 2))) {
                                cERROR(1, "sends on sock %p stuck for 15 "
index b7a24d0ca30df9d82beee3866b0dc30861946c0f..015e1e1f87c649ff48df282c6c04780569c3192d 100644 (file)
@@ -776,16 +776,16 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
        char *kernel_type;
        unsigned long data_page;
        char *kernel_dev;
-       char *dir_page;
+       struct filename *dir;
        int retval;
 
        retval = copy_mount_string(type, &kernel_type);
        if (retval < 0)
                goto out;
 
-       dir_page = getname(dir_name);
-       retval = PTR_ERR(dir_page);
-       if (IS_ERR(dir_page))
+       dir = getname(dir_name);
+       retval = PTR_ERR(dir);
+       if (IS_ERR(dir))
                goto out1;
 
        retval = copy_mount_string(dev_name, &kernel_dev);
@@ -807,7 +807,7 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
                }
        }
 
-       retval = do_mount(kernel_dev, dir_page, kernel_type,
+       retval = do_mount(kernel_dev, dir->name, kernel_type,
                        flags, (void*)data_page);
 
  out4:
@@ -815,7 +815,7 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
  out3:
        kfree(kernel_dev);
  out2:
-       putname(dir_page);
+       putname(dir);
  out1:
        kfree(kernel_type);
  out:
index 4f2bebc276c52f3ca60b75fbff9eeea8ea21bbe5..8b9011b67041ddcd57dbcc42e77fa7d0d8b05f7e 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -59,7 +59,6 @@
 #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"
@@ -106,7 +105,7 @@ static inline void put_binfmt(struct linux_binfmt * fmt)
 SYSCALL_DEFINE1(uselib, const char __user *, library)
 {
        struct file *file;
-       char *tmp = getname(library);
+       struct filename *tmp = getname(library);
        int error = PTR_ERR(tmp);
        static const struct open_flags uselib_flags = {
                .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
@@ -392,7 +391,7 @@ struct user_arg_ptr {
        union {
                const char __user *const __user *native;
 #ifdef CONFIG_COMPAT
-               compat_uptr_t __user *compat;
+               const compat_uptr_t __user *compat;
 #endif
        } ptr;
 };
@@ -752,13 +751,14 @@ struct file *open_exec(const char *name)
 {
        struct file *file;
        int err;
+       struct filename tmp = { .name = name };
        static const struct open_flags open_exec_flags = {
                .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
                .acc_mode = MAY_EXEC | MAY_OPEN,
                .intent = LOOKUP_OPEN
        };
 
-       file = do_filp_open(AT_FDCWD, name, &open_exec_flags, LOOKUP_FOLLOW);
+       file = do_filp_open(AT_FDCWD, &tmp, &open_exec_flags, LOOKUP_FOLLOW);
        if (IS_ERR(file))
                goto out;
 
@@ -1574,9 +1574,9 @@ int do_execve(const char *filename,
 }
 
 #ifdef CONFIG_COMPAT
-int compat_do_execve(char *filename,
-       compat_uptr_t __user *__argv,
-       compat_uptr_t __user *__envp,
+int compat_do_execve(const char *filename,
+       const compat_uptr_t __user *__argv,
+       const compat_uptr_t __user *__envp,
        struct pt_regs *regs)
 {
        struct user_arg_ptr argv = {
@@ -1658,3 +1658,56 @@ int get_dumpable(struct mm_struct *mm)
 {
        return __get_dumpable(mm->flags);
 }
+
+#ifdef __ARCH_WANT_SYS_EXECVE
+SYSCALL_DEFINE3(execve,
+               const char __user *, filename,
+               const char __user *const __user *, argv,
+               const char __user *const __user *, envp)
+{
+       struct filename *path = getname(filename);
+       int error = PTR_ERR(path);
+       if (!IS_ERR(path)) {
+               error = do_execve(path->name, argv, envp, current_pt_regs());
+               putname(path);
+       }
+       return error;
+}
+#ifdef CONFIG_COMPAT
+asmlinkage long compat_sys_execve(const char __user * filename,
+       const compat_uptr_t __user * argv,
+       const compat_uptr_t __user * envp)
+{
+       struct filename *path = getname(filename);
+       int error = PTR_ERR(path);
+       if (!IS_ERR(path)) {
+               error = compat_do_execve(path->name, argv, envp,
+                                                       current_pt_regs());
+               putname(path);
+       }
+       return error;
+}
+#endif
+#endif
+
+#ifdef __ARCH_WANT_KERNEL_EXECVE
+int kernel_execve(const char *filename,
+                 const char *const argv[],
+                 const char *const envp[])
+{
+       struct pt_regs *p = current_pt_regs();
+       int ret;
+
+       ret = do_execve(filename,
+                       (const char __user *const __user *)argv,
+                       (const char __user *const __user *)envp, p);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * We were successful.  We won't be returning to our caller, but
+        * instead to user space by manipulating the kernel stack.
+        */
+       ret_from_kernel_execve(p);
+}
+#endif
index 1585db1aa3651a3eb2fbe586156fd5bd270f5b82..f936cb50dc0d524250dae6d6ac5382db5c1f25b7 100644 (file)
@@ -814,8 +814,8 @@ static int _write_mirror(struct ore_io_state *ios, int cur_comp)
                        struct bio *bio;
 
                        if (per_dev != master_dev) {
-                               bio = bio_kmalloc(GFP_KERNEL,
-                                                 master_dev->bio->bi_max_vecs);
+                               bio = bio_clone_kmalloc(master_dev->bio,
+                                                       GFP_KERNEL);
                                if (unlikely(!bio)) {
                                        ORE_DBGMSG(
                                              "Failed to allocate BIO size=%u\n",
@@ -824,7 +824,6 @@ static int _write_mirror(struct ore_io_state *ios, int cur_comp)
                                        goto out;
                                }
 
-                               __bio_clone(bio, master_dev->bio);
                                bio->bi_bdev = NULL;
                                bio->bi_next = NULL;
                                per_dev->offset = master_dev->offset;
index 59e3bbfac0b17af51d9101b0d35dc6414ad53187..5e59280d42d779fb13fe9171d22d24ea4fc81095 100644 (file)
@@ -389,8 +389,6 @@ static int exofs_sync_fs(struct super_block *sb, int wait)
        if (unlikely(ret))
                goto out;
 
-       lock_super(sb);
-
        ios->length = offsetof(struct exofs_fscb, s_dev_table_oid);
        memset(fscb, 0, ios->length);
        fscb->s_nextid = cpu_to_le64(sbi->s_nextid);
@@ -406,8 +404,6 @@ static int exofs_sync_fs(struct super_block *sb, int wait)
        if (unlikely(ret))
                EXOFS_ERR("%s: ore_write failed.\n", __func__);
 
-
-       unlock_super(sb);
 out:
        EXOFS_DBGMSG("s_nextid=0x%llx ret=%d\n", _LLU(sbi->s_nextid), ret);
        ore_put_io_state(ios);
index 17ae5c83d2346353272fb0c42ed52f1a20aa3c70..29e79713c7eb6ccd37eac31c20c02fb5fd826744 100644 (file)
@@ -2578,11 +2578,9 @@ out:
 static int ext3_unfreeze(struct super_block *sb)
 {
        if (!(sb->s_flags & MS_RDONLY)) {
-               lock_super(sb);
                /* Reser the needs_recovery flag before the fs is unlocked. */
                EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
                ext3_commit_super(sb, EXT3_SB(sb)->s_es, 1);
-               unlock_super(sb);
                journal_unlock_updates(EXT3_SB(sb)->s_journal);
        }
        return 0;
@@ -2602,7 +2600,6 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
 #endif
 
        /* Store the original options */
-       lock_super(sb);
        old_sb_flags = sb->s_flags;
        old_opts.s_mount_opt = sbi->s_mount_opt;
        old_opts.s_resuid = sbi->s_resuid;
@@ -2708,8 +2705,6 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
                    old_opts.s_qf_names[i] != sbi->s_qf_names[i])
                        kfree(old_opts.s_qf_names[i]);
 #endif
-       unlock_super(sb);
-
        if (enable_quota)
                dquot_resume(sb, -1);
        return 0;
@@ -2728,7 +2723,6 @@ restore_opts:
                sbi->s_qf_names[i] = old_opts.s_qf_names[i];
        }
 #endif
-       unlock_super(sb);
        return err;
 }
 
index bca6d0a1255ecab0a1a8ec2b86032296a7a49e13..2a182342442edc772bdfafc11eb55d6639db6805 100644 (file)
@@ -571,7 +571,7 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
        int short_len = 0, fill_len = 0;
        int ret = 0;
 
-       lock_super(sb);
+       mutex_lock(&sbi->s_lock);
 
        cpos = filp->f_pos;
        /* Fake . and .. for the root directory. */
@@ -693,7 +693,7 @@ fill_failed:
        if (unicode)
                __putname(unicode);
 out:
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_lock);
        return ret;
 }
 
index ca7e8f8bad7cd405f344f5983da364a7a2d0606f..623f36f0423bf0e7fb584945868089e5a6746482 100644 (file)
@@ -71,8 +71,9 @@ struct msdos_sb_info {
        unsigned long root_cluster;   /* first cluster of the root directory */
        unsigned long fsinfo_sector;  /* sector number of FAT32 fsinfo */
        struct mutex fat_lock;
-       unsigned int prev_free;       /* previously allocated cluster number */
-       unsigned int free_clusters;   /* -1 if undefined */
+       struct mutex s_lock;
+       unsigned int prev_free;      /* previously allocated cluster number */
+       unsigned int free_clusters;  /* -1 if undefined */
        unsigned int free_clus_valid; /* is free_clusters valid? */
        struct fat_mount_options options;
        struct nls_table *nls_disk;   /* Codepage used on disk */
index 76f60c642c06399b1bf8696ff515be9a99ffc922..5bafaad0053059502b33219c1c1e2b8deb0e5e58 100644 (file)
@@ -673,9 +673,9 @@ static int fat_write_inode(struct inode *inode, struct writeback_control *wbc)
        if (inode->i_ino == MSDOS_FSINFO_INO) {
                struct super_block *sb = inode->i_sb;
 
-               lock_super(sb);
+               mutex_lock(&MSDOS_SB(sb)->s_lock);
                err = fat_clusters_flush(sb);
-               unlock_super(sb);
+               mutex_unlock(&MSDOS_SB(sb)->s_lock);
        } else
                err = __fat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
 
@@ -1268,6 +1268,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
                b = (struct fat_boot_sector *) bh->b_data;
        }
 
+       mutex_init(&sbi->s_lock);
        sbi->cluster_size = sb->s_blocksize * sbi->sec_per_clus;
        sbi->cluster_bits = ffs(sbi->cluster_size) - 1;
        sbi->fats = b->fats;
index c1055e778fff51a980105797ad82ce4c28005691..e2cfda94a28d249fd85961747b625a3c8b5bd100 100644 (file)
@@ -208,7 +208,7 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
        struct inode *inode;
        int err;
 
-       lock_super(sb);
+       mutex_lock(&MSDOS_SB(sb)->s_lock);
        err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
        switch (err) {
        case -ENOENT:
@@ -221,7 +221,7 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
        default:
                inode = ERR_PTR(err);
        }
-       unlock_super(sb);
+       mutex_unlock(&MSDOS_SB(sb)->s_lock);
        return d_splice_alias(inode, dentry);
 }
 
@@ -273,7 +273,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        unsigned char msdos_name[MSDOS_NAME];
        int err, is_hid;
 
-       lock_super(sb);
+       mutex_lock(&MSDOS_SB(sb)->s_lock);
 
        err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
                                msdos_name, &MSDOS_SB(sb)->options);
@@ -302,7 +302,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 
        d_instantiate(dentry, inode);
 out:
-       unlock_super(sb);
+       mutex_unlock(&MSDOS_SB(sb)->s_lock);
        if (!err)
                err = fat_flush_inodes(sb, dir, inode);
        return err;
@@ -316,7 +316,7 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
        struct fat_slot_info sinfo;
        int err;
 
-       lock_super(sb);
+       mutex_lock(&MSDOS_SB(sb)->s_lock);
        /*
         * Check whether the directory is not in use, then check
         * whether it is empty.
@@ -337,7 +337,7 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
        inode->i_ctime = CURRENT_TIME_SEC;
        fat_detach(inode);
 out:
-       unlock_super(sb);
+       mutex_unlock(&MSDOS_SB(sb)->s_lock);
        if (!err)
                err = fat_flush_inodes(sb, dir, inode);
 
@@ -354,7 +354,7 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        struct timespec ts;
        int err, is_hid, cluster;
 
-       lock_super(sb);
+       mutex_lock(&MSDOS_SB(sb)->s_lock);
 
        err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
                                msdos_name, &MSDOS_SB(sb)->options);
@@ -392,14 +392,14 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 
        d_instantiate(dentry, inode);
 
-       unlock_super(sb);
+       mutex_unlock(&MSDOS_SB(sb)->s_lock);
        fat_flush_inodes(sb, dir, inode);
        return 0;
 
 out_free:
        fat_free_clusters(dir, cluster);
 out:
-       unlock_super(sb);
+       mutex_unlock(&MSDOS_SB(sb)->s_lock);
        return err;
 }
 
@@ -411,7 +411,7 @@ static int msdos_unlink(struct inode *dir, struct dentry *dentry)
        struct fat_slot_info sinfo;
        int err;
 
-       lock_super(sb);
+       mutex_lock(&MSDOS_SB(sb)->s_lock);
        err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
        if (err)
                goto out;
@@ -423,7 +423,7 @@ static int msdos_unlink(struct inode *dir, struct dentry *dentry)
        inode->i_ctime = CURRENT_TIME_SEC;
        fat_detach(inode);
 out:
-       unlock_super(sb);
+       mutex_unlock(&MSDOS_SB(sb)->s_lock);
        if (!err)
                err = fat_flush_inodes(sb, dir, inode);
 
@@ -606,7 +606,7 @@ static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,
        unsigned char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME];
        int err, is_hid;
 
-       lock_super(sb);
+       mutex_lock(&MSDOS_SB(sb)->s_lock);
 
        err = msdos_format_name(old_dentry->d_name.name,
                                old_dentry->d_name.len, old_msdos_name,
@@ -625,7 +625,7 @@ static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,
        err = do_msdos_rename(old_dir, old_msdos_name, old_dentry,
                              new_dir, new_msdos_name, new_dentry, is_hid);
 out:
-       unlock_super(sb);
+       mutex_unlock(&MSDOS_SB(sb)->s_lock);
        if (!err)
                err = fat_flush_inodes(sb, old_dir, new_dir);
        return err;
index e535dd75b986779f8910831c8bafba44ab2a5e71..ac959d655e7d7f7dd92448437b58ec4fe81ce1ab 100644 (file)
@@ -721,7 +721,7 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
        struct dentry *alias;
        int err;
 
-       lock_super(sb);
+       mutex_lock(&MSDOS_SB(sb)->s_lock);
 
        err = vfat_find(dir, &dentry->d_name, &sinfo);
        if (err) {
@@ -752,13 +752,13 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
                if (!S_ISDIR(inode->i_mode))
                        d_move(alias, dentry);
                iput(inode);
-               unlock_super(sb);
+               mutex_unlock(&MSDOS_SB(sb)->s_lock);
                return alias;
        } else
                dput(alias);
 
 out:
-       unlock_super(sb);
+       mutex_unlock(&MSDOS_SB(sb)->s_lock);
        dentry->d_time = dentry->d_parent->d_inode->i_version;
        dentry = d_splice_alias(inode, dentry);
        if (dentry)
@@ -766,7 +766,7 @@ out:
        return dentry;
 
 error:
-       unlock_super(sb);
+       mutex_unlock(&MSDOS_SB(sb)->s_lock);
        return ERR_PTR(err);
 }
 
@@ -779,7 +779,7 @@ static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        struct timespec ts;
        int err;
 
-       lock_super(sb);
+       mutex_lock(&MSDOS_SB(sb)->s_lock);
 
        ts = CURRENT_TIME_SEC;
        err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo);
@@ -800,7 +800,7 @@ static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        dentry->d_time = dentry->d_parent->d_inode->i_version;
        d_instantiate(dentry, inode);
 out:
-       unlock_super(sb);
+       mutex_unlock(&MSDOS_SB(sb)->s_lock);
        return err;
 }
 
@@ -811,7 +811,7 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
        struct fat_slot_info sinfo;
        int err;
 
-       lock_super(sb);
+       mutex_lock(&MSDOS_SB(sb)->s_lock);
 
        err = fat_dir_empty(inode);
        if (err)
@@ -829,7 +829,7 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
        inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
        fat_detach(inode);
 out:
-       unlock_super(sb);
+       mutex_unlock(&MSDOS_SB(sb)->s_lock);
 
        return err;
 }
@@ -841,7 +841,7 @@ static int vfat_unlink(struct inode *dir, struct dentry *dentry)
        struct fat_slot_info sinfo;
        int err;
 
-       lock_super(sb);
+       mutex_lock(&MSDOS_SB(sb)->s_lock);
 
        err = vfat_find(dir, &dentry->d_name, &sinfo);
        if (err)
@@ -854,7 +854,7 @@ static int vfat_unlink(struct inode *dir, struct dentry *dentry)
        inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
        fat_detach(inode);
 out:
-       unlock_super(sb);
+       mutex_unlock(&MSDOS_SB(sb)->s_lock);
 
        return err;
 }
@@ -867,7 +867,7 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        struct timespec ts;
        int err, cluster;
 
-       lock_super(sb);
+       mutex_lock(&MSDOS_SB(sb)->s_lock);
 
        ts = CURRENT_TIME_SEC;
        cluster = fat_alloc_new_dir(dir, &ts);
@@ -896,13 +896,13 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        dentry->d_time = dentry->d_parent->d_inode->i_version;
        d_instantiate(dentry, inode);
 
-       unlock_super(sb);
+       mutex_unlock(&MSDOS_SB(sb)->s_lock);
        return 0;
 
 out_free:
        fat_free_clusters(dir, cluster);
 out:
-       unlock_super(sb);
+       mutex_unlock(&MSDOS_SB(sb)->s_lock);
        return err;
 }
 
@@ -921,7 +921,7 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
        old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
        old_inode = old_dentry->d_inode;
        new_inode = new_dentry->d_inode;
-       lock_super(sb);
+       mutex_lock(&MSDOS_SB(sb)->s_lock);
        err = vfat_find(old_dir, &old_dentry->d_name, &old_sinfo);
        if (err)
                goto out;
@@ -996,7 +996,7 @@ out:
        brelse(sinfo.bh);
        brelse(dotdot_bh);
        brelse(old_sinfo.bh);
-       unlock_super(sb);
+       mutex_unlock(&MSDOS_SB(sb)->s_lock);
 
        return err;
 
index 0f1bda4bebfaa77280a1234a2b8e19edb4b8d94b..d3b5fa80b71b76a973919a6b9cfa2ebb34096adf 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -922,6 +922,9 @@ SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags)
        if ((flags & ~O_CLOEXEC) != 0)
                return -EINVAL;
 
+       if (unlikely(oldfd == newfd))
+               return -EINVAL;
+
        if (newfd >= rlimit(RLIMIT_NOFILE))
                return -EMFILE;
 
index dac67923330f76eff9f4f961d73e5a3b1f1053db..a72bf9ddd0d2b56781bc84b591f45ff4e4627a93 100644 (file)
@@ -36,7 +36,7 @@ struct files_stat_struct files_stat = {
        .max_files = NR_FILE
 };
 
-DEFINE_LGLOCK(files_lglock);
+DEFINE_STATIC_LGLOCK(files_lglock);
 
 /* SLAB cache for file structures */
 static struct kmem_cache *filp_cachep __read_mostly;
index 96f24286667adf1aefe4a4c2b4fc2fc67eb19880..da165f6adcbfa67a12f9f19363692ab6c5d00d19 100644 (file)
@@ -124,7 +124,7 @@ EXPORT_SYMBOL(unregister_filesystem);
 static int fs_index(const char __user * __name)
 {
        struct file_system_type * tmp;
-       char * name;
+       struct filename *name;
        int err, index;
 
        name = getname(__name);
@@ -135,7 +135,7 @@ static int fs_index(const char __user * __name)
        err = -EINVAL;
        read_lock(&file_systems_lock);
        for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
-               if (strcmp(tmp->name,name) == 0) {
+               if (strcmp(tmp->name, name->name) == 0) {
                        err = index;
                        break;
                }
index 401b6c6248aeba3a8f6cf2d4069ac1ec2b1ae72b..51ea267d444c4d7aef1259521aa1f06154f26d13 100644 (file)
@@ -249,7 +249,7 @@ static bool inode_dirtied_after(struct inode *inode, unsigned long t)
 }
 
 /*
- * Move expired (dirtied after work->older_than_this) dirty inodes from
+ * Move expired (dirtied before work->older_than_this) dirty inodes from
  * @delaying_queue to @dispatch_queue.
  */
 static int move_expired_inodes(struct list_head *delaying_queue,
index e8ed6d4a6181132ff47960dc118cd6fb60c1b81c..4767774a5f3e7d9c61b5f6ac67571bd450b331ee 100644 (file)
@@ -161,6 +161,8 @@ static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid,
        case GFS2_SMALL_FH_SIZE:
        case GFS2_LARGE_FH_SIZE:
        case GFS2_OLD_FH_SIZE:
+               if (fh_len < GFS2_SMALL_FH_SIZE)
+                       return NULL;
                this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
                this.no_formal_ino |= be32_to_cpu(fh[1]);
                this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
@@ -180,6 +182,8 @@ static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid,
        switch (fh_type) {
        case GFS2_LARGE_FH_SIZE:
        case GFS2_OLD_FH_SIZE:
+               if (fh_len < GFS2_LARGE_FH_SIZE)
+                       return NULL;
                parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32;
                parent.no_formal_ino |= be32_to_cpu(fh[5]);
                parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32;
index 1fe731337f0790add39e1d4870f4d9bb8174fb8b..9c88da0e855a1001fd50e9979c3cc487d7bc80dc 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __UM_FS_HOSTFS
 #define __UM_FS_HOSTFS
 
-#include "os.h"
+#include <os.h>
 
 /*
  * These are exactly the same definitions as in fs.h, but the names are
index 6c9f3a9d5e211adcadb8e93c80bbd7b12d4460db..457addc5c91f2f2da42092d9f193a47aa8f678dd 100644 (file)
@@ -16,8 +16,8 @@
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include "hostfs.h"
-#include "init.h"
-#include "kern.h"
+#include <init.h>
+#include <kern.h>
 
 struct hostfs_inode_info {
        int fd;
@@ -848,9 +848,11 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
            attr->ia_size != i_size_read(inode)) {
                int error;
 
-               error = vmtruncate(inode, attr->ia_size);
-               if (err)
-                       return err;
+               error = inode_newsize_ok(inode, attr->ia_size);
+               if (error)
+                       return error;
+
+               truncate_setsize(inode, attr->ia_size);
        }
 
        setattr_copy(inode, attr);
index a74ad0d371c2298b84b3dc735990d71ed68aede3..67838f3aa20a8fa6937eb6e48b39a9bef15d51aa 100644 (file)
@@ -15,7 +15,6 @@
 #include <sys/types.h>
 #include <sys/vfs.h>
 #include "hostfs.h"
-#include "os.h"
 #include <utime.h>
 
 static void stat64_to_hostfs(const struct stat64 *buf, struct hostfs_stat *p)
index bc28bf077a6abe92b4041be6f6057cd6815fd57b..a3076228523db4db7a105a966f6049a8570b705c 100644 (file)
@@ -398,7 +398,6 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
        *flags |= MS_NOATIME;
        
        hpfs_lock(s);
-       lock_super(s);
        uid = sbi->sb_uid; gid = sbi->sb_gid;
        umask = 0777 & ~sbi->sb_mode;
        lowercase = sbi->sb_lowercase;
@@ -431,12 +430,10 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
 
        replace_mount_options(s, new_opts);
 
-       unlock_super(s);
        hpfs_unlock(s);
        return 0;
 
 out_err:
-       unlock_super(s);
        hpfs_unlock(s);
        kfree(new_opts);
        return -EINVAL;
index c1dffe47fde212b75daa69a0860255ee39b29285..78f21f8dc2ecf4caf8427bdab5e1deb0c3470952 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/pid_namespace.h>
 #include <linux/namei.h>
 #include <asm/uaccess.h>
-#include "os.h"
+#include <os.h>
 
 static struct inode *get_inode(struct super_block *, struct dentry *);
 
@@ -674,7 +674,7 @@ static struct inode *get_inode(struct super_block *sb, struct dentry *dentry)
 
        if (!inode) {
                dput(dentry);
-               return ERR_PTR(-ENOMEM);
+               return NULL;
        }
 
        if (S_ISDIR(dentry->d_inode->i_mode)) {
index 371bcc4b1697df808e506a6f88735209dec17dd8..916b7cbf3e3e4fae7bc831c66373b5d5ea7a3c4a 100644 (file)
@@ -97,8 +97,8 @@ struct open_flags {
        int acc_mode;
        int intent;
 };
-extern struct file *do_filp_open(int dfd, const char *pathname,
-               const struct open_flags *op, int lookup_flags);
+extern struct file *do_filp_open(int dfd, struct filename *pathname,
+               const struct open_flags *op, int flags);
 extern struct file *do_file_open_root(struct dentry *, struct vfsmount *,
                const char *, const struct open_flags *, int lookup_flags);
 
index 1d3804492aa77d7ca4440d087fd415febc2e3681..2b4f2358eadbb063fab1fb2c275e9cad1151bd6c 100644 (file)
@@ -175,7 +175,7 @@ static struct dentry *isofs_fh_to_parent(struct super_block *sb,
 {
        struct isofs_fid *ifid = (struct isofs_fid *)fid;
 
-       if (fh_type != 2)
+       if (fh_len < 2 || fh_type != 2)
                return NULL;
 
        return isofs_export_iget(sb,
index ff487954cd96f1447b254b28a41fcdbd82b61b55..d3d8799e2187233e23e1614990443203d4fff1ad 100644 (file)
@@ -100,6 +100,10 @@ static int jffs2_sync_fs(struct super_block *sb, int wait)
 {
        struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
 
+#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
+       cancel_delayed_work_sync(&c->wbuf_dwork);
+#endif
+
        mutex_lock(&c->alloc_sem);
        jffs2_flush_wbuf_pad(c);
        mutex_unlock(&c->alloc_sem);
index 6f4529d3697fd3f97d5b018dbe9f5c0362cee034..a6597d60d76de751224243ddfe6d990cd6de7e87 100644 (file)
@@ -1044,10 +1044,10 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c,
        ops.datbuf = NULL;
 
        ret = mtd_read_oob(c->mtd, jeb->offset, &ops);
-       if (ret || ops.oobretlen != ops.ooblen) {
+       if ((ret && !mtd_is_bitflip(ret)) || ops.oobretlen != ops.ooblen) {
                pr_err("cannot read OOB for EB at %08x, requested %zd bytes, read %zd bytes, error %d\n",
                       jeb->offset, ops.ooblen, ops.oobretlen, ret);
-               if (!ret)
+               if (!ret || mtd_is_bitflip(ret))
                        ret = -EIO;
                return ret;
        }
@@ -1086,10 +1086,10 @@ int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c,
        ops.datbuf = NULL;
 
        ret = mtd_read_oob(c->mtd, jeb->offset, &ops);
-       if (ret || ops.oobretlen != ops.ooblen) {
+       if ((ret && !mtd_is_bitflip(ret)) || ops.oobretlen != ops.ooblen) {
                pr_err("cannot read OOB for EB at %08x, requested %zd bytes, read %zd bytes, error %d\n",
                       jeb->offset, ops.ooblen, ops.oobretlen, ret);
-               if (!ret)
+               if (!ret || mtd_is_bitflip(ret))
                        ret = -EIO;
                return ret;
        }
index 7ef14b3c5bee9460609d863a973f0dfad93f163c..e4fb3ba5a58a3d50eb11a0f9533ca58ae5150283 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/utsname.h>
 #include <linux/kernel.h>
 #include <linux/ktime.h>
 #include <linux/slab.h>
@@ -19,6 +18,8 @@
 
 #include <asm/unaligned.h>
 
+#include "netns.h"
+
 #define NLMDBG_FACILITY                NLMDBG_MONITOR
 #define NSM_PROGRAM            100024
 #define NSM_VERSION            1
@@ -40,6 +41,7 @@ struct nsm_args {
        u32                     proc;
 
        char                    *mon_name;
+       char                    *nodename;
 };
 
 struct nsm_res {
@@ -70,7 +72,7 @@ static struct rpc_clnt *nsm_create(struct net *net)
        };
        struct rpc_create_args args = {
                .net                    = net,
-               .protocol               = XPRT_TRANSPORT_UDP,
+               .protocol               = XPRT_TRANSPORT_TCP,
                .address                = (struct sockaddr *)&sin,
                .addrsize               = sizeof(sin),
                .servername             = "rpc.statd",
@@ -83,10 +85,54 @@ static struct rpc_clnt *nsm_create(struct net *net)
        return rpc_create(&args);
 }
 
-static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
-                        struct net *net)
+static struct rpc_clnt *nsm_client_get(struct net *net)
 {
+       static DEFINE_MUTEX(nsm_create_mutex);
        struct rpc_clnt *clnt;
+       struct lockd_net *ln = net_generic(net, lockd_net_id);
+
+       spin_lock(&ln->nsm_clnt_lock);
+       if (ln->nsm_users) {
+               ln->nsm_users++;
+               clnt = ln->nsm_clnt;
+               spin_unlock(&ln->nsm_clnt_lock);
+               goto out;
+       }
+       spin_unlock(&ln->nsm_clnt_lock);
+
+       mutex_lock(&nsm_create_mutex);
+       clnt = nsm_create(net);
+       if (!IS_ERR(clnt)) {
+               ln->nsm_clnt = clnt;
+               smp_wmb();
+               ln->nsm_users = 1;
+       }
+       mutex_unlock(&nsm_create_mutex);
+out:
+       return clnt;
+}
+
+static void nsm_client_put(struct net *net)
+{
+       struct lockd_net *ln = net_generic(net, lockd_net_id);
+       struct rpc_clnt *clnt = ln->nsm_clnt;
+       int shutdown = 0;
+
+       spin_lock(&ln->nsm_clnt_lock);
+       if (ln->nsm_users) {
+               if (--ln->nsm_users)
+                       ln->nsm_clnt = NULL;
+               shutdown = !ln->nsm_users;
+       }
+       spin_unlock(&ln->nsm_clnt_lock);
+
+       if (shutdown)
+               rpc_shutdown_client(clnt);
+}
+
+static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
+                        struct rpc_clnt *clnt)
+{
        int             status;
        struct nsm_args args = {
                .priv           = &nsm->sm_priv,
@@ -94,31 +140,24 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
                .vers           = 3,
                .proc           = NLMPROC_NSM_NOTIFY,
                .mon_name       = nsm->sm_mon_name,
+               .nodename       = clnt->cl_nodename,
        };
        struct rpc_message msg = {
                .rpc_argp       = &args,
                .rpc_resp       = res,
        };
 
-       clnt = nsm_create(net);
-       if (IS_ERR(clnt)) {
-               status = PTR_ERR(clnt);
-               dprintk("lockd: failed to create NSM upcall transport, "
-                               "status=%d\n", status);
-               goto out;
-       }
+       BUG_ON(clnt == NULL);
 
        memset(res, 0, sizeof(*res));
 
        msg.rpc_proc = &clnt->cl_procinfo[proc];
-       status = rpc_call_sync(clnt, &msg, 0);
+       status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN);
        if (status < 0)
                dprintk("lockd: NSM upcall RPC failed, status=%d\n",
                                status);
        else
                status = 0;
-       rpc_shutdown_client(clnt);
- out:
        return status;
 }
 
@@ -138,6 +177,7 @@ int nsm_monitor(const struct nlm_host *host)
        struct nsm_handle *nsm = host->h_nsmhandle;
        struct nsm_res  res;
        int             status;
+       struct rpc_clnt *clnt;
 
        dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
 
@@ -150,7 +190,15 @@ int nsm_monitor(const struct nlm_host *host)
         */
        nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
 
-       status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, host->net);
+       clnt = nsm_client_get(host->net);
+       if (IS_ERR(clnt)) {
+               status = PTR_ERR(clnt);
+               dprintk("lockd: failed to create NSM upcall transport, "
+                               "status=%d, net=%p\n", status, host->net);
+               return status;
+       }
+
+       status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, clnt);
        if (unlikely(res.status != 0))
                status = -EIO;
        if (unlikely(status < 0)) {
@@ -182,9 +230,11 @@ void nsm_unmonitor(const struct nlm_host *host)
 
        if (atomic_read(&nsm->sm_count) == 1
         && nsm->sm_monitored && !nsm->sm_sticky) {
+               struct lockd_net *ln = net_generic(host->net, lockd_net_id);
+
                dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
 
-               status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, host->net);
+               status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, ln->nsm_clnt);
                if (res.status != 0)
                        status = -EIO;
                if (status < 0)
@@ -192,6 +242,8 @@ void nsm_unmonitor(const struct nlm_host *host)
                                        nsm->sm_name);
                else
                        nsm->sm_monitored = 0;
+
+               nsm_client_put(host->net);
        }
 }
 
@@ -430,7 +482,7 @@ static void encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp)
 {
        __be32 *p;
 
-       encode_nsm_string(xdr, utsname()->nodename);
+       encode_nsm_string(xdr, argp->nodename);
        p = xdr_reserve_space(xdr, 4 + 4 + 4);
        *p++ = cpu_to_be32(argp->prog);
        *p++ = cpu_to_be32(argp->vers);
index 4eee248ba96e441eb54e460130d3dde2f20d6ca1..5010b55628b4755bab2c3e01f1042efd20beec10 100644 (file)
@@ -12,6 +12,10 @@ struct lockd_net {
        struct delayed_work grace_period_end;
        struct lock_manager lockd_manager;
        struct list_head grace_list;
+
+       spinlock_t nsm_clnt_lock;
+       unsigned int nsm_users;
+       struct rpc_clnt *nsm_clnt;
 };
 
 extern int lockd_net_id;
index 31a63f87b80602346cc78cfead614d35f620c9cd..a2aa97d45670635c4d84ef422ea9a1d794cdce69 100644 (file)
@@ -126,7 +126,7 @@ static void restart_grace(void)
 static int
 lockd(void *vrqstp)
 {
-       int             err = 0, preverr = 0;
+       int             err = 0;
        struct svc_rqst *rqstp = vrqstp;
 
        /* try_to_freeze() is called from svc_recv() */
@@ -165,21 +165,8 @@ lockd(void *vrqstp)
                 * recvfrom routine.
                 */
                err = svc_recv(rqstp, timeout);
-               if (err == -EAGAIN || err == -EINTR) {
-                       preverr = err;
+               if (err == -EAGAIN || err == -EINTR)
                        continue;
-               }
-               if (err < 0) {
-                       if (err != preverr) {
-                               printk(KERN_WARNING "%s: unexpected error "
-                                       "from svc_recv (%d)\n", __func__, err);
-                               preverr = err;
-                       }
-                       schedule_timeout_interruptible(HZ);
-                       continue;
-               }
-               preverr = err;
-
                dprintk("lockd: request from %s\n",
                                svc_print_addr(rqstp, buf, sizeof(buf)));
 
@@ -596,6 +583,7 @@ static int lockd_init_net(struct net *net)
 
        INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender);
        INIT_LIST_HEAD(&ln->grace_list);
+       spin_lock_init(&ln->nsm_clnt_lock);
        return 0;
 }
 
index abc7dc6c490b6dc7ca6e9119c585dc10b1a2d3d9..a94e331a52a2febbf46a4df702156c1a013b2990 100644 (file)
@@ -1289,7 +1289,7 @@ EXPORT_SYMBOL(__break_lease);
 void lease_get_mtime(struct inode *inode, struct timespec *time)
 {
        struct file_lock *flock = inode->i_flock;
-       if (flock && IS_LEASE(flock) && (flock->fl_type & F_WRLCK))
+       if (flock && IS_LEASE(flock) && (flock->fl_type == F_WRLCK))
                *time = current_fs_time(inode->i_sb);
        else
                *time = inode->i_mtime;
@@ -2185,8 +2185,8 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
        } else {
                seq_printf(f, "%s ",
                               (lease_breaking(fl))
-                              ? (fl->fl_type & F_UNLCK) ? "UNLCK" : "READ "
-                              : (fl->fl_type & F_WRLCK) ? "WRITE" : "READ ");
+                              ? (fl->fl_type == F_UNLCK) ? "UNLCK" : "READ "
+                              : (fl->fl_type == F_WRLCK) ? "WRITE" : "READ ");
        }
        if (inode) {
 #ifdef WE_CAN_BREAK_LSLK_NOW
index aa30d19e9edd75acf05780cad24eadbf37fba910..d1895f30815670de8abd8a6c921443035c21a364 100644 (file)
  * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
  * PATH_MAX includes the nul terminator --RR.
  */
-static char *getname_flags(const char __user *filename, int flags, int *empty)
+void final_putname(struct filename *name)
 {
-       char *result = __getname(), *err;
+       if (name->separate) {
+               __putname(name->name);
+               kfree(name);
+       } else {
+               __putname(name);
+       }
+}
+
+#define EMBEDDED_NAME_MAX      (PATH_MAX - sizeof(struct filename))
+
+static struct filename *
+getname_flags(const char __user *filename, int flags, int *empty)
+{
+       struct filename *result, *err;
        int len;
+       long max;
+       char *kname;
 
+       result = audit_reusename(filename);
+       if (result)
+               return result;
+
+       result = __getname();
        if (unlikely(!result))
                return ERR_PTR(-ENOMEM);
 
-       len = strncpy_from_user(result, filename, PATH_MAX);
-       err = ERR_PTR(len);
-       if (unlikely(len < 0))
+       /*
+        * First, try to embed the struct filename inside the names_cache
+        * allocation
+        */
+       kname = (char *)result + sizeof(*result);
+       result->name = kname;
+       result->separate = false;
+       max = EMBEDDED_NAME_MAX;
+
+recopy:
+       len = strncpy_from_user(kname, filename, max);
+       if (unlikely(len < 0)) {
+               err = ERR_PTR(len);
                goto error;
+       }
+
+       /*
+        * Uh-oh. We have a name that's approaching PATH_MAX. Allocate a
+        * separate struct filename so we can dedicate the entire
+        * names_cache allocation for the pathname, and re-do the copy from
+        * userland.
+        */
+       if (len == EMBEDDED_NAME_MAX && max == EMBEDDED_NAME_MAX) {
+               kname = (char *)result;
+
+               result = kzalloc(sizeof(*result), GFP_KERNEL);
+               if (!result) {
+                       err = ERR_PTR(-ENOMEM);
+                       result = (struct filename *)kname;
+                       goto error;
+               }
+               result->name = kname;
+               result->separate = true;
+               max = PATH_MAX;
+               goto recopy;
+       }
 
        /* The empty path is special. */
        if (unlikely(!len)) {
@@ -140,30 +192,32 @@ static char *getname_flags(const char __user *filename, int flags, int *empty)
        }
 
        err = ERR_PTR(-ENAMETOOLONG);
-       if (likely(len < PATH_MAX)) {
-               audit_getname(result);
-               return result;
-       }
+       if (unlikely(len >= PATH_MAX))
+               goto error;
+
+       result->uptr = filename;
+       audit_getname(result);
+       return result;
 
 error:
-       __putname(result);
+       final_putname(result);
        return err;
 }
 
-char *getname(const char __user * filename)
+struct filename *
+getname(const char __user * filename)
 {
        return getname_flags(filename, 0, NULL);
 }
+EXPORT_SYMBOL(getname);
 
 #ifdef CONFIG_AUDITSYSCALL
-void putname(const char *name)
+void putname(struct filename *name)
 {
        if (unlikely(!audit_dummy_context()))
-               audit_putname(name);
-       else
-               __putname(name);
+               return audit_putname(name);
+       final_putname(name);
 }
-EXPORT_SYMBOL(putname);
 #endif
 
 static int check_acl(struct inode *inode, int mask)
@@ -692,9 +746,9 @@ static inline int may_follow_link(struct path *link, struct nameidata *nd)
        if (uid_eq(parent->i_uid, inode->i_uid))
                return 0;
 
+       audit_log_link_denied("follow_link", link);
        path_put_conditional(link, nd);
        path_put(&nd->path);
-       audit_log_link_denied("follow_link", link);
        return -EACCES;
 }
 
@@ -810,6 +864,7 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
        return error;
 
 out_put_nd_path:
+       *p = NULL;
        path_put(&nd->path);
        path_put(link);
        return error;
@@ -1962,24 +2017,29 @@ static int path_lookupat(int dfd, const char *name,
        return err;
 }
 
-static int do_path_lookup(int dfd, const char *name,
+static int filename_lookup(int dfd, struct filename *name,
                                unsigned int flags, struct nameidata *nd)
 {
-       int retval = path_lookupat(dfd, name, flags | LOOKUP_RCU, nd);
+       int retval = path_lookupat(dfd, name->name, flags | LOOKUP_RCU, nd);
        if (unlikely(retval == -ECHILD))
-               retval = path_lookupat(dfd, name, flags, nd);
+               retval = path_lookupat(dfd, name->name, flags, nd);
        if (unlikely(retval == -ESTALE))
-               retval = path_lookupat(dfd, name, flags | LOOKUP_REVAL, nd);
+               retval = path_lookupat(dfd, name->name,
+                                               flags | LOOKUP_REVAL, nd);
 
-       if (likely(!retval)) {
-               if (unlikely(!audit_dummy_context())) {
-                       if (nd->path.dentry && nd->inode)
-                               audit_inode(name, nd->path.dentry);
-               }
-       }
+       if (likely(!retval))
+               audit_inode(name, nd->path.dentry, flags & LOOKUP_PARENT);
        return retval;
 }
 
+static int do_path_lookup(int dfd, const char *name,
+                               unsigned int flags, struct nameidata *nd)
+{
+       struct filename filename = { .name = name };
+
+       return filename_lookup(dfd, &filename, flags, nd);
+}
+
 /* does lookup, returns the object with parent locked */
 struct dentry *kern_path_locked(const char *name, struct path *path)
 {
@@ -2097,13 +2157,13 @@ int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
                 struct path *path, int *empty)
 {
        struct nameidata nd;
-       char *tmp = getname_flags(name, flags, empty);
+       struct filename *tmp = getname_flags(name, flags, empty);
        int err = PTR_ERR(tmp);
        if (!IS_ERR(tmp)) {
 
                BUG_ON(flags & LOOKUP_PARENT);
 
-               err = do_path_lookup(dfd, tmp, flags, &nd);
+               err = filename_lookup(dfd, tmp, flags, &nd);
                putname(tmp);
                if (!err)
                        *path = nd.path;
@@ -2117,22 +2177,28 @@ int user_path_at(int dfd, const char __user *name, unsigned flags,
        return user_path_at_empty(dfd, name, flags, path, NULL);
 }
 
-static int user_path_parent(int dfd, const char __user *path,
-                       struct nameidata *nd, char **name)
+/*
+ * NB: most callers don't do anything directly with the reference to the
+ *     to struct filename, but the nd->last pointer points into the name string
+ *     allocated by getname. So we must hold the reference to it until all
+ *     path-walking is complete.
+ */
+static struct filename *
+user_path_parent(int dfd, const char __user *path, struct nameidata *nd)
 {
-       char *s = getname(path);
+       struct filename *s = getname(path);
        int error;
 
        if (IS_ERR(s))
-               return PTR_ERR(s);
+               return s;
 
-       error = do_path_lookup(dfd, s, LOOKUP_PARENT, nd);
-       if (error)
+       error = filename_lookup(dfd, s, LOOKUP_PARENT, nd);
+       if (error) {
                putname(s);
-       else
-               *name = s;
+               return ERR_PTR(error);
+       }
 
-       return error;
+       return s;
 }
 
 /*
@@ -2179,7 +2245,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
                return -ENOENT;
 
        BUG_ON(victim->d_parent->d_inode != dir);
-       audit_inode_child(victim, dir);
+       audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
 
        error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
        if (error)
@@ -2624,7 +2690,7 @@ out_dput:
  */
 static int do_last(struct nameidata *nd, struct path *path,
                   struct file *file, const struct open_flags *op,
-                  int *opened, const char *pathname)
+                  int *opened, struct filename *name)
 {
        struct dentry *dir = nd->path.dentry;
        int open_flag = op->open_flag;
@@ -2651,7 +2717,7 @@ static int do_last(struct nameidata *nd, struct path *path,
                error = complete_walk(nd);
                if (error)
                        return error;
-               audit_inode(pathname, nd->path.dentry);
+               audit_inode(name, nd->path.dentry, 0);
                if (open_flag & O_CREAT) {
                        error = -EISDIR;
                        goto out;
@@ -2661,7 +2727,7 @@ static int do_last(struct nameidata *nd, struct path *path,
                error = complete_walk(nd);
                if (error)
                        return error;
-               audit_inode(pathname, dir);
+               audit_inode(name, dir, 0);
                goto finish_open;
        }
 
@@ -2690,7 +2756,7 @@ static int do_last(struct nameidata *nd, struct path *path,
                if (error)
                        return error;
 
-               audit_inode(pathname, dir);
+               audit_inode(name, dir, 0);
                error = -EISDIR;
                /* trailing slashes? */
                if (nd->last.name[nd->last.len])
@@ -2720,7 +2786,7 @@ retry_lookup:
                    !S_ISREG(file->f_path.dentry->d_inode->i_mode))
                        will_truncate = false;
 
-               audit_inode(pathname, file->f_path.dentry);
+               audit_inode(name, file->f_path.dentry, 0);
                goto opened;
        }
 
@@ -2737,7 +2803,7 @@ retry_lookup:
         * create/update audit record if it already exists.
         */
        if (path->dentry->d_inode)
-               audit_inode(pathname, path->dentry);
+               audit_inode(name, path->dentry, 0);
 
        /*
         * If atomic_open() acquired write access it is dropped now due to
@@ -2802,7 +2868,7 @@ finish_lookup:
        error = -ENOTDIR;
        if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup)
                goto out;
-       audit_inode(pathname, nd->path.dentry);
+       audit_inode(name, nd->path.dentry, 0);
 finish_open:
        if (!S_ISREG(nd->inode->i_mode))
                will_truncate = false;
@@ -2870,7 +2936,7 @@ stale_open:
        goto retry_lookup;
 }
 
-static struct file *path_openat(int dfd, const char *pathname,
+static struct file *path_openat(int dfd, struct filename *pathname,
                struct nameidata *nd, const struct open_flags *op, int flags)
 {
        struct file *base = NULL;
@@ -2885,12 +2951,12 @@ static struct file *path_openat(int dfd, const char *pathname,
 
        file->f_flags = op->open_flag;
 
-       error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);
+       error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base);
        if (unlikely(error))
                goto out;
 
        current->total_link_count = 0;
-       error = link_path_walk(pathname, nd);
+       error = link_path_walk(pathname->name, nd);
        if (unlikely(error))
                goto out;
 
@@ -2936,7 +3002,7 @@ out:
        return file;
 }
 
-struct file *do_filp_open(int dfd, const char *pathname,
+struct file *do_filp_open(int dfd, struct filename *pathname,
                const struct open_flags *op, int flags)
 {
        struct nameidata nd;
@@ -2955,6 +3021,7 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
 {
        struct nameidata nd;
        struct file *file;
+       struct filename filename = { .name = name };
 
        nd.root.mnt = mnt;
        nd.root.dentry = dentry;
@@ -2964,11 +3031,11 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
        if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN)
                return ERR_PTR(-ELOOP);
 
-       file = path_openat(-1, name, &nd, op, flags | LOOKUP_RCU);
+       file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_RCU);
        if (unlikely(file == ERR_PTR(-ECHILD)))
-               file = path_openat(-1, name, &nd, op, flags);
+               file = path_openat(-1, &filename, &nd, op, flags);
        if (unlikely(file == ERR_PTR(-ESTALE)))
-               file = path_openat(-1, name, &nd, op, flags | LOOKUP_REVAL);
+               file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_REVAL);
        return file;
 }
 
@@ -3043,11 +3110,11 @@ EXPORT_SYMBOL(done_path_create);
 
 struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, int is_dir)
 {
-       char *tmp = getname(pathname);
+       struct filename *tmp = getname(pathname);
        struct dentry *res;
        if (IS_ERR(tmp))
                return ERR_CAST(tmp);
-       res = kern_path_create(dfd, tmp, path, is_dir);
+       res = kern_path_create(dfd, tmp->name, path, is_dir);
        putname(tmp);
        return res;
 }
@@ -3252,13 +3319,13 @@ out:
 static long do_rmdir(int dfd, const char __user *pathname)
 {
        int error = 0;
-       char * name;
+       struct filename *name;
        struct dentry *dentry;
        struct nameidata nd;
 
-       error = user_path_parent(dfd, pathname, &nd, &name);
-       if (error)
-               return error;
+       name = user_path_parent(dfd, pathname, &nd);
+       if (IS_ERR(name))
+               return PTR_ERR(name);
 
        switch(nd.last_type) {
        case LAST_DOTDOT:
@@ -3347,14 +3414,14 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
 static long do_unlinkat(int dfd, const char __user *pathname)
 {
        int error;
-       char *name;
+       struct filename *name;
        struct dentry *dentry;
        struct nameidata nd;
        struct inode *inode = NULL;
 
-       error = user_path_parent(dfd, pathname, &nd, &name);
-       if (error)
-               return error;
+       name = user_path_parent(dfd, pathname, &nd);
+       if (IS_ERR(name))
+               return PTR_ERR(name);
 
        error = -EISDIR;
        if (nd.last_type != LAST_NORM)
@@ -3438,7 +3505,7 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
                int, newdfd, const char __user *, newname)
 {
        int error;
-       char *from;
+       struct filename *from;
        struct dentry *dentry;
        struct path path;
 
@@ -3451,9 +3518,9 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
        if (IS_ERR(dentry))
                goto out_putname;
 
-       error = security_path_symlink(&path, dentry, from);
+       error = security_path_symlink(&path, dentry, from->name);
        if (!error)
-               error = vfs_symlink(path.dentry->d_inode, dentry, from);
+               error = vfs_symlink(path.dentry->d_inode, dentry, from->name);
        done_path_create(&path, dentry);
 out_putname:
        putname(from);
@@ -3733,17 +3800,21 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
        struct dentry *old_dentry, *new_dentry;
        struct dentry *trap;
        struct nameidata oldnd, newnd;
-       char *from;
-       char *to;
+       struct filename *from;
+       struct filename *to;
        int error;
 
-       error = user_path_parent(olddfd, oldname, &oldnd, &from);
-       if (error)
+       from = user_path_parent(olddfd, oldname, &oldnd);
+       if (IS_ERR(from)) {
+               error = PTR_ERR(from);
                goto exit;
+       }
 
-       error = user_path_parent(newdfd, newname, &newnd, &to);
-       if (error)
+       to = user_path_parent(newdfd, newname, &newnd);
+       if (IS_ERR(to)) {
+               error = PTR_ERR(to);
                goto exit1;
+       }
 
        error = -EXDEV;
        if (oldnd.path.mnt != newnd.path.mnt)
@@ -3967,7 +4038,6 @@ EXPORT_SYMBOL(follow_down_one);
 EXPORT_SYMBOL(follow_down);
 EXPORT_SYMBOL(follow_up);
 EXPORT_SYMBOL(get_write_access); /* nfsd */
-EXPORT_SYMBOL(getname);
 EXPORT_SYMBOL(lock_rename);
 EXPORT_SYMBOL(lookup_one_len);
 EXPORT_SYMBOL(page_follow_link_light);
index 7bdf7907413f0ea5f3c9e9c2de6b4002381e2064..24960626bb6bfc7b9eff78631876d4eb7ca7a40e 100644 (file)
@@ -1640,7 +1640,7 @@ static int do_change_type(struct path *path, int flag)
 /*
  * do loopback mount.
  */
-static int do_loopback(struct path *path, char *old_name,
+static int do_loopback(struct path *path, const char *old_name,
                                int recurse)
 {
        LIST_HEAD(umount_list);
@@ -1764,7 +1764,7 @@ static inline int tree_contains_unbindable(struct mount *mnt)
        return 0;
 }
 
-static int do_move_mount(struct path *path, char *old_name)
+static int do_move_mount(struct path *path, const char *old_name)
 {
        struct path old_path, parent_path;
        struct mount *p;
@@ -1917,8 +1917,8 @@ unlock:
  * create a new mount for userspace and request it to be added into the
  * namespace's tree
  */
-static int do_new_mount(struct path *path, char *type, int flags,
-                       int mnt_flags, char *name, void *data)
+static int do_new_mount(struct path *path, const char *type, int flags,
+                       int mnt_flags, const char *name, void *data)
 {
        struct vfsmount *mnt;
        int err;
@@ -2191,8 +2191,8 @@ int copy_mount_string(const void __user *data, char **where)
  * Therefore, if this magic number is present, it carries no information
  * and must be discarded.
  */
-long do_mount(char *dev_name, char *dir_name, char *type_page,
-                 unsigned long flags, void *data_page)
+long do_mount(const char *dev_name, const char *dir_name,
+               const char *type_page, unsigned long flags, void *data_page)
 {
        struct path path;
        int retval = 0;
@@ -2408,7 +2408,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
 {
        int ret;
        char *kernel_type;
-       char *kernel_dir;
+       struct filename *kernel_dir;
        char *kernel_dev;
        unsigned long data_page;
 
@@ -2430,7 +2430,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
        if (ret < 0)
                goto out_data;
 
-       ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags,
+       ret = do_mount(kernel_dev, kernel_dir->name, kernel_type, flags,
                (void *) data_page);
 
        free_page(data_page);
index db7ad719628a655f748d30257f00d95f9191ec6e..13ca196385f5faff6c88fd32e00d317cf68dcbd7 100644 (file)
@@ -95,8 +95,8 @@ config NFS_SWAP
          This option enables swapon to work on files located on NFS mounts.
 
 config NFS_V4_1
-       bool "NFS client support for NFSv4.1 (EXPERIMENTAL)"
-       depends on NFS_V4 && EXPERIMENTAL
+       bool "NFS client support for NFSv4.1"
+       depends on NFS_V4
        select SUNRPC_BACKCHANNEL
        help
          This option enables support for minor version 1 of the NFSv4 protocol
index dd392ed5f2e28ef48a85b37d0dc2ade6ab903d80..f1027b06a1a9625e8fe7b0e7c551ce13e510414d 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/bio.h>         /* struct bio */
 #include <linux/buffer_head.h> /* various write calls */
 #include <linux/prefetch.h>
+#include <linux/pagevec.h>
 
 #include "../pnfs.h"
 #include "../internal.h"
@@ -162,25 +163,39 @@ static struct bio *bl_alloc_init_bio(int npg, sector_t isect,
        return bio;
 }
 
-static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw,
+static struct bio *do_add_page_to_bio(struct bio *bio, int npg, int rw,
                                      sector_t isect, struct page *page,
                                      struct pnfs_block_extent *be,
                                      void (*end_io)(struct bio *, int err),
-                                     struct parallel_io *par)
+                                     struct parallel_io *par,
+                                     unsigned int offset, int len)
 {
+       isect = isect + (offset >> SECTOR_SHIFT);
+       dprintk("%s: npg %d rw %d isect %llu offset %u len %d\n", __func__,
+               npg, rw, (unsigned long long)isect, offset, len);
 retry:
        if (!bio) {
                bio = bl_alloc_init_bio(npg, isect, be, end_io, par);
                if (!bio)
                        return ERR_PTR(-ENOMEM);
        }
-       if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) {
+       if (bio_add_page(bio, page, len, offset) < len) {
                bio = bl_submit_bio(rw, bio);
                goto retry;
        }
        return bio;
 }
 
+static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw,
+                                     sector_t isect, struct page *page,
+                                     struct pnfs_block_extent *be,
+                                     void (*end_io)(struct bio *, int err),
+                                     struct parallel_io *par)
+{
+       return do_add_page_to_bio(bio, npg, rw, isect, page, be,
+                                 end_io, par, 0, PAGE_CACHE_SIZE);
+}
+
 /* This is basically copied from mpage_end_io_read */
 static void bl_end_io_read(struct bio *bio, int err)
 {
@@ -228,14 +243,6 @@ bl_end_par_io_read(void *data, int unused)
        schedule_work(&rdata->task.u.tk_work);
 }
 
-static bool
-bl_check_alignment(u64 offset, u32 len, unsigned long blkmask)
-{
-       if ((offset & blkmask) || (len & blkmask))
-               return false;
-       return true;
-}
-
 static enum pnfs_try_status
 bl_read_pagelist(struct nfs_read_data *rdata)
 {
@@ -246,15 +253,15 @@ bl_read_pagelist(struct nfs_read_data *rdata)
        sector_t isect, extent_length = 0;
        struct parallel_io *par;
        loff_t f_offset = rdata->args.offset;
+       size_t bytes_left = rdata->args.count;
+       unsigned int pg_offset, pg_len;
        struct page **pages = rdata->args.pages;
        int pg_index = rdata->args.pgbase >> PAGE_CACHE_SHIFT;
+       const bool is_dio = (header->dreq != NULL);
 
        dprintk("%s enter nr_pages %u offset %lld count %u\n", __func__,
               rdata->pages.npages, f_offset, (unsigned int)rdata->args.count);
 
-       if (!bl_check_alignment(f_offset, rdata->args.count, PAGE_CACHE_MASK))
-               goto use_mds;
-
        par = alloc_parallel(rdata);
        if (!par)
                goto use_mds;
@@ -284,36 +291,53 @@ bl_read_pagelist(struct nfs_read_data *rdata)
                                extent_length = min(extent_length, cow_length);
                        }
                }
+
+               if (is_dio) {
+                       pg_offset = f_offset & ~PAGE_CACHE_MASK;
+                       if (pg_offset + bytes_left > PAGE_CACHE_SIZE)
+                               pg_len = PAGE_CACHE_SIZE - pg_offset;
+                       else
+                               pg_len = bytes_left;
+
+                       f_offset += pg_len;
+                       bytes_left -= pg_len;
+                       isect += (pg_offset >> SECTOR_SHIFT);
+               } else {
+                       pg_offset = 0;
+                       pg_len = PAGE_CACHE_SIZE;
+               }
+
                hole = is_hole(be, isect);
                if (hole && !cow_read) {
                        bio = bl_submit_bio(READ, bio);
                        /* Fill hole w/ zeroes w/o accessing device */
                        dprintk("%s Zeroing page for hole\n", __func__);
-                       zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE);
+                       zero_user_segment(pages[i], pg_offset, pg_len);
                        print_page(pages[i]);
                        SetPageUptodate(pages[i]);
                } else {
                        struct pnfs_block_extent *be_read;
 
                        be_read = (hole && cow_read) ? cow_read : be;
-                       bio = bl_add_page_to_bio(bio, rdata->pages.npages - i,
+                       bio = do_add_page_to_bio(bio, rdata->pages.npages - i,
                                                 READ,
                                                 isect, pages[i], be_read,
-                                                bl_end_io_read, par);
+                                                bl_end_io_read, par,
+                                                pg_offset, pg_len);
                        if (IS_ERR(bio)) {
                                header->pnfs_error = PTR_ERR(bio);
                                bio = NULL;
                                goto out;
                        }
                }
-               isect += PAGE_CACHE_SECTORS;
+               isect += (pg_len >> SECTOR_SHIFT);
                extent_length -= PAGE_CACHE_SECTORS;
        }
        if ((isect << SECTOR_SHIFT) >= header->inode->i_size) {
                rdata->res.eof = 1;
-               rdata->res.count = header->inode->i_size - f_offset;
+               rdata->res.count = header->inode->i_size - rdata->args.offset;
        } else {
-               rdata->res.count = (isect << SECTOR_SHIFT) - f_offset;
+               rdata->res.count = (isect << SECTOR_SHIFT) - rdata->args.offset;
        }
 out:
        bl_put_extent(be);
@@ -461,6 +485,106 @@ map_block(struct buffer_head *bh, sector_t isect, struct pnfs_block_extent *be)
        return;
 }
 
+static void
+bl_read_single_end_io(struct bio *bio, int error)
+{
+       struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+       struct page *page = bvec->bv_page;
+
+       /* Only one page in bvec */
+       unlock_page(page);
+}
+
+static int
+bl_do_readpage_sync(struct page *page, struct pnfs_block_extent *be,
+                   unsigned int offset, unsigned int len)
+{
+       struct bio *bio;
+       struct page *shadow_page;
+       sector_t isect;
+       char *kaddr, *kshadow_addr;
+       int ret = 0;
+
+       dprintk("%s: offset %u len %u\n", __func__, offset, len);
+
+       shadow_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
+       if (shadow_page == NULL)
+               return -ENOMEM;
+
+       bio = bio_alloc(GFP_NOIO, 1);
+       if (bio == NULL)
+               return -ENOMEM;
+
+       isect = (page->index << PAGE_CACHE_SECTOR_SHIFT) +
+               (offset / SECTOR_SIZE);
+
+       bio->bi_sector = isect - be->be_f_offset + be->be_v_offset;
+       bio->bi_bdev = be->be_mdev;
+       bio->bi_end_io = bl_read_single_end_io;
+
+       lock_page(shadow_page);
+       if (bio_add_page(bio, shadow_page,
+                        SECTOR_SIZE, round_down(offset, SECTOR_SIZE)) == 0) {
+               unlock_page(shadow_page);
+               bio_put(bio);
+               return -EIO;
+       }
+
+       submit_bio(READ, bio);
+       wait_on_page_locked(shadow_page);
+       if (unlikely(!test_bit(BIO_UPTODATE, &bio->bi_flags))) {
+               ret = -EIO;
+       } else {
+               kaddr = kmap_atomic(page);
+               kshadow_addr = kmap_atomic(shadow_page);
+               memcpy(kaddr + offset, kshadow_addr + offset, len);
+               kunmap_atomic(kshadow_addr);
+               kunmap_atomic(kaddr);
+       }
+       __free_page(shadow_page);
+       bio_put(bio);
+
+       return ret;
+}
+
+static int
+bl_read_partial_page_sync(struct page *page, struct pnfs_block_extent *be,
+                         unsigned int dirty_offset, unsigned int dirty_len,
+                         bool full_page)
+{
+       int ret = 0;
+       unsigned int start, end;
+
+       if (full_page) {
+               start = 0;
+               end = PAGE_CACHE_SIZE;
+       } else {
+               start = round_down(dirty_offset, SECTOR_SIZE);
+               end = round_up(dirty_offset + dirty_len, SECTOR_SIZE);
+       }
+
+       dprintk("%s: offset %u len %d\n", __func__, dirty_offset, dirty_len);
+       if (!be) {
+               zero_user_segments(page, start, dirty_offset,
+                                  dirty_offset + dirty_len, end);
+               if (start == 0 && end == PAGE_CACHE_SIZE &&
+                   trylock_page(page)) {
+                       SetPageUptodate(page);
+                       unlock_page(page);
+               }
+               return ret;
+       }
+
+       if (start != dirty_offset)
+               ret = bl_do_readpage_sync(page, be, start, dirty_offset - start);
+
+       if (!ret && (dirty_offset + dirty_len < end))
+               ret = bl_do_readpage_sync(page, be, dirty_offset + dirty_len,
+                                         end - dirty_offset - dirty_len);
+
+       return ret;
+}
+
 /* Given an unmapped page, zero it or read in page for COW, page is locked
  * by caller.
  */
@@ -494,7 +618,6 @@ init_page_for_write(struct page *page, struct pnfs_block_extent *cow_read)
        SetPageUptodate(page);
 
 cleanup:
-       bl_put_extent(cow_read);
        if (bh)
                free_buffer_head(bh);
        if (ret) {
@@ -566,6 +689,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync)
        struct parallel_io *par = NULL;
        loff_t offset = wdata->args.offset;
        size_t count = wdata->args.count;
+       unsigned int pg_offset, pg_len, saved_len;
        struct page **pages = wdata->args.pages;
        struct page *page;
        pgoff_t index;
@@ -574,10 +698,13 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync)
            NFS_SERVER(header->inode)->pnfs_blksize >> PAGE_CACHE_SHIFT;
 
        dprintk("%s enter, %Zu@%lld\n", __func__, count, offset);
-       /* Check for alignment first */
-       if (!bl_check_alignment(offset, count, PAGE_CACHE_MASK))
-               goto out_mds;
 
+       if (header->dreq != NULL &&
+           (!IS_ALIGNED(offset, NFS_SERVER(header->inode)->pnfs_blksize) ||
+            !IS_ALIGNED(count, NFS_SERVER(header->inode)->pnfs_blksize))) {
+               dprintk("pnfsblock nonblock aligned DIO writes. Resend MDS\n");
+               goto out_mds;
+       }
        /* At this point, wdata->pages is a (sequential) list of nfs_pages.
         * We want to write each, and if there is an error set pnfs_error
         * to have it redone using nfs.
@@ -674,10 +801,11 @@ next_page:
                if (!extent_length) {
                        /* We've used up the previous extent */
                        bl_put_extent(be);
+                       bl_put_extent(cow_read);
                        bio = bl_submit_bio(WRITE, bio);
                        /* Get the next one */
                        be = bl_find_get_extent(BLK_LSEG2EXT(header->lseg),
-                                            isect, NULL);
+                                            isect, &cow_read);
                        if (!be || !is_writable(be, isect)) {
                                header->pnfs_error = -EINVAL;
                                goto out;
@@ -694,7 +822,26 @@ next_page:
                        extent_length = be->be_length -
                            (isect - be->be_f_offset);
                }
-               if (be->be_state == PNFS_BLOCK_INVALID_DATA) {
+
+               dprintk("%s offset %lld count %Zu\n", __func__, offset, count);
+               pg_offset = offset & ~PAGE_CACHE_MASK;
+               if (pg_offset + count > PAGE_CACHE_SIZE)
+                       pg_len = PAGE_CACHE_SIZE - pg_offset;
+               else
+                       pg_len = count;
+
+               saved_len = pg_len;
+               if (be->be_state == PNFS_BLOCK_INVALID_DATA &&
+                   !bl_is_sector_init(be->be_inval, isect)) {
+                       ret = bl_read_partial_page_sync(pages[i], cow_read,
+                                                       pg_offset, pg_len, true);
+                       if (ret) {
+                               dprintk("%s bl_read_partial_page_sync fail %d\n",
+                                       __func__, ret);
+                               header->pnfs_error = ret;
+                               goto out;
+                       }
+
                        ret = bl_mark_sectors_init(be->be_inval, isect,
                                                       PAGE_CACHE_SECTORS);
                        if (unlikely(ret)) {
@@ -703,15 +850,35 @@ next_page:
                                header->pnfs_error = ret;
                                goto out;
                        }
+
+                       /* Expand to full page write */
+                       pg_offset = 0;
+                       pg_len = PAGE_CACHE_SIZE;
+               } else if  ((pg_offset & (SECTOR_SIZE - 1)) ||
+                           (pg_len & (SECTOR_SIZE - 1))){
+                       /* ahh, nasty case. We have to do sync full sector
+                        * read-modify-write cycles.
+                        */
+                       unsigned int saved_offset = pg_offset;
+                       ret = bl_read_partial_page_sync(pages[i], be, pg_offset,
+                                                       pg_len, false);
+                       pg_offset = round_down(pg_offset, SECTOR_SIZE);
+                       pg_len = round_up(saved_offset + pg_len, SECTOR_SIZE)
+                                - pg_offset;
                }
-               bio = bl_add_page_to_bio(bio, wdata->pages.npages - i, WRITE,
+
+
+               bio = do_add_page_to_bio(bio, wdata->pages.npages - i, WRITE,
                                         isect, pages[i], be,
-                                        bl_end_io_write, par);
+                                        bl_end_io_write, par,
+                                        pg_offset, pg_len);
                if (IS_ERR(bio)) {
                        header->pnfs_error = PTR_ERR(bio);
                        bio = NULL;
                        goto out;
                }
+               offset += saved_len;
+               count -= saved_len;
                isect += PAGE_CACHE_SECTORS;
                last_isect = isect;
                extent_length -= PAGE_CACHE_SECTORS;
@@ -729,17 +896,16 @@ next_page:
        }
 
 write_done:
-       wdata->res.count = (last_isect << SECTOR_SHIFT) - (offset);
-       if (count < wdata->res.count) {
-               wdata->res.count = count;
-       }
+       wdata->res.count = wdata->args.count;
 out:
        bl_put_extent(be);
+       bl_put_extent(cow_read);
        bl_submit_bio(WRITE, bio);
        put_parallel(par);
        return PNFS_ATTEMPTED;
 out_mds:
        bl_put_extent(be);
+       bl_put_extent(cow_read);
        kfree(par);
        return PNFS_NOT_ATTEMPTED;
 }
@@ -874,7 +1040,7 @@ static void free_blk_mountid(struct block_mount_id *mid)
        }
 }
 
-/* This is mostly copied from the filelayout's get_device_info function.
+/* This is mostly copied from the filelayout_get_device_info function.
  * It seems much of this should be at the generic pnfs level.
  */
 static struct pnfs_block_dev *
@@ -1011,33 +1177,95 @@ bl_clear_layoutdriver(struct nfs_server *server)
        return 0;
 }
 
+static bool
+is_aligned_req(struct nfs_page *req, unsigned int alignment)
+{
+       return IS_ALIGNED(req->wb_offset, alignment) &&
+              IS_ALIGNED(req->wb_bytes, alignment);
+}
+
 static void
 bl_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
-       if (!bl_check_alignment(req->wb_offset, req->wb_bytes, PAGE_CACHE_MASK))
+       if (pgio->pg_dreq != NULL &&
+           !is_aligned_req(req, SECTOR_SIZE))
                nfs_pageio_reset_read_mds(pgio);
        else
                pnfs_generic_pg_init_read(pgio, req);
 }
 
+static bool
+bl_pg_test_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
+               struct nfs_page *req)
+{
+       if (pgio->pg_dreq != NULL &&
+           !is_aligned_req(req, SECTOR_SIZE))
+               return false;
+
+       return pnfs_generic_pg_test(pgio, prev, req);
+}
+
+/*
+ * Return the number of contiguous bytes for a given inode
+ * starting at page frame idx.
+ */
+static u64 pnfs_num_cont_bytes(struct inode *inode, pgoff_t idx)
+{
+       struct address_space *mapping = inode->i_mapping;
+       pgoff_t end;
+
+       /* Optimize common case that writes from 0 to end of file */
+       end = DIV_ROUND_UP(i_size_read(inode), PAGE_CACHE_SIZE);
+       if (end != NFS_I(inode)->npages) {
+               rcu_read_lock();
+               end = radix_tree_next_hole(&mapping->page_tree, idx + 1, ULONG_MAX);
+               rcu_read_unlock();
+       }
+
+       if (!end)
+               return i_size_read(inode) - (idx << PAGE_CACHE_SHIFT);
+       else
+               return (end - idx) << PAGE_CACHE_SHIFT;
+}
+
 static void
 bl_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
-       if (!bl_check_alignment(req->wb_offset, req->wb_bytes, PAGE_CACHE_MASK))
+       if (pgio->pg_dreq != NULL &&
+           !is_aligned_req(req, PAGE_CACHE_SIZE)) {
                nfs_pageio_reset_write_mds(pgio);
-       else
-               pnfs_generic_pg_init_write(pgio, req);
+       } else {
+               u64 wb_size;
+               if (pgio->pg_dreq == NULL)
+                       wb_size = pnfs_num_cont_bytes(pgio->pg_inode,
+                                                     req->wb_index);
+               else
+                       wb_size = nfs_dreq_bytes_left(pgio->pg_dreq);
+
+               pnfs_generic_pg_init_write(pgio, req, wb_size);
+       }
+}
+
+static bool
+bl_pg_test_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
+                struct nfs_page *req)
+{
+       if (pgio->pg_dreq != NULL &&
+           !is_aligned_req(req, PAGE_CACHE_SIZE))
+               return false;
+
+       return pnfs_generic_pg_test(pgio, prev, req);
 }
 
 static const struct nfs_pageio_ops bl_pg_read_ops = {
        .pg_init = bl_pg_init_read,
-       .pg_test = pnfs_generic_pg_test,
+       .pg_test = bl_pg_test_read,
        .pg_doio = pnfs_generic_pg_readpages,
 };
 
 static const struct nfs_pageio_ops bl_pg_write_ops = {
        .pg_init = bl_pg_init_write,
-       .pg_test = pnfs_generic_pg_test,
+       .pg_test = bl_pg_test_write,
        .pg_doio = pnfs_generic_pg_writepages,
 };
 
index 03350690118e239161fceb18e5939b97d7e062b4..f4891bde8851d8092012f06811496de724b2d5e4 100644 (file)
@@ -41,6 +41,7 @@
 
 #define PAGE_CACHE_SECTORS (PAGE_CACHE_SIZE >> SECTOR_SHIFT)
 #define PAGE_CACHE_SECTOR_SHIFT (PAGE_CACHE_SHIFT - SECTOR_SHIFT)
+#define SECTOR_SIZE (1 << SECTOR_SHIFT)
 
 struct block_mount_id {
        spinlock_t                      bm_lock;    /* protects list */
@@ -172,7 +173,6 @@ struct bl_msg_hdr {
 /* blocklayoutdev.c */
 ssize_t bl_pipe_downcall(struct file *, const char __user *, size_t);
 void bl_pipe_destroy_msg(struct rpc_pipe_msg *);
-struct block_device *nfs4_blkdev_get(dev_t dev);
 int nfs4_blkdev_put(struct block_device *bdev);
 struct pnfs_block_dev *nfs4_blk_decode_device(struct nfs_server *server,
                                                struct pnfs_device *dev);
index c96554245ccf7d90703c80d9a3e3f81b48fa65ee..a86c5bdad9e3119155889c37ae91052f7b9cc3ef 100644 (file)
@@ -53,22 +53,6 @@ static int decode_sector_number(__be32 **rp, sector_t *sp)
        return 0;
 }
 
-/* Open a block_device by device number. */
-struct block_device *nfs4_blkdev_get(dev_t dev)
-{
-       struct block_device *bd;
-
-       dprintk("%s enter\n", __func__);
-       bd = blkdev_get_by_dev(dev, FMODE_READ, NULL);
-       if (IS_ERR(bd))
-               goto fail;
-       return bd;
-fail:
-       dprintk("%s failed to open device : %ld\n",
-                       __func__, PTR_ERR(bd));
-       return NULL;
-}
-
 /*
  * Release the block device
  */
@@ -172,11 +156,12 @@ nfs4_blk_decode_device(struct nfs_server *server,
                goto out;
        }
 
-       bd = nfs4_blkdev_get(MKDEV(reply->major, reply->minor));
+       bd = blkdev_get_by_dev(MKDEV(reply->major, reply->minor),
+                              FMODE_READ, NULL);
        if (IS_ERR(bd)) {
-               rc = PTR_ERR(bd);
-               dprintk("%s failed to open device : %d\n", __func__, rc);
-               rv = ERR_PTR(rc);
+               dprintk("%s failed to open device : %ld\n", __func__,
+                       PTR_ERR(bd));
+               rv = ERR_CAST(bd);
                goto out;
        }
 
index 1f9a6032796b0ff239f2337fae7b656deb71ced6..9c3e117c3ed1f04c5dd1650f70a3aa4ca2fd7d8c 100644 (file)
@@ -683,8 +683,7 @@ encode_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
                p = xdr_encode_hyper(p, lce->bse_length << SECTOR_SHIFT);
                p = xdr_encode_hyper(p, 0LL);
                *p++ = cpu_to_be32(PNFS_BLOCK_READWRITE_DATA);
-               list_del(&lce->bse_node);
-               list_add_tail(&lce->bse_node, &bl->bl_committing);
+               list_move_tail(&lce->bse_node, &bl->bl_committing);
                bl->bl_count--;
                count++;
        }
index 4c8459e5bdeef904e930cff50def65f7ac91f672..9a521fb3986955aab3f32e755bdef94e9c313aa2 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/svcsock.h>
 #include <linux/nfs_fs.h>
+#include <linux/errno.h>
 #include <linux/mutex.h>
 #include <linux/freezer.h>
 #include <linux/kthread.h>
@@ -23,6 +24,7 @@
 #include "nfs4_fs.h"
 #include "callback.h"
 #include "internal.h"
+#include "netns.h"
 
 #define NFSDBG_FACILITY NFSDBG_CALLBACK
 
@@ -37,7 +39,32 @@ static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1];
 static DEFINE_MUTEX(nfs_callback_mutex);
 static struct svc_program nfs4_callback_program;
 
-unsigned short nfs_callback_tcpport6;
+static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net)
+{
+       int ret;
+       struct nfs_net *nn = net_generic(net, nfs_net_id);
+
+       ret = svc_create_xprt(serv, "tcp", net, PF_INET,
+                               nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
+       if (ret <= 0)
+               goto out_err;
+       nn->nfs_callback_tcpport = ret;
+       dprintk("NFS: Callback listener port = %u (af %u, net %p)\n",
+                       nn->nfs_callback_tcpport, PF_INET, net);
+
+       ret = svc_create_xprt(serv, "tcp", net, PF_INET6,
+                               nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
+       if (ret > 0) {
+               nn->nfs_callback_tcpport6 = ret;
+               dprintk("NFS: Callback listener port = %u (af %u, net %p)\n",
+                               nn->nfs_callback_tcpport6, PF_INET6, net);
+       } else if (ret != -EAFNOSUPPORT)
+               goto out_err;
+       return 0;
+
+out_err:
+       return (ret) ? ret : -ENOMEM;
+}
 
 /*
  * This is the NFSv4 callback kernel thread.
@@ -45,7 +72,7 @@ unsigned short nfs_callback_tcpport6;
 static int
 nfs4_callback_svc(void *vrqstp)
 {
-       int err, preverr = 0;
+       int err;
        struct svc_rqst *rqstp = vrqstp;
 
        set_freezable();
@@ -55,20 +82,8 @@ nfs4_callback_svc(void *vrqstp)
                 * Listen for a request on the socket
                 */
                err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT);
-               if (err == -EAGAIN || err == -EINTR) {
-                       preverr = err;
-                       continue;
-               }
-               if (err < 0) {
-                       if (err != preverr) {
-                               printk(KERN_WARNING "NFS: %s: unexpected error "
-                                       "from svc_recv (%d)\n", __func__, err);
-                               preverr = err;
-                       }
-                       schedule_timeout_uninterruptible(HZ);
+               if (err == -EAGAIN || err == -EINTR)
                        continue;
-               }
-               preverr = err;
                svc_process(rqstp);
        }
        return 0;
@@ -78,38 +93,23 @@ nfs4_callback_svc(void *vrqstp)
  * Prepare to bring up the NFSv4 callback service
  */
 static struct svc_rqst *
-nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt)
+nfs4_callback_up(struct svc_serv *serv)
 {
-       int ret;
-
-       ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET,
-                               nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
-       if (ret <= 0)
-               goto out_err;
-       nfs_callback_tcpport = ret;
-       dprintk("NFS: Callback listener port = %u (af %u)\n",
-                       nfs_callback_tcpport, PF_INET);
-
-       ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6,
-                               nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
-       if (ret > 0) {
-               nfs_callback_tcpport6 = ret;
-               dprintk("NFS: Callback listener port = %u (af %u)\n",
-                               nfs_callback_tcpport6, PF_INET6);
-       } else if (ret == -EAFNOSUPPORT)
-               ret = 0;
-       else
-               goto out_err;
-
        return svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE);
-
-out_err:
-       if (ret == 0)
-               ret = -ENOMEM;
-       return ERR_PTR(ret);
 }
 
 #if defined(CONFIG_NFS_V4_1)
+static int nfs41_callback_up_net(struct svc_serv *serv, struct net *net)
+{
+       /*
+        * Create an svc_sock for the back channel service that shares the
+        * fore channel connection.
+        * Returns the input port (0) and sets the svc_serv bc_xprt on success
+        */
+       return svc_create_xprt(serv, "tcp-bc", net, PF_INET, 0,
+                             SVC_SOCK_ANONYMOUS);
+}
+
 /*
  * The callback service for NFSv4.1 callbacks
  */
@@ -149,28 +149,9 @@ nfs41_callback_svc(void *vrqstp)
  * Bring up the NFSv4.1 callback service
  */
 static struct svc_rqst *
-nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt)
+nfs41_callback_up(struct svc_serv *serv)
 {
        struct svc_rqst *rqstp;
-       int ret;
-
-       /*
-        * Create an svc_sock for the back channel service that shares the
-        * fore channel connection.
-        * Returns the input port (0) and sets the svc_serv bc_xprt on success
-        */
-       ret = svc_create_xprt(serv, "tcp-bc", &init_net, PF_INET, 0,
-                             SVC_SOCK_ANONYMOUS);
-       if (ret < 0) {
-               rqstp = ERR_PTR(ret);
-               goto out;
-       }
-
-       /*
-        * Save the svc_serv in the transport so that it can
-        * be referenced when the session backchannel is initialized
-        */
-       xprt->bc_serv = serv;
 
        INIT_LIST_HEAD(&serv->sv_cb_list);
        spin_lock_init(&serv->sv_cb_lock);
@@ -180,90 +161,74 @@ nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt)
                svc_xprt_put(serv->sv_bc_xprt);
                serv->sv_bc_xprt = NULL;
        }
-out:
        dprintk("--> %s return %ld\n", __func__,
                IS_ERR(rqstp) ? PTR_ERR(rqstp) : 0);
        return rqstp;
 }
 
-static inline int nfs_minorversion_callback_svc_setup(u32 minorversion,
-               struct svc_serv *serv, struct rpc_xprt *xprt,
+static void nfs_minorversion_callback_svc_setup(struct svc_serv *serv,
                struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp))
 {
-       if (minorversion) {
-               *rqstpp = nfs41_callback_up(serv, xprt);
-               *callback_svc = nfs41_callback_svc;
-       }
-       return minorversion;
+       *rqstpp = nfs41_callback_up(serv);
+       *callback_svc = nfs41_callback_svc;
 }
 
 static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
-               struct nfs_callback_data *cb_info)
+               struct svc_serv *serv)
 {
        if (minorversion)
-               xprt->bc_serv = cb_info->serv;
+               /*
+                * Save the svc_serv in the transport so that it can
+                * be referenced when the session backchannel is initialized
+                */
+               xprt->bc_serv = serv;
 }
 #else
-static inline int nfs_minorversion_callback_svc_setup(u32 minorversion,
-               struct svc_serv *serv, struct rpc_xprt *xprt,
-               struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp))
+static int nfs41_callback_up_net(struct svc_serv *serv, struct net *net)
 {
        return 0;
 }
 
+static void nfs_minorversion_callback_svc_setup(struct svc_serv *serv,
+               struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp))
+{
+       *rqstpp = ERR_PTR(-ENOTSUPP);
+       *callback_svc = ERR_PTR(-ENOTSUPP);
+}
+
 static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
-               struct nfs_callback_data *cb_info)
+               struct svc_serv *serv)
 {
 }
 #endif /* CONFIG_NFS_V4_1 */
 
-/*
- * Bring up the callback thread if it is not already up.
- */
-int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
+static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,
+                                 struct svc_serv *serv)
 {
-       struct svc_serv *serv = NULL;
        struct svc_rqst *rqstp;
        int (*callback_svc)(void *vrqstp);
        struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
        char svc_name[12];
-       int ret = 0;
-       int minorversion_setup;
-       struct net *net = &init_net;
+       int ret;
 
-       mutex_lock(&nfs_callback_mutex);
-       if (cb_info->users++ || cb_info->task != NULL) {
-               nfs_callback_bc_serv(minorversion, xprt, cb_info);
-               goto out;
-       }
-       serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
-       if (!serv) {
-               ret = -ENOMEM;
-               goto out_err;
-       }
-       /* As there is only one thread we need to over-ride the
-        * default maximum of 80 connections
-        */
-       serv->sv_maxconn = 1024;
+       nfs_callback_bc_serv(minorversion, xprt, serv);
 
-       ret = svc_bind(serv, net);
-       if (ret < 0) {
-               printk(KERN_WARNING "NFS: bind callback service failed\n");
-               goto out_err;
-       }
+       if (cb_info->task)
+               return 0;
 
-       minorversion_setup =  nfs_minorversion_callback_svc_setup(minorversion,
-                                       serv, xprt, &rqstp, &callback_svc);
-       if (!minorversion_setup) {
+       switch (minorversion) {
+       case 0:
                /* v4.0 callback setup */
-               rqstp = nfs4_callback_up(serv, xprt);
+               rqstp = nfs4_callback_up(serv);
                callback_svc = nfs4_callback_svc;
+               break;
+       default:
+               nfs_minorversion_callback_svc_setup(serv,
+                               &rqstp, &callback_svc);
        }
 
-       if (IS_ERR(rqstp)) {
-               ret = PTR_ERR(rqstp);
-               goto out_err;
-       }
+       if (IS_ERR(rqstp))
+               return PTR_ERR(rqstp);
 
        svc_sock_update_bufs(serv);
 
@@ -276,41 +241,165 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
                svc_exit_thread(cb_info->rqst);
                cb_info->rqst = NULL;
                cb_info->task = NULL;
-               goto out_err;
+               return PTR_ERR(cb_info->task);
+       }
+       dprintk("nfs_callback_up: service started\n");
+       return 0;
+}
+
+static void nfs_callback_down_net(u32 minorversion, struct svc_serv *serv, struct net *net)
+{
+       struct nfs_net *nn = net_generic(net, nfs_net_id);
+
+       if (--nn->cb_users[minorversion])
+               return;
+
+       dprintk("NFS: destroy per-net callback data; net=%p\n", net);
+       svc_shutdown_net(serv, net);
+}
+
+static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, struct net *net)
+{
+       struct nfs_net *nn = net_generic(net, nfs_net_id);
+       int ret;
+
+       if (nn->cb_users[minorversion]++)
+               return 0;
+
+       dprintk("NFS: create per-net callback data; net=%p\n", net);
+
+       ret = svc_bind(serv, net);
+       if (ret < 0) {
+               printk(KERN_WARNING "NFS: bind callback service failed\n");
+               goto err_bind;
+       }
+
+       switch (minorversion) {
+               case 0:
+                       ret = nfs4_callback_up_net(serv, net);
+                       break;
+               case 1:
+                       ret = nfs41_callback_up_net(serv, net);
+                       break;
+               default:
+                       printk(KERN_ERR "NFS: unknown callback version: %d\n",
+                                       minorversion);
+                       ret = -EINVAL;
+                       break;
+       }
+
+       if (ret < 0) {
+               printk(KERN_ERR "NFS: callback service start failed\n");
+               goto err_socks;
+       }
+       return 0;
+
+err_socks:
+       svc_rpcb_cleanup(serv, net);
+err_bind:
+       dprintk("NFS: Couldn't create callback socket: err = %d; "
+                       "net = %p\n", ret, net);
+       return ret;
+}
+
+static struct svc_serv *nfs_callback_create_svc(int minorversion)
+{
+       struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
+       struct svc_serv *serv;
+
+       /*
+        * Check whether we're already up and running.
+        */
+       if (cb_info->task) {
+               /*
+                * Note: increase service usage, because later in case of error
+                * svc_destroy() will be called.
+                */
+               svc_get(cb_info->serv);
+               return cb_info->serv;
+       }
+
+       /*
+        * Sanity check: if there's no task,
+        * we should be the first user ...
+        */
+       if (cb_info->users)
+               printk(KERN_WARNING "nfs_callback_create_svc: no kthread, %d users??\n",
+                       cb_info->users);
+
+       serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
+       if (!serv) {
+               printk(KERN_ERR "nfs_callback_create_svc: create service failed\n");
+               return ERR_PTR(-ENOMEM);
+       }
+       /* As there is only one thread we need to over-ride the
+        * default maximum of 80 connections
+        */
+       serv->sv_maxconn = 1024;
+       dprintk("nfs_callback_create_svc: service created\n");
+       return serv;
+}
+
+/*
+ * Bring up the callback thread if it is not already up.
+ */
+int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
+{
+       struct svc_serv *serv;
+       struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
+       int ret;
+       struct net *net = xprt->xprt_net;
+
+       mutex_lock(&nfs_callback_mutex);
+
+       serv = nfs_callback_create_svc(minorversion);
+       if (IS_ERR(serv)) {
+               ret = PTR_ERR(serv);
+               goto err_create;
        }
-out:
+
+       ret = nfs_callback_up_net(minorversion, serv, net);
+       if (ret < 0)
+               goto err_net;
+
+       ret = nfs_callback_start_svc(minorversion, xprt, serv);
+       if (ret < 0)
+               goto err_start;
+
+       cb_info->users++;
        /*
         * svc_create creates the svc_serv with sv_nrthreads == 1, and then
         * svc_prepare_thread increments that. So we need to call svc_destroy
         * on both success and failure so that the refcount is 1 when the
         * thread exits.
         */
-       if (serv)
-               svc_destroy(serv);
+err_net:
+       svc_destroy(serv);
+err_create:
        mutex_unlock(&nfs_callback_mutex);
        return ret;
-out_err:
-       dprintk("NFS: Couldn't create callback socket or server thread; "
-               "err = %d\n", ret);
-       cb_info->users--;
-       if (serv)
-               svc_shutdown_net(serv, net);
-       goto out;
+
+err_start:
+       nfs_callback_down_net(minorversion, serv, net);
+       dprintk("NFS: Couldn't create server thread; err = %d\n", ret);
+       goto err_net;
 }
 
 /*
  * Kill the callback thread if it's no longer being used.
  */
-void nfs_callback_down(int minorversion)
+void nfs_callback_down(int minorversion, struct net *net)
 {
        struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
 
        mutex_lock(&nfs_callback_mutex);
+       nfs_callback_down_net(minorversion, cb_info->serv, net);
        cb_info->users--;
        if (cb_info->users == 0 && cb_info->task != NULL) {
                kthread_stop(cb_info->task);
-               svc_shutdown_net(cb_info->serv, &init_net);
+               dprintk("nfs_callback_down: service stopped\n");
                svc_exit_thread(cb_info->rqst);
+               dprintk("nfs_callback_down: service destroyed\n");
                cb_info->serv = NULL;
                cb_info->rqst = NULL;
                cb_info->task = NULL;
index b44d7b128b71973678ff265a9ea13dbeb1415c00..4251c2ae06adaf432e9d4d8304f4eea1b5b72c57 100644 (file)
@@ -194,7 +194,7 @@ extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,
                                   struct cb_process_state *cps);
 #if IS_ENABLED(CONFIG_NFS_V4)
 extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt);
-extern void nfs_callback_down(int minorversion);
+extern void nfs_callback_down(int minorversion, struct net *net);
 extern int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation,
                                            const nfs4_stateid *stateid);
 extern int nfs4_set_callback_sessionid(struct nfs_client *clp);
@@ -209,6 +209,5 @@ extern int nfs4_set_callback_sessionid(struct nfs_client *clp);
 
 extern unsigned int nfs_callback_set_tcpport;
 extern unsigned short nfs_callback_tcpport;
-extern unsigned short nfs_callback_tcpport6;
 
 #endif /* __LINUX_FS_NFS_CALLBACK_H */
index 1b5d809a105e42d992344aad78fb57526c2af8fa..76b4a7a3e55931e0f9cc79d08c248048cbfaa961 100644 (file)
@@ -122,7 +122,15 @@ static struct pnfs_layout_hdr * get_layout_by_fh_locked(struct nfs_client *clp,
                        ino = igrab(lo->plh_inode);
                        if (!ino)
                                continue;
-                       get_layout_hdr(lo);
+                       spin_lock(&ino->i_lock);
+                       /* Is this layout in the process of being freed? */
+                       if (NFS_I(ino)->layout != lo) {
+                               spin_unlock(&ino->i_lock);
+                               iput(ino);
+                               continue;
+                       }
+                       pnfs_get_layout_hdr(lo);
+                       spin_unlock(&ino->i_lock);
                        return lo;
                }
        }
@@ -158,7 +166,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,
        ino = lo->plh_inode;
        spin_lock(&ino->i_lock);
        if (test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags) ||
-           mark_matching_lsegs_invalid(lo, &free_me_list,
+           pnfs_mark_matching_lsegs_invalid(lo, &free_me_list,
                                        &args->cbl_range))
                rv = NFS4ERR_DELAY;
        else
@@ -166,7 +174,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,
        pnfs_set_layout_stateid(lo, &args->cbl_stateid, true);
        spin_unlock(&ino->i_lock);
        pnfs_free_lseg_list(&free_me_list);
-       put_layout_hdr(lo);
+       pnfs_put_layout_hdr(lo);
        iput(ino);
        return rv;
 }
@@ -196,9 +204,18 @@ static u32 initiate_bulk_draining(struct nfs_client *clp,
                        continue;
 
                list_for_each_entry(lo, &server->layouts, plh_layouts) {
-                       if (!igrab(lo->plh_inode))
+                       ino = igrab(lo->plh_inode);
+                       if (ino)
+                               continue;
+                       spin_lock(&ino->i_lock);
+                       /* Is this layout in the process of being freed? */
+                       if (NFS_I(ino)->layout != lo) {
+                               spin_unlock(&ino->i_lock);
+                               iput(ino);
                                continue;
-                       get_layout_hdr(lo);
+                       }
+                       pnfs_get_layout_hdr(lo);
+                       spin_unlock(&ino->i_lock);
                        BUG_ON(!list_empty(&lo->plh_bulk_recall));
                        list_add(&lo->plh_bulk_recall, &recall_list);
                }
@@ -211,12 +228,12 @@ static u32 initiate_bulk_draining(struct nfs_client *clp,
                ino = lo->plh_inode;
                spin_lock(&ino->i_lock);
                set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
-               if (mark_matching_lsegs_invalid(lo, &free_me_list, &range))
+               if (pnfs_mark_matching_lsegs_invalid(lo, &free_me_list, &range))
                        rv = NFS4ERR_DELAY;
                list_del_init(&lo->plh_bulk_recall);
                spin_unlock(&ino->i_lock);
                pnfs_free_lseg_list(&free_me_list);
-               put_layout_hdr(lo);
+               pnfs_put_layout_hdr(lo);
                iput(ino);
        }
        return rv;
index 99694442b93f6d64f5f433d8cf3cc8fdc08de52e..8b39a42ac35ee5d8c081f205e631b6b2458b4be1 100644 (file)
@@ -93,10 +93,10 @@ static struct nfs_subversion *find_nfs_version(unsigned int version)
                        spin_unlock(&nfs_version_lock);
                        return nfs;
                }
-       };
+       }
 
        spin_unlock(&nfs_version_lock);
-       return ERR_PTR(-EPROTONOSUPPORT);;
+       return ERR_PTR(-EPROTONOSUPPORT);
 }
 
 struct nfs_subversion *get_nfs_version(unsigned int version)
@@ -498,7 +498,8 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
                        return nfs_found_client(cl_init, clp);
                }
                if (new) {
-                       list_add(&new->cl_share_link, &nn->nfs_client_list);
+                       list_add_tail(&new->cl_share_link,
+                                       &nn->nfs_client_list);
                        spin_unlock(&nn->nfs_client_lock);
                        new->cl_flags = cl_init->init_flags;
                        return rpc_ops->init_client(new, timeparms, ip_addr,
@@ -668,7 +669,8 @@ int nfs_init_server_rpcclient(struct nfs_server *server,
 {
        struct nfs_client *clp = server->nfs_client;
 
-       server->client = rpc_clone_client(clp->cl_rpcclient);
+       server->client = rpc_clone_client_set_auth(clp->cl_rpcclient,
+                                                       pseudoflavour);
        if (IS_ERR(server->client)) {
                dprintk("%s: couldn't create rpc_client!\n", __func__);
                return PTR_ERR(server->client);
@@ -678,16 +680,6 @@ int nfs_init_server_rpcclient(struct nfs_server *server,
                        timeo,
                        sizeof(server->client->cl_timeout_default));
        server->client->cl_timeout = &server->client->cl_timeout_default;
-
-       if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) {
-               struct rpc_auth *auth;
-
-               auth = rpcauth_create(pseudoflavour, server->client);
-               if (IS_ERR(auth)) {
-                       dprintk("%s: couldn't create credcache!\n", __func__);
-                       return PTR_ERR(auth);
-               }
-       }
        server->client->cl_softrtry = 0;
        if (server->flags & NFS_MOUNT_SOFT)
                server->client->cl_softrtry = 1;
@@ -761,6 +753,8 @@ static int nfs_init_server(struct nfs_server *server,
                        data->timeo, data->retrans);
        if (data->flags & NFS_MOUNT_NORESVPORT)
                set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
+       if (server->options & NFS_OPTION_MIGRATION)
+               set_bit(NFS_CS_MIGRATION, &cl_init.init_flags);
 
        /* Allocate or find a client reference we can use */
        clp = nfs_get_client(&cl_init, &timeparms, NULL, RPC_AUTH_UNIX);
@@ -855,7 +849,6 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
        if (server->wsize > NFS_MAX_FILE_IO_SIZE)
                server->wsize = NFS_MAX_FILE_IO_SIZE;
        server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-       server->pnfs_blksize = fsinfo->blksize;
 
        server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
 
index 627f108ede23327e3339d4e35ac47f6cb09490d3..ce8cb926526bfad79aabe5b8448f80212e1670f9 100644 (file)
@@ -2072,7 +2072,7 @@ found:
        nfs_access_free_entry(entry);
 }
 
-static void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
+void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
 {
        struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL);
        if (cache == NULL)
@@ -2098,6 +2098,20 @@ static void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *s
                spin_unlock(&nfs_access_lru_lock);
        }
 }
+EXPORT_SYMBOL_GPL(nfs_access_add_cache);
+
+void nfs_access_set_mask(struct nfs_access_entry *entry, u32 access_result)
+{
+       entry->mask = 0;
+       if (access_result & NFS4_ACCESS_READ)
+               entry->mask |= MAY_READ;
+       if (access_result &
+           (NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE))
+               entry->mask |= MAY_WRITE;
+       if (access_result & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE))
+               entry->mask |= MAY_EXEC;
+}
+EXPORT_SYMBOL_GPL(nfs_access_set_mask);
 
 static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
 {
index 1ba385b7c90da41b4c90d5760fe13bbc7482302a..cae26cbd59ee89cd5d73e719ef201b26ef9cabc3 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/kref.h>
 #include <linux/slab.h>
 #include <linux/task_io_accounting_ops.h>
+#include <linux/module.h>
 
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
@@ -78,6 +79,7 @@ struct nfs_direct_req {
        atomic_t                io_count;       /* i/os we're waiting for */
        spinlock_t              lock;           /* protect completion state */
        ssize_t                 count,          /* bytes actually processed */
+                               bytes_left,     /* bytes left to be sent */
                                error;          /* any reported error */
        struct completion       completion;     /* wait for i/o completion */
 
@@ -190,6 +192,12 @@ static void nfs_direct_req_release(struct nfs_direct_req *dreq)
        kref_put(&dreq->kref, nfs_direct_req_free);
 }
 
+ssize_t nfs_dreq_bytes_left(struct nfs_direct_req *dreq)
+{
+       return dreq->bytes_left;
+}
+EXPORT_SYMBOL_GPL(nfs_dreq_bytes_left);
+
 /*
  * Collects and returns the final error value/byte-count.
  */
@@ -390,6 +398,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_pageio_descriptor *de
                        user_addr += req_len;
                        pos += req_len;
                        count -= req_len;
+                       dreq->bytes_left -= req_len;
                }
                /* The nfs_page now hold references to these pages */
                nfs_direct_release_pages(pagevec, npages);
@@ -450,23 +459,28 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov,
        ssize_t result = -ENOMEM;
        struct inode *inode = iocb->ki_filp->f_mapping->host;
        struct nfs_direct_req *dreq;
+       struct nfs_lock_context *l_ctx;
 
        dreq = nfs_direct_req_alloc();
        if (dreq == NULL)
                goto out;
 
        dreq->inode = inode;
+       dreq->bytes_left = iov_length(iov, nr_segs);
        dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
-       dreq->l_ctx = nfs_get_lock_context(dreq->ctx);
-       if (dreq->l_ctx == NULL)
+       l_ctx = nfs_get_lock_context(dreq->ctx);
+       if (IS_ERR(l_ctx)) {
+               result = PTR_ERR(l_ctx);
                goto out_release;
+       }
+       dreq->l_ctx = l_ctx;
        if (!is_sync_kiocb(iocb))
                dreq->iocb = iocb;
 
+       NFS_I(inode)->read_io += iov_length(iov, nr_segs);
        result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos, uio);
        if (!result)
                result = nfs_direct_wait(dreq);
-       NFS_I(inode)->read_io += result;
 out_release:
        nfs_direct_req_release(dreq);
 out:
@@ -706,6 +720,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_pageio_descriptor *d
                        user_addr += req_len;
                        pos += req_len;
                        count -= req_len;
+                       dreq->bytes_left -= req_len;
                }
                /* The nfs_page now hold references to these pages */
                nfs_direct_release_pages(pagevec, npages);
@@ -814,6 +829,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
        get_dreq(dreq);
        atomic_inc(&inode->i_dio_count);
 
+       NFS_I(dreq->inode)->write_io += iov_length(iov, nr_segs);
        for (seg = 0; seg < nr_segs; seg++) {
                const struct iovec *vec = &iov[seg];
                result = nfs_direct_write_schedule_segment(&desc, vec, pos, uio);
@@ -825,7 +841,6 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
                pos += vec->iov_len;
        }
        nfs_pageio_complete(&desc);
-       NFS_I(dreq->inode)->write_io += desc.pg_bytes_written;
 
        /*
         * If no bytes were started, return the error, and let the
@@ -849,16 +864,21 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov,
        ssize_t result = -ENOMEM;
        struct inode *inode = iocb->ki_filp->f_mapping->host;
        struct nfs_direct_req *dreq;
+       struct nfs_lock_context *l_ctx;
 
        dreq = nfs_direct_req_alloc();
        if (!dreq)
                goto out;
 
        dreq->inode = inode;
+       dreq->bytes_left = count;
        dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
-       dreq->l_ctx = nfs_get_lock_context(dreq->ctx);
-       if (dreq->l_ctx == NULL)
+       l_ctx = nfs_get_lock_context(dreq->ctx);
+       if (IS_ERR(l_ctx)) {
+               result = PTR_ERR(l_ctx);
                goto out_release;
+       }
+       dreq->l_ctx = l_ctx;
        if (!is_sync_kiocb(iocb))
                dreq->iocb = iocb;
 
index f692be97676d264d8e9100df4306e9e9fb021a7f..582bb8866131d27a8d53d069c8bd7714caa7af4d 100644 (file)
@@ -259,7 +259,7 @@ nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync)
        struct dentry *dentry = file->f_path.dentry;
        struct nfs_open_context *ctx = nfs_file_open_context(file);
        struct inode *inode = dentry->d_inode;
-       int have_error, status;
+       int have_error, do_resend, status;
        int ret = 0;
 
        dprintk("NFS: fsync file(%s/%s) datasync %d\n",
@@ -267,15 +267,23 @@ nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync)
                        datasync);
 
        nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
+       do_resend = test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags);
        have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
        status = nfs_commit_inode(inode, FLUSH_SYNC);
-       if (status >= 0 && ret < 0)
-               status = ret;
        have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
-       if (have_error)
+       if (have_error) {
                ret = xchg(&ctx->error, 0);
-       if (!ret && status < 0)
+               if (ret)
+                       goto out;
+       }
+       if (status < 0) {
                ret = status;
+               goto out;
+       }
+       do_resend |= test_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags);
+       if (do_resend)
+               ret = -EAGAIN;
+out:
        return ret;
 }
 EXPORT_SYMBOL_GPL(nfs_file_fsync_commit);
@@ -286,13 +294,22 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
        int ret;
        struct inode *inode = file->f_path.dentry->d_inode;
 
-       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
-       if (ret != 0)
-               goto out;
-       mutex_lock(&inode->i_mutex);
-       ret = nfs_file_fsync_commit(file, start, end, datasync);
-       mutex_unlock(&inode->i_mutex);
-out:
+       do {
+               ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+               if (ret != 0)
+                       break;
+               mutex_lock(&inode->i_mutex);
+               ret = nfs_file_fsync_commit(file, start, end, datasync);
+               mutex_unlock(&inode->i_mutex);
+               /*
+                * If nfs_file_fsync_commit detected a server reboot, then
+                * resend all dirty pages that might have been covered by
+                * the NFS_CONTEXT_RESEND_WRITES flag
+                */
+               start = 0;
+               end = LLONG_MAX;
+       } while (ret == -EAGAIN);
+
        return ret;
 }
 
index 4654ced096a644a50dbd0421eb68c7a76db9d791..033803c36644289b449bcb568e79cdb256ccb1fd 100644 (file)
@@ -32,6 +32,8 @@
 
 #include <asm/uaccess.h>
 
+#include "internal.h"
+
 #define NFSDBG_FACILITY                NFSDBG_CLIENT
 
 /*
index a850079467d85f149d997b9c96176c9a0829be0d..9cc4a3fbf4b0d4ab3106b7584ba756776005e6f8 100644 (file)
 static const struct cred *id_resolver_cache;
 static struct key_type key_type_id_resolver_legacy;
 
-struct idmap {
-       struct rpc_pipe         *idmap_pipe;
-       struct key_construction *idmap_key_cons;
-       struct mutex            idmap_mutex;
-};
-
 struct idmap_legacy_upcalldata {
        struct rpc_pipe_msg pipe_msg;
        struct idmap_msg idmap_msg;
+       struct key_construction *key_cons;
        struct idmap *idmap;
 };
 
+struct idmap {
+       struct rpc_pipe         *idmap_pipe;
+       struct idmap_legacy_upcalldata *idmap_upcall_data;
+       struct mutex            idmap_mutex;
+};
+
 /**
  * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields
  * @fattr: fully initialised struct nfs_fattr
@@ -158,7 +159,7 @@ static int nfs_map_string_to_numeric(const char *name, size_t namelen, __u32 *re
                return 0;
        memcpy(buf, name, namelen);
        buf[namelen] = '\0';
-       if (strict_strtoul(buf, 0, &val) != 0)
+       if (kstrtoul(buf, 0, &val) != 0)
                return 0;
        *res = val;
        return 1;
@@ -330,7 +331,6 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen,
                ret = nfs_idmap_request_key(&key_type_id_resolver_legacy,
                                            name, namelen, type, data,
                                            data_size, idmap);
-               idmap->idmap_key_cons = NULL;
                mutex_unlock(&idmap->idmap_mutex);
        }
        return ret;
@@ -364,7 +364,7 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *typ
        if (data_size <= 0) {
                ret = -EINVAL;
        } else {
-               ret = strict_strtol(id_str, 10, &id_long);
+               ret = kstrtol(id_str, 10, &id_long);
                *id = (__u32)id_long;
        }
        return ret;
@@ -465,8 +465,6 @@ nfs_idmap_new(struct nfs_client *clp)
        struct rpc_pipe *pipe;
        int error;
 
-       BUG_ON(clp->cl_idmap != NULL);
-
        idmap = kzalloc(sizeof(*idmap), GFP_KERNEL);
        if (idmap == NULL)
                return -ENOMEM;
@@ -510,7 +508,6 @@ static int __rpc_pipefs_event(struct nfs_client *clp, unsigned long event,
 
        switch (event) {
        case RPC_PIPEFS_MOUNT:
-               BUG_ON(clp->cl_rpcclient->cl_dentry == NULL);
                err = __nfs_idmap_register(clp->cl_rpcclient->cl_dentry,
                                                clp->cl_idmap,
                                                clp->cl_idmap->idmap_pipe);
@@ -632,9 +629,6 @@ static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap,
        substring_t substr;
        int token, ret;
 
-       memset(im,  0, sizeof(*im));
-       memset(msg, 0, sizeof(*msg));
-
        im->im_type = IDMAP_TYPE_GROUP;
        token = match_token(desc, nfs_idmap_tokens, &substr);
 
@@ -665,6 +659,35 @@ out:
        return ret;
 }
 
+static bool
+nfs_idmap_prepare_pipe_upcall(struct idmap *idmap,
+               struct idmap_legacy_upcalldata *data)
+{
+       if (idmap->idmap_upcall_data != NULL) {
+               WARN_ON_ONCE(1);
+               return false;
+       }
+       idmap->idmap_upcall_data = data;
+       return true;
+}
+
+static void
+nfs_idmap_complete_pipe_upcall_locked(struct idmap *idmap, int ret)
+{
+       struct key_construction *cons = idmap->idmap_upcall_data->key_cons;
+
+       kfree(idmap->idmap_upcall_data);
+       idmap->idmap_upcall_data = NULL;
+       complete_request_key(cons, ret);
+}
+
+static void
+nfs_idmap_abort_pipe_upcall(struct idmap *idmap, int ret)
+{
+       if (idmap->idmap_upcall_data != NULL)
+               nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
+}
+
 static int nfs_idmap_legacy_upcall(struct key_construction *cons,
                                   const char *op,
                                   void *aux)
@@ -677,29 +700,28 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons,
        int ret = -ENOMEM;
 
        /* msg and im are freed in idmap_pipe_destroy_msg */
-       data = kmalloc(sizeof(*data), GFP_KERNEL);
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
                goto out1;
 
        msg = &data->pipe_msg;
        im = &data->idmap_msg;
        data->idmap = idmap;
+       data->key_cons = cons;
 
        ret = nfs_idmap_prepare_message(key->description, idmap, im, msg);
        if (ret < 0)
                goto out2;
 
-       BUG_ON(idmap->idmap_key_cons != NULL);
-       idmap->idmap_key_cons = cons;
+       ret = -EAGAIN;
+       if (!nfs_idmap_prepare_pipe_upcall(idmap, data))
+               goto out2;
 
        ret = rpc_queue_upcall(idmap->idmap_pipe, msg);
        if (ret < 0)
-               goto out3;
+               nfs_idmap_abort_pipe_upcall(idmap, ret);
 
        return ret;
-
-out3:
-       idmap->idmap_key_cons = NULL;
 out2:
        kfree(data);
 out1:
@@ -714,21 +736,32 @@ static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *dat
                                        authkey);
 }
 
-static int nfs_idmap_read_message(struct idmap_msg *im, struct key *key, struct key *authkey)
+static int nfs_idmap_read_and_verify_message(struct idmap_msg *im,
+               struct idmap_msg *upcall,
+               struct key *key, struct key *authkey)
 {
        char id_str[NFS_UINT_MAXLEN];
-       int ret = -EINVAL;
+       int ret = -ENOKEY;
 
+       /* ret = -ENOKEY */
+       if (upcall->im_type != im->im_type || upcall->im_conv != im->im_conv)
+               goto out;
        switch (im->im_conv) {
        case IDMAP_CONV_NAMETOID:
+               if (strcmp(upcall->im_name, im->im_name) != 0)
+                       break;
                sprintf(id_str, "%d", im->im_id);
                ret = nfs_idmap_instantiate(key, authkey, id_str);
                break;
        case IDMAP_CONV_IDTONAME:
+               if (upcall->im_id != im->im_id)
+                       break;
                ret = nfs_idmap_instantiate(key, authkey, im->im_name);
                break;
+       default:
+               ret = -EINVAL;
        }
-
+out:
        return ret;
 }
 
@@ -740,14 +773,16 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
        struct key_construction *cons;
        struct idmap_msg im;
        size_t namelen_in;
-       int ret;
+       int ret = -ENOKEY;
 
        /* If instantiation is successful, anyone waiting for key construction
         * will have been woken up and someone else may now have used
         * idmap_key_cons - so after this point we may no longer touch it.
         */
-       cons = ACCESS_ONCE(idmap->idmap_key_cons);
-       idmap->idmap_key_cons = NULL;
+       if (idmap->idmap_upcall_data == NULL)
+               goto out_noupcall;
+
+       cons = idmap->idmap_upcall_data->key_cons;
 
        if (mlen != sizeof(im)) {
                ret = -ENOSPC;
@@ -768,16 +803,19 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
        if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ) {
                ret = -EINVAL;
                goto out;
-       }
+}
 
-       ret = nfs_idmap_read_message(&im, cons->key, cons->authkey);
+       ret = nfs_idmap_read_and_verify_message(&im,
+                       &idmap->idmap_upcall_data->idmap_msg,
+                       cons->key, cons->authkey);
        if (ret >= 0) {
                key_set_timeout(cons->key, nfs_idmap_cache_timeout);
                ret = mlen;
        }
 
 out:
-       complete_request_key(cons, ret);
+       nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
+out_noupcall:
        return ret;
 }
 
@@ -788,14 +826,9 @@ idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg)
                        struct idmap_legacy_upcalldata,
                        pipe_msg);
        struct idmap *idmap = data->idmap;
-       struct key_construction *cons;
-       if (msg->errno) {
-               cons = ACCESS_ONCE(idmap->idmap_key_cons);
-               idmap->idmap_key_cons = NULL;
-               complete_request_key(cons, msg->errno);
-       }
-       /* Free memory allocated in nfs_idmap_legacy_upcall() */
-       kfree(data);
+
+       if (msg->errno)
+               nfs_idmap_abort_pipe_upcall(idmap, msg->errno);
 }
 
 static void
@@ -803,7 +836,8 @@ idmap_release_pipe(struct inode *inode)
 {
        struct rpc_inode *rpci = RPC_I(inode);
        struct idmap *idmap = (struct idmap *)rpci->private;
-       idmap->idmap_key_cons = NULL;
+
+       nfs_idmap_abort_pipe_upcall(idmap, -EPIPE);
 }
 
 int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid)
index e4c716d374a86b16352f539a1cdd364c652986ad..5c7325c5c5e66b23beacd6fb7485fda5a640dcd9 100644 (file)
@@ -547,8 +547,8 @@ EXPORT_SYMBOL_GPL(nfs_getattr);
 static void nfs_init_lock_context(struct nfs_lock_context *l_ctx)
 {
        atomic_set(&l_ctx->count, 1);
-       l_ctx->lockowner = current->files;
-       l_ctx->pid = current->tgid;
+       l_ctx->lockowner.l_owner = current->files;
+       l_ctx->lockowner.l_pid = current->tgid;
        INIT_LIST_HEAD(&l_ctx->list);
 }
 
@@ -557,9 +557,9 @@ static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context
        struct nfs_lock_context *pos;
 
        list_for_each_entry(pos, &ctx->lock_context.list, list) {
-               if (pos->lockowner != current->files)
+               if (pos->lockowner.l_owner != current->files)
                        continue;
-               if (pos->pid != current->tgid)
+               if (pos->lockowner.l_pid != current->tgid)
                        continue;
                atomic_inc(&pos->count);
                return pos;
@@ -578,7 +578,7 @@ struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx)
                spin_unlock(&inode->i_lock);
                new = kmalloc(sizeof(*new), GFP_KERNEL);
                if (new == NULL)
-                       return NULL;
+                       return ERR_PTR(-ENOMEM);
                nfs_init_lock_context(new);
                spin_lock(&inode->i_lock);
                res = __nfs_find_lock_context(ctx);
index 31fdb03225cd0ed989424dddf361698394aa1241..59b133c5d652df5d2397b1e24e22f390fed459fc 100644 (file)
@@ -101,11 +101,11 @@ struct nfs_client_initdata {
  */
 struct nfs_parsed_mount_data {
        int                     flags;
-       int                     rsize, wsize;
-       int                     timeo, retrans;
-       int                     acregmin, acregmax,
+       unsigned int            rsize, wsize;
+       unsigned int            timeo, retrans;
+       unsigned int            acregmin, acregmax,
                                acdirmin, acdirmax;
-       int                     namlen;
+       unsigned int            namlen;
        unsigned int            options;
        unsigned int            bsize;
        unsigned int            auth_flavor_len;
@@ -464,6 +464,7 @@ static inline void nfs_inode_dio_wait(struct inode *inode)
 {
        inode_dio_wait(inode);
 }
+extern ssize_t nfs_dreq_bytes_left(struct nfs_direct_req *dreq);
 
 /* nfs4proc.c */
 extern void __nfs4_read_done_cb(struct nfs_read_data *);
@@ -483,6 +484,12 @@ extern int _nfs4_call_sync_session(struct rpc_clnt *clnt,
                                   struct nfs4_sequence_args *args,
                                   struct nfs4_sequence_res *res,
                                   int cache_reply);
+extern int nfs40_walk_client_list(struct nfs_client *clp,
+                               struct nfs_client **result,
+                               struct rpc_cred *cred);
+extern int nfs41_walk_client_list(struct nfs_client *clp,
+                               struct nfs_client **result,
+                               struct rpc_cred *cred);
 
 /*
  * Determine the device name as a string
index 0539de1b8d1fe3477500b400ff2b9b6d5781b984..8ee1fab832686ed068468c5de8b12789af8a6371 100644 (file)
@@ -5,6 +5,7 @@
 #ifndef __NFS_NETNS_H__
 #define __NFS_NETNS_H__
 
+#include <linux/nfs4.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 
@@ -22,6 +23,9 @@ struct nfs_net {
        struct list_head nfs_volume_list;
 #if IS_ENABLED(CONFIG_NFS_V4)
        struct idr cb_ident_idr; /* Protected by nfs_client_lock */
+       unsigned short nfs_callback_tcpport;
+       unsigned short nfs_callback_tcpport6;
+       int cb_users[NFS4_MAX_MINOR_VERSION + 1];
 #endif
        spinlock_t nfs_client_lock;
        struct timespec boot_time;
index da0618aeeadb88c04447a63b18e2d908b6d03955..a525fdefccdeb475edb9468c1467e6196db20246 100644 (file)
@@ -132,8 +132,8 @@ struct nfs4_lock_owner {
 struct nfs4_lock_state {
        struct list_head        ls_locks;       /* Other lock stateids */
        struct nfs4_state *     ls_state;       /* Pointer to open state */
-#define NFS_LOCK_INITIALIZED 1
-       int                     ls_flags;
+#define NFS_LOCK_INITIALIZED 0
+       unsigned long           ls_flags;
        struct nfs_seqid_counter        ls_seqid;
        nfs4_stateid            ls_stateid;
        atomic_t                ls_count;
@@ -191,6 +191,8 @@ struct nfs4_state_recovery_ops {
        int (*establish_clid)(struct nfs_client *, struct rpc_cred *);
        struct rpc_cred * (*get_clid_cred)(struct nfs_client *);
        int (*reclaim_complete)(struct nfs_client *);
+       int (*detect_trunking)(struct nfs_client *, struct nfs_client **,
+               struct rpc_cred *);
 };
 
 struct nfs4_state_maintenance_ops {
@@ -223,7 +225,7 @@ extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred);
 extern int nfs4_destroy_clientid(struct nfs_client *clp);
 extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
-extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc);
+extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
 extern int nfs4_proc_fs_locations(struct rpc_clnt *, struct inode *, const struct qstr *,
                                  struct nfs4_fs_locations *, struct page *);
@@ -320,9 +322,15 @@ extern void nfs4_renew_state(struct work_struct *);
 /* nfs4state.c */
 struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp);
 struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp);
+int nfs4_discover_server_trunking(struct nfs_client *clp,
+                       struct nfs_client **);
+int nfs40_discover_server_trunking(struct nfs_client *clp,
+                       struct nfs_client **, struct rpc_cred *);
 #if defined(CONFIG_NFS_V4_1)
 struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp);
 struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp);
+int nfs41_discover_server_trunking(struct nfs_client *clp,
+                       struct nfs_client **, struct rpc_cred *);
 extern void nfs4_schedule_session_recovery(struct nfs4_session *, int);
 #else
 static inline void nfs4_schedule_session_recovery(struct nfs4_session *session, int err)
@@ -351,7 +359,7 @@ extern void nfs41_handle_server_scope(struct nfs_client *,
 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
 extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
 extern void nfs4_select_rw_stateid(nfs4_stateid *, struct nfs4_state *,
-               fmode_t, fl_owner_t, pid_t);
+               fmode_t, const struct nfs_lockowner *);
 
 extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask);
 extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task);
@@ -372,6 +380,9 @@ extern bool nfs4_disable_idmapping;
 extern unsigned short max_session_slots;
 extern unsigned short send_implementation_id;
 
+#define NFS4_CLIENT_ID_UNIQ_LEN                (64)
+extern char nfs4_client_id_uniquifier[NFS4_CLIENT_ID_UNIQ_LEN];
+
 /* nfs4sysctl.c */
 #ifdef CONFIG_SYSCTL
 int nfs4_register_sysctl(void);
index 24eb663f8ed528426572471a629ab033726919d8..6bacfde1319a76945a9ab9634e453f8a61def8ce 100644 (file)
@@ -84,7 +84,7 @@ error:
 static void nfs4_destroy_callback(struct nfs_client *clp)
 {
        if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
-               nfs_callback_down(clp->cl_mvops->minor_version);
+               nfs_callback_down(clp->cl_mvops->minor_version, clp->cl_net);
 }
 
 static void nfs4_shutdown_client(struct nfs_client *clp)
@@ -185,6 +185,7 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
                                    rpc_authflavor_t authflavour)
 {
        char buf[INET6_ADDRSTRLEN + 1];
+       struct nfs_client *old;
        int error;
 
        if (clp->cl_cons_state == NFS_CS_READY) {
@@ -230,6 +231,17 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
 
        if (!nfs4_has_session(clp))
                nfs_mark_client_ready(clp, NFS_CS_READY);
+
+       error = nfs4_discover_server_trunking(clp, &old);
+       if (error < 0)
+               goto error;
+       if (clp != old) {
+               clp->cl_preserve_clid = true;
+               nfs_put_client(clp);
+               clp = old;
+               atomic_inc(&clp->cl_count);
+       }
+
        return clp;
 
 error:
@@ -239,6 +251,248 @@ error:
        return ERR_PTR(error);
 }
 
+/*
+ * SETCLIENTID just did a callback update with the callback ident in
+ * "drop," but server trunking discovery claims "drop" and "keep" are
+ * actually the same server.  Swap the callback IDs so that "keep"
+ * will continue to use the callback ident the server now knows about,
+ * and so that "keep"'s original callback ident is destroyed when
+ * "drop" is freed.
+ */
+static void nfs4_swap_callback_idents(struct nfs_client *keep,
+                                     struct nfs_client *drop)
+{
+       struct nfs_net *nn = net_generic(keep->cl_net, nfs_net_id);
+       unsigned int save = keep->cl_cb_ident;
+
+       if (keep->cl_cb_ident == drop->cl_cb_ident)
+               return;
+
+       dprintk("%s: keeping callback ident %u and dropping ident %u\n",
+               __func__, keep->cl_cb_ident, drop->cl_cb_ident);
+
+       spin_lock(&nn->nfs_client_lock);
+
+       idr_replace(&nn->cb_ident_idr, keep, drop->cl_cb_ident);
+       keep->cl_cb_ident = drop->cl_cb_ident;
+
+       idr_replace(&nn->cb_ident_idr, drop, save);
+       drop->cl_cb_ident = save;
+
+       spin_unlock(&nn->nfs_client_lock);
+}
+
+/**
+ * nfs40_walk_client_list - Find server that recognizes a client ID
+ *
+ * @new: nfs_client with client ID to test
+ * @result: OUT: found nfs_client, or new
+ * @cred: credential to use for trunking test
+ *
+ * Returns zero, a negative errno, or a negative NFS4ERR status.
+ * If zero is returned, an nfs_client pointer is planted in "result."
+ *
+ * NB: nfs40_walk_client_list() relies on the new nfs_client being
+ *     the last nfs_client on the list.
+ */
+int nfs40_walk_client_list(struct nfs_client *new,
+                          struct nfs_client **result,
+                          struct rpc_cred *cred)
+{
+       struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
+       struct nfs_client *pos, *n, *prev = NULL;
+       struct nfs4_setclientid_res clid = {
+               .clientid       = new->cl_clientid,
+               .confirm        = new->cl_confirm,
+       };
+       int status;
+
+       spin_lock(&nn->nfs_client_lock);
+       list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
+               /* If "pos" isn't marked ready, we can't trust the
+                * remaining fields in "pos" */
+               if (pos->cl_cons_state < NFS_CS_READY)
+                       continue;
+
+               if (pos->rpc_ops != new->rpc_ops)
+                       continue;
+
+               if (pos->cl_proto != new->cl_proto)
+                       continue;
+
+               if (pos->cl_minorversion != new->cl_minorversion)
+                       continue;
+
+               if (pos->cl_clientid != new->cl_clientid)
+                       continue;
+
+               atomic_inc(&pos->cl_count);
+               spin_unlock(&nn->nfs_client_lock);
+
+               if (prev)
+                       nfs_put_client(prev);
+
+               status = nfs4_proc_setclientid_confirm(pos, &clid, cred);
+               if (status == 0) {
+                       nfs4_swap_callback_idents(pos, new);
+
+                       nfs_put_client(pos);
+                       *result = pos;
+                       dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
+                               __func__, pos, atomic_read(&pos->cl_count));
+                       return 0;
+               }
+               if (status != -NFS4ERR_STALE_CLIENTID) {
+                       nfs_put_client(pos);
+                       dprintk("NFS: <-- %s status = %d, no result\n",
+                               __func__, status);
+                       return status;
+               }
+
+               spin_lock(&nn->nfs_client_lock);
+               prev = pos;
+       }
+
+       /*
+        * No matching nfs_client found.  This should be impossible,
+        * because the new nfs_client has already been added to
+        * nfs_client_list by nfs_get_client().
+        *
+        * Don't BUG(), since the caller is holding a mutex.
+        */
+       if (prev)
+               nfs_put_client(prev);
+       spin_unlock(&nn->nfs_client_lock);
+       pr_err("NFS: %s Error: no matching nfs_client found\n", __func__);
+       return -NFS4ERR_STALE_CLIENTID;
+}
+
+#ifdef CONFIG_NFS_V4_1
+/*
+ * Returns true if the client IDs match
+ */
+static bool nfs4_match_clientids(struct nfs_client *a, struct nfs_client *b)
+{
+       if (a->cl_clientid != b->cl_clientid) {
+               dprintk("NFS: --> %s client ID %llx does not match %llx\n",
+                       __func__, a->cl_clientid, b->cl_clientid);
+               return false;
+       }
+       dprintk("NFS: --> %s client ID %llx matches %llx\n",
+               __func__, a->cl_clientid, b->cl_clientid);
+       return true;
+}
+
+/*
+ * Returns true if the server owners match
+ */
+static bool
+nfs4_match_serverowners(struct nfs_client *a, struct nfs_client *b)
+{
+       struct nfs41_server_owner *o1 = a->cl_serverowner;
+       struct nfs41_server_owner *o2 = b->cl_serverowner;
+
+       if (o1->minor_id != o2->minor_id) {
+               dprintk("NFS: --> %s server owner minor IDs do not match\n",
+                       __func__);
+               return false;
+       }
+
+       if (o1->major_id_sz != o2->major_id_sz)
+               goto out_major_mismatch;
+       if (memcmp(o1->major_id, o2->major_id, o1->major_id_sz) != 0)
+               goto out_major_mismatch;
+
+       dprintk("NFS: --> %s server owners match\n", __func__);
+       return true;
+
+out_major_mismatch:
+       dprintk("NFS: --> %s server owner major IDs do not match\n",
+               __func__);
+       return false;
+}
+
+/**
+ * nfs41_walk_client_list - Find nfs_client that matches a client/server owner
+ *
+ * @new: nfs_client with client ID to test
+ * @result: OUT: found nfs_client, or new
+ * @cred: credential to use for trunking test
+ *
+ * Returns zero, a negative errno, or a negative NFS4ERR status.
+ * If zero is returned, an nfs_client pointer is planted in "result."
+ *
+ * NB: nfs41_walk_client_list() relies on the new nfs_client being
+ *     the last nfs_client on the list.
+ */
+int nfs41_walk_client_list(struct nfs_client *new,
+                          struct nfs_client **result,
+                          struct rpc_cred *cred)
+{
+       struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
+       struct nfs_client *pos, *n, *prev = NULL;
+       int error;
+
+       spin_lock(&nn->nfs_client_lock);
+       list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
+               /* If "pos" isn't marked ready, we can't trust the
+                * remaining fields in "pos", especially the client
+                * ID and serverowner fields.  Wait for CREATE_SESSION
+                * to finish. */
+               if (pos->cl_cons_state < NFS_CS_READY) {
+                       atomic_inc(&pos->cl_count);
+                       spin_unlock(&nn->nfs_client_lock);
+
+                       if (prev)
+                               nfs_put_client(prev);
+                       prev = pos;
+
+                       error = nfs_wait_client_init_complete(pos);
+                       if (error < 0) {
+                               nfs_put_client(pos);
+                               spin_lock(&nn->nfs_client_lock);
+                               continue;
+                       }
+
+                       spin_lock(&nn->nfs_client_lock);
+               }
+
+               if (pos->rpc_ops != new->rpc_ops)
+                       continue;
+
+               if (pos->cl_proto != new->cl_proto)
+                       continue;
+
+               if (pos->cl_minorversion != new->cl_minorversion)
+                       continue;
+
+               if (!nfs4_match_clientids(pos, new))
+                       continue;
+
+               if (!nfs4_match_serverowners(pos, new))
+                       continue;
+
+               spin_unlock(&nn->nfs_client_lock);
+               dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
+                       __func__, pos, atomic_read(&pos->cl_count));
+
+               *result = pos;
+               return 0;
+       }
+
+       /*
+        * No matching nfs_client found.  This should be impossible,
+        * because the new nfs_client has already been added to
+        * nfs_client_list by nfs_get_client().
+        *
+        * Don't BUG(), since the caller is holding a mutex.
+        */
+       spin_unlock(&nn->nfs_client_lock);
+       pr_err("NFS: %s Error: no matching nfs_client found\n", __func__);
+       return -NFS4ERR_STALE_CLIENTID;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
 static void nfs4_destroy_server(struct nfs_server *server)
 {
        nfs_server_return_all_delegations(server);
index eb5eb8eef4d34db3c7bafe3c84c1db0bf43e8974..afddd6639afb1bd5242e95c5b659fa2b86174181 100644 (file)
@@ -95,16 +95,25 @@ nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
        int ret;
        struct inode *inode = file->f_path.dentry->d_inode;
 
-       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
-       if (ret != 0)
-               goto out;
-       mutex_lock(&inode->i_mutex);
-       ret = nfs_file_fsync_commit(file, start, end, datasync);
-       if (!ret && !datasync)
-               /* application has asked for meta-data sync */
-               ret = pnfs_layoutcommit_inode(inode, true);
-       mutex_unlock(&inode->i_mutex);
-out:
+       do {
+               ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+               if (ret != 0)
+                       break;
+               mutex_lock(&inode->i_mutex);
+               ret = nfs_file_fsync_commit(file, start, end, datasync);
+               if (!ret && !datasync)
+                       /* application has asked for meta-data sync */
+                       ret = pnfs_layoutcommit_inode(inode, true);
+               mutex_unlock(&inode->i_mutex);
+               /*
+                * If nfs_file_fsync_commit detected a server reboot, then
+                * resend all dirty pages that might have been covered by
+                * the NFS_CONTEXT_RESEND_WRITES flag
+                */
+               start = 0;
+               end = LLONG_MAX;
+       } while (ret == -EAGAIN);
+
        return ret;
 }
 
index 53f94d915bd18ce77c4cf542ebc25378c56f2add..52d8472120663de91855690fa0996cdf03e4a8a4 100644 (file)
@@ -190,8 +190,6 @@ static int filelayout_async_handle_error(struct rpc_task *task,
                 * i/o and all i/o waiting on the slot table to the MDS until
                 * layout is destroyed and a new valid layout is obtained.
                 */
-               set_bit(NFS_LAYOUT_INVALID,
-                               &NFS_I(inode)->layout->plh_flags);
                pnfs_destroy_layout(NFS_I(inode));
                rpc_wake_up(&tbl->slot_tbl_waitq);
                goto reset;
@@ -205,7 +203,7 @@ static int filelayout_async_handle_error(struct rpc_task *task,
        case -EPIPE:
                dprintk("%s DS connection error %d\n", __func__,
                        task->tk_status);
-               filelayout_mark_devid_invalid(devid);
+               nfs4_mark_deviceid_unavailable(devid);
                clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
                _pnfs_return_layout(inode);
                rpc_wake_up(&tbl->slot_tbl_waitq);
@@ -269,6 +267,21 @@ filelayout_set_layoutcommit(struct nfs_write_data *wdata)
                (unsigned long) NFS_I(hdr->inode)->layout->plh_lwb);
 }
 
+bool
+filelayout_test_devid_unavailable(struct nfs4_deviceid_node *node)
+{
+       return filelayout_test_devid_invalid(node) ||
+               nfs4_test_deviceid_unavailable(node);
+}
+
+static bool
+filelayout_reset_to_mds(struct pnfs_layout_segment *lseg)
+{
+       struct nfs4_deviceid_node *node = FILELAYOUT_DEVID_NODE(lseg);
+
+       return filelayout_test_devid_unavailable(node);
+}
+
 /*
  * Call ops for the async read/write cases
  * In the case of dense layouts, the offset needs to be reset to its
@@ -453,7 +466,7 @@ static void filelayout_commit_release(void *calldata)
        struct nfs_commit_data *data = calldata;
 
        data->completion_ops->completion(data);
-       put_lseg(data->lseg);
+       pnfs_put_lseg(data->lseg);
        nfs_put_client(data->ds_clp);
        nfs_commitdata_release(data);
 }
@@ -608,13 +621,13 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
        d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode)->pnfs_curr_ld,
                                   NFS_SERVER(lo->plh_inode)->nfs_client, id);
        if (d == NULL) {
-               dsaddr = get_device_info(lo->plh_inode, id, gfp_flags);
+               dsaddr = filelayout_get_device_info(lo->plh_inode, id, gfp_flags);
                if (dsaddr == NULL)
                        goto out;
        } else
                dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node);
-       /* Found deviceid is being reaped */
-       if (test_bit(NFS_DEVICEID_INVALID, &dsaddr->id_node.flags))
+       /* Found deviceid is unavailable */
+       if (filelayout_test_devid_unavailable(&dsaddr->id_node))
                        goto out_put;
 
        fl->dsaddr = dsaddr;
@@ -931,7 +944,7 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
        nfs_init_cinfo(&cinfo, pgio->pg_inode, pgio->pg_dreq);
        status = filelayout_alloc_commit_info(pgio->pg_lseg, &cinfo, GFP_NOFS);
        if (status < 0) {
-               put_lseg(pgio->pg_lseg);
+               pnfs_put_lseg(pgio->pg_lseg);
                pgio->pg_lseg = NULL;
                goto out_mds;
        }
@@ -985,7 +998,7 @@ filelayout_clear_request_commit(struct nfs_page *req,
 out:
        nfs_request_remove_commit_list(req, cinfo);
        spin_unlock(cinfo->lock);
-       put_lseg(freeme);
+       pnfs_put_lseg(freeme);
 }
 
 static struct list_head *
@@ -1018,7 +1031,7 @@ filelayout_choose_commit_list(struct nfs_page *req,
                 * off due to a rewrite, in which case it will be done in
                 * filelayout_clear_request_commit
                 */
-               buckets[i].wlseg = get_lseg(lseg);
+               buckets[i].wlseg = pnfs_get_lseg(lseg);
        }
        set_bit(PG_COMMIT_TO_DS, &req->wb_flags);
        cinfo->ds->nwritten++;
@@ -1128,7 +1141,7 @@ filelayout_scan_ds_commit_list(struct pnfs_commit_bucket *bucket,
                if (list_empty(src))
                        bucket->wlseg = NULL;
                else
-                       get_lseg(bucket->clseg);
+                       pnfs_get_lseg(bucket->clseg);
        }
        return ret;
 }
@@ -1159,12 +1172,12 @@ static void filelayout_recover_commit_reqs(struct list_head *dst,
 
        /* NOTE cinfo->lock is NOT held, relying on fact that this is
         * only called on single thread per dreq.
-        * Can't take the lock because need to do put_lseg
+        * Can't take the lock because need to do pnfs_put_lseg
         */
        for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) {
                if (transfer_commit_list(&b->written, dst, cinfo, 0)) {
                        BUG_ON(!list_empty(&b->written));
-                       put_lseg(b->wlseg);
+                       pnfs_put_lseg(b->wlseg);
                        b->wlseg = NULL;
                }
        }
@@ -1200,7 +1213,7 @@ alloc_ds_commits(struct nfs_commit_info *cinfo, struct list_head *list)
                if (list_empty(&bucket->committing))
                        continue;
                nfs_retry_commit(&bucket->committing, bucket->clseg, cinfo);
-               put_lseg(bucket->clseg);
+               pnfs_put_lseg(bucket->clseg);
                bucket->clseg = NULL;
        }
        /* Caller will clean up entries put on list */
index 43fe802dd67855fbfe521825d0c24ef3acca7c38..dca47d78671026810c67b139763cd1b27548d42d 100644 (file)
@@ -128,24 +128,14 @@ filelayout_mark_devid_invalid(struct nfs4_deviceid_node *node)
        set_bit(NFS_DEVICEID_INVALID, &node->flags);
 }
 
-static inline bool
-filelayout_test_layout_invalid(struct pnfs_layout_hdr *lo)
-{
-       return test_bit(NFS_LAYOUT_INVALID, &lo->plh_flags);
-}
-
 static inline bool
 filelayout_test_devid_invalid(struct nfs4_deviceid_node *node)
 {
        return test_bit(NFS_DEVICEID_INVALID, &node->flags);
 }
 
-static inline bool
-filelayout_reset_to_mds(struct pnfs_layout_segment *lseg)
-{
-       return filelayout_test_devid_invalid(FILELAYOUT_DEVID_NODE(lseg)) ||
-               filelayout_test_layout_invalid(lseg->pls_layout);
-}
+extern bool
+filelayout_test_devid_unavailable(struct nfs4_deviceid_node *node);
 
 extern struct nfs_fh *
 nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j);
@@ -158,7 +148,7 @@ struct nfs4_pnfs_ds *nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg,
 extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
 extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
 struct nfs4_file_layout_dsaddr *
-get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags);
+filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags);
 void nfs4_ds_disconnect(struct nfs_client *clp);
 
 #endif /* FS_NFS_NFS4FILELAYOUT_H */
index f81231f30d949aa5d6b8a328cce91b792c656004..3336d5eaf879adc07a2e95f64b512835935763a6 100644 (file)
@@ -690,7 +690,7 @@ decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_fl
  * of available devices, and return it.
  */
 struct nfs4_file_layout_dsaddr *
-get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags)
+filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags)
 {
        struct pnfs_device *pdev = NULL;
        u32 max_resp_sz;
@@ -804,13 +804,14 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
        struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx];
        struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
 
-       if (filelayout_test_devid_invalid(devid))
+       if (filelayout_test_devid_unavailable(devid))
                return NULL;
 
        if (ds == NULL) {
                printk(KERN_ERR "NFS: %s: No data server for offset index %d\n",
                        __func__, ds_idx);
-               goto mark_dev_invalid;
+               filelayout_mark_devid_invalid(devid);
+               return NULL;
        }
 
        if (!ds->ds_clp) {
@@ -818,14 +819,12 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
                int err;
 
                err = nfs4_ds_connect(s, ds);
-               if (err)
-                       goto mark_dev_invalid;
+               if (err) {
+                       nfs4_mark_deviceid_unavailable(devid);
+                       return NULL;
+               }
        }
        return ds;
-
-mark_dev_invalid:
-       filelayout_mark_devid_invalid(devid);
-       return NULL;
 }
 
 module_param(dataserver_retrans, uint, 0644);
index 017b4b01a69c7a747b4afab8c7591b5f2ac59a20..79fbb61ce202bcb90df2c8ad0f7f3ecf3bba7aac 100644 (file)
@@ -192,25 +192,13 @@ out:
 struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *clnt, struct inode *inode,
                                        struct qstr *name)
 {
-       struct rpc_clnt *clone;
-       struct rpc_auth *auth;
        rpc_authflavor_t flavor;
 
        flavor = nfs4_negotiate_security(inode, name);
        if ((int)flavor < 0)
-               return ERR_PTR(flavor);
+               return ERR_PTR((int)flavor);
 
-       clone = rpc_clone_client(clnt);
-       if (IS_ERR(clone))
-               return clone;
-
-       auth = rpcauth_create(flavor, clone);
-       if (!auth) {
-               rpc_shutdown_client(clone);
-               clone = ERR_PTR(-EIO);
-       }
-
-       return clone;
+       return rpc_clone_client_set_auth(clnt, flavor);
 }
 
 static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
index 1e50326d00ddd1f7ef8931470bc1cd0ad32b4015..68b21d81b7acfa79bef010023195c1f45023c82b 100644 (file)
@@ -104,6 +104,8 @@ static int nfs4_map_errors(int err)
                return -EACCES;
        case -NFS4ERR_MINOR_VERS_MISMATCH:
                return -EPROTONOSUPPORT;
+       case -NFS4ERR_ACCESS:
+               return -EACCES;
        default:
                dprintk("%s could not handle NFSv4 error %d\n",
                                __func__, -err);
@@ -150,6 +152,12 @@ static const u32 nfs4_pnfs_open_bitmap[3] = {
        FATTR4_WORD2_MDSTHRESHOLD
 };
 
+static const u32 nfs4_open_noattr_bitmap[3] = {
+       FATTR4_WORD0_TYPE
+       | FATTR4_WORD0_CHANGE
+       | FATTR4_WORD0_FILEID,
+};
+
 const u32 nfs4_statfs_bitmap[2] = {
        FATTR4_WORD0_FILES_AVAIL
        | FATTR4_WORD0_FILES_FREE
@@ -832,6 +840,7 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
        p->o_res.seqid = p->o_arg.seqid;
        p->c_res.seqid = p->c_arg.seqid;
        p->o_res.server = p->o_arg.server;
+       p->o_res.access_request = p->o_arg.access;
        nfs_fattr_init(&p->f_attr);
        nfs_fattr_init_names(&p->f_attr, &p->owner_name, &p->group_name);
 }
@@ -860,6 +869,14 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
        p->o_arg.fh = NFS_FH(dir);
        p->o_arg.open_flags = flags;
        p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
+       /* don't put an ACCESS op in OPEN compound if O_EXCL, because ACCESS
+        * will return permission denied for all bits until close */
+       if (!(flags & O_EXCL)) {
+               /* ask server to check for all possible rights as results
+                * are cached */
+               p->o_arg.access = NFS4_ACCESS_READ | NFS4_ACCESS_MODIFY |
+                                 NFS4_ACCESS_EXTEND | NFS4_ACCESS_EXECUTE;
+       }
        p->o_arg.clientid = server->nfs_client->cl_clientid;
        p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time);
        p->o_arg.id.uniquifier = sp->so_seqid.owner_id;
@@ -1115,11 +1132,80 @@ out_return_state:
        return state;
 }
 
-static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
+static void
+nfs4_opendata_check_deleg(struct nfs4_opendata *data, struct nfs4_state *state)
+{
+       struct nfs_client *clp = NFS_SERVER(state->inode)->nfs_client;
+       struct nfs_delegation *delegation;
+       int delegation_flags = 0;
+
+       rcu_read_lock();
+       delegation = rcu_dereference(NFS_I(state->inode)->delegation);
+       if (delegation)
+               delegation_flags = delegation->flags;
+       rcu_read_unlock();
+       if (data->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR) {
+               pr_err_ratelimited("NFS: Broken NFSv4 server %s is "
+                                  "returning a delegation for "
+                                  "OPEN(CLAIM_DELEGATE_CUR)\n",
+                                  clp->cl_hostname);
+       } else if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0)
+               nfs_inode_set_delegation(state->inode,
+                                        data->owner->so_cred,
+                                        &data->o_res);
+       else
+               nfs_inode_reclaim_delegation(state->inode,
+                                            data->owner->so_cred,
+                                            &data->o_res);
+}
+
+/*
+ * Check the inode attributes against the CLAIM_PREVIOUS returned attributes
+ * and update the nfs4_state.
+ */
+static struct nfs4_state *
+_nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data)
+{
+       struct inode *inode = data->state->inode;
+       struct nfs4_state *state = data->state;
+       int ret;
+
+       if (!data->rpc_done) {
+               ret = data->rpc_status;
+               goto err;
+       }
+
+       ret = -ESTALE;
+       if (!(data->f_attr.valid & NFS_ATTR_FATTR_TYPE) ||
+           !(data->f_attr.valid & NFS_ATTR_FATTR_FILEID) ||
+           !(data->f_attr.valid & NFS_ATTR_FATTR_CHANGE))
+               goto err;
+
+       ret = -ENOMEM;
+       state = nfs4_get_open_state(inode, data->owner);
+       if (state == NULL)
+               goto err;
+
+       ret = nfs_refresh_inode(inode, &data->f_attr);
+       if (ret)
+               goto err;
+
+       if (data->o_res.delegation_type != 0)
+               nfs4_opendata_check_deleg(data, state);
+       update_open_stateid(state, &data->o_res.stateid, NULL,
+                           data->o_arg.fmode);
+
+       return state;
+err:
+       return ERR_PTR(ret);
+
+}
+
+static struct nfs4_state *
+_nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
 {
        struct inode *inode;
        struct nfs4_state *state = NULL;
-       struct nfs_delegation *delegation;
        int ret;
 
        if (!data->rpc_done) {
@@ -1138,30 +1224,8 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data
        state = nfs4_get_open_state(inode, data->owner);
        if (state == NULL)
                goto err_put_inode;
-       if (data->o_res.delegation_type != 0) {
-               struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
-               int delegation_flags = 0;
-
-               rcu_read_lock();
-               delegation = rcu_dereference(NFS_I(inode)->delegation);
-               if (delegation)
-                       delegation_flags = delegation->flags;
-               rcu_read_unlock();
-               if (data->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR) {
-                       pr_err_ratelimited("NFS: Broken NFSv4 server %s is "
-                                       "returning a delegation for "
-                                       "OPEN(CLAIM_DELEGATE_CUR)\n",
-                                       clp->cl_hostname);
-               } else if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0)
-                       nfs_inode_set_delegation(state->inode,
-                                       data->owner->so_cred,
-                                       &data->o_res);
-               else
-                       nfs_inode_reclaim_delegation(state->inode,
-                                       data->owner->so_cred,
-                                       &data->o_res);
-       }
-
+       if (data->o_res.delegation_type != 0)
+               nfs4_opendata_check_deleg(data, state);
        update_open_stateid(state, &data->o_res.stateid, NULL,
                        data->o_arg.fmode);
        iput(inode);
@@ -1173,6 +1237,14 @@ err:
        return ERR_PTR(ret);
 }
 
+static struct nfs4_state *
+nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
+{
+       if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS)
+               return _nfs4_opendata_reclaim_to_nfs4_state(data);
+       return _nfs4_opendata_to_nfs4_state(data);
+}
+
 static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state)
 {
        struct nfs_inode *nfsi = NFS_I(state->inode);
@@ -1494,6 +1566,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
        data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid;
        if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
                task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
+               data->o_arg.open_bitmap = &nfs4_open_noattr_bitmap[0];
                nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
        }
        data->timestamp = jiffies;
@@ -1526,7 +1599,8 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
                return;
 
        if (task->tk_status == 0) {
-               switch (data->o_res.f_attr->mode & S_IFMT) {
+               if (data->o_res.f_attr->valid & NFS_ATTR_FATTR_TYPE) {
+                       switch (data->o_res.f_attr->mode & S_IFMT) {
                        case S_IFREG:
                                break;
                        case S_IFLNK:
@@ -1537,6 +1611,7 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
                                break;
                        default:
                                data->rpc_status = -ENOTDIR;
+                       }
                }
                renew_lease(data->o_res.server, data->timestamp);
                if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM))
@@ -1643,6 +1718,39 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data)
        return status;
 }
 
+static int nfs4_opendata_access(struct rpc_cred *cred,
+                               struct nfs4_opendata *opendata,
+                               struct nfs4_state *state, fmode_t fmode)
+{
+       struct nfs_access_entry cache;
+       u32 mask;
+
+       /* access call failed or for some reason the server doesn't
+        * support any access modes -- defer access call until later */
+       if (opendata->o_res.access_supported == 0)
+               return 0;
+
+       mask = 0;
+       /* don't check MAY_WRITE - a newly created file may not have
+        * write mode bits, but POSIX allows the creating process to write */
+       if (fmode & FMODE_READ)
+               mask |= MAY_READ;
+       if (fmode & FMODE_EXEC)
+               mask |= MAY_EXEC;
+
+       cache.cred = cred;
+       cache.jiffies = jiffies;
+       nfs_access_set_mask(&cache, opendata->o_res.access_result);
+       nfs_access_add_cache(state->inode, &cache);
+
+       if ((mask & ~cache.mask & (MAY_READ | MAY_EXEC)) == 0)
+               return 0;
+
+       /* even though OPEN succeeded, access is denied. Close the file */
+       nfs4_close_state(state, fmode);
+       return -NFS4ERR_ACCESS;
+}
+
 /*
  * Note: On error, nfs4_proc_open will free the struct nfs4_opendata
  */
@@ -1774,7 +1882,11 @@ static void nfs41_clear_delegation_stateid(struct nfs4_state *state)
                 * informs us the stateid is unrecognized. */
                if (status != -NFS4ERR_BAD_STATEID)
                        nfs41_free_stateid(server, stateid);
+               nfs_remove_bad_delegation(state->inode);
 
+               write_seqlock(&state->seqlock);
+               nfs4_stateid_copy(&state->stateid, &state->open_stateid);
+               write_sequnlock(&state->seqlock);
                clear_bit(NFS_DELEGATED_STATE, &state->flags);
        }
 }
@@ -1790,7 +1902,7 @@ static void nfs41_clear_delegation_stateid(struct nfs4_state *state)
 static int nfs41_check_open_stateid(struct nfs4_state *state)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
-       nfs4_stateid *stateid = &state->stateid;
+       nfs4_stateid *stateid = &state->open_stateid;
        int status;
 
        /* If a state reset has been done, test_stateid is unneeded */
@@ -1896,6 +2008,10 @@ static int _nfs4_do_open(struct inode *dir,
        if (server->caps & NFS_CAP_POSIX_LOCK)
                set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
 
+       status = nfs4_opendata_access(cred, opendata, state, fmode);
+       if (status != 0)
+               goto err_opendata_put;
+
        if (opendata->o_arg.open_flags & O_EXCL) {
                nfs4_exclusive_attrset(opendata, sattr);
 
@@ -1941,7 +2057,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir,
        struct nfs4_state *res;
        int status;
 
-       fmode &= FMODE_READ|FMODE_WRITE;
+       fmode &= FMODE_READ|FMODE_WRITE|FMODE_EXEC;
        do {
                status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred,
                                       &res, ctx_th);
@@ -2013,8 +2129,12 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
        nfs_fattr_init(fattr);
 
        if (state != NULL) {
+               struct nfs_lockowner lockowner = {
+                       .l_owner = current->files,
+                       .l_pid = current->tgid,
+               };
                nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE,
-                               current->files, current->tgid);
+                               &lockowner);
        } else if (nfs4_copy_delegation_stateid(&arg.stateid, inode,
                                FMODE_WRITE)) {
                /* Use that stateid */
@@ -2133,6 +2253,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
 {
        struct nfs4_closedata *calldata = data;
        struct nfs4_state *state = calldata->state;
+       struct inode *inode = calldata->inode;
        int call_close = 0;
 
        dprintk("%s: begin!\n", __func__);
@@ -2166,16 +2287,13 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
        if (calldata->arg.fmode == 0) {
                task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE];
                if (calldata->roc &&
-                   pnfs_roc_drain(calldata->inode, &calldata->roc_barrier)) {
-                       rpc_sleep_on(&NFS_SERVER(calldata->inode)->roc_rpcwaitq,
-                                    task, NULL);
+                   pnfs_roc_drain(inode, &calldata->roc_barrier, task))
                        goto out;
-               }
        }
 
        nfs_fattr_init(calldata->res.fattr);
        calldata->timestamp = jiffies;
-       if (nfs4_setup_sequence(NFS_SERVER(calldata->inode),
+       if (nfs4_setup_sequence(NFS_SERVER(inode),
                                &calldata->arg.seq_args,
                                &calldata->res.seq_res,
                                task))
@@ -2202,7 +2320,7 @@ static const struct rpc_call_ops nfs4_close_ops = {
  *
  * NOTE: Caller must be holding the sp->so_owner semaphore!
  */
-int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc)
+int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
        struct nfs4_closedata *calldata;
@@ -2238,7 +2356,7 @@ int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc)
        calldata->res.fattr = &calldata->fattr;
        calldata->res.seqid = calldata->arg.seqid;
        calldata->res.server = server;
-       calldata->roc = roc;
+       calldata->roc = pnfs_roc(state->inode);
        nfs_sb_active(calldata->inode->i_sb);
 
        msg.rpc_argp = &calldata->arg;
@@ -2255,8 +2373,6 @@ int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc)
 out_free_calldata:
        kfree(calldata);
 out:
-       if (roc)
-               pnfs_roc_release(state->inode);
        nfs4_put_open_state(state);
        nfs4_put_state_owner(sp);
        return status;
@@ -2399,7 +2515,7 @@ static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandl
        int ret;
 
        auth = rpcauth_create(flavor, server->client);
-       if (!auth) {
+       if (IS_ERR(auth)) {
                ret = -EIO;
                goto out;
        }
@@ -2767,13 +2883,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
 
        status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
        if (!status) {
-               entry->mask = 0;
-               if (res.access & NFS4_ACCESS_READ)
-                       entry->mask |= MAY_READ;
-               if (res.access & (NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE))
-                       entry->mask |= MAY_WRITE;
-               if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE))
-                       entry->mask |= MAY_EXEC;
+               nfs_access_set_mask(entry, res.access);
                nfs_refresh_inode(inode, res.fattr);
        }
        nfs_free_fattr(res.fattr);
@@ -3362,8 +3472,11 @@ static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, s
 
        nfs_fattr_init(fsinfo->fattr);
        error = nfs4_do_fsinfo(server, fhandle, fsinfo);
-       if (error == 0)
+       if (error == 0) {
+               /* block layout checks this! */
+               server->pnfs_blksize = fsinfo->blksize;
                set_pnfs_layoutdriver(server, fhandle, fsinfo->layouttype);
+       }
 
        return error;
 }
@@ -4007,6 +4120,36 @@ static void nfs4_init_boot_verifier(const struct nfs_client *clp,
        memcpy(bootverf->data, verf, sizeof(bootverf->data));
 }
 
+static unsigned int
+nfs4_init_nonuniform_client_string(const struct nfs_client *clp,
+                                  char *buf, size_t len)
+{
+       unsigned int result;
+
+       rcu_read_lock();
+       result = scnprintf(buf, len, "Linux NFSv4.0 %s/%s %s",
+                               clp->cl_ipaddr,
+                               rpc_peeraddr2str(clp->cl_rpcclient,
+                                                       RPC_DISPLAY_ADDR),
+                               rpc_peeraddr2str(clp->cl_rpcclient,
+                                                       RPC_DISPLAY_PROTO));
+       rcu_read_unlock();
+       return result;
+}
+
+static unsigned int
+nfs4_init_uniform_client_string(const struct nfs_client *clp,
+                               char *buf, size_t len)
+{
+       char *nodename = clp->cl_rpcclient->cl_nodename;
+
+       if (nfs4_client_id_uniquifier[0] != '\0')
+               nodename = nfs4_client_id_uniquifier;
+       return scnprintf(buf, len, "Linux NFSv%u.%u %s",
+                               clp->rpc_ops->version, clp->cl_minorversion,
+                               nodename);
+}
+
 /**
  * nfs4_proc_setclientid - Negotiate client ID
  * @clp: state data structure
@@ -4037,15 +4180,18 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
 
        /* nfs_client_id4 */
        nfs4_init_boot_verifier(clp, &sc_verifier);
-       rcu_read_lock();
-       setclientid.sc_name_len = scnprintf(setclientid.sc_name,
-                       sizeof(setclientid.sc_name), "%s/%s %s",
-                       clp->cl_ipaddr,
-                       rpc_peeraddr2str(clp->cl_rpcclient,
-                                               RPC_DISPLAY_ADDR),
-                       rpc_peeraddr2str(clp->cl_rpcclient,
-                                               RPC_DISPLAY_PROTO));
+       if (test_bit(NFS_CS_MIGRATION, &clp->cl_flags))
+               setclientid.sc_name_len =
+                               nfs4_init_uniform_client_string(clp,
+                                               setclientid.sc_name,
+                                               sizeof(setclientid.sc_name));
+       else
+               setclientid.sc_name_len =
+                               nfs4_init_nonuniform_client_string(clp,
+                                               setclientid.sc_name,
+                                               sizeof(setclientid.sc_name));
        /* cb_client4 */
+       rcu_read_lock();
        setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
                                sizeof(setclientid.sc_netid),
                                rpc_peeraddr2str(clp->cl_rpcclient,
@@ -4391,7 +4537,7 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
 
        if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
                return;
-       if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) {
+       if (test_bit(NFS_LOCK_INITIALIZED, &calldata->lsp->ls_flags) == 0) {
                /* Note: exit _without_ running nfs4_locku_done */
                task->tk_action = NULL;
                return;
@@ -4585,7 +4731,7 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
        }
        if (data->rpc_status == 0) {
                nfs4_stateid_copy(&data->lsp->ls_stateid, &data->res.stateid);
-               data->lsp->ls_flags |= NFS_LOCK_INITIALIZED;
+               set_bit(NFS_LOCK_INITIALIZED, &data->lsp->ls_flags);
                renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), data->timestamp);
        }
 out:
@@ -4632,7 +4778,7 @@ static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_
        case -NFS4ERR_BAD_STATEID:
                lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
                if (new_lock_owner != 0 ||
-                  (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
+                  test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0)
                        nfs4_schedule_stateid_recovery(server, lsp->ls_state);
                break;
        case -NFS4ERR_STALE_STATEID:
@@ -4756,7 +4902,7 @@ static int nfs41_check_expired_locks(struct nfs4_state *state)
        struct nfs_server *server = NFS_SERVER(state->inode);
 
        list_for_each_entry(lsp, &state->lock_states, ls_locks) {
-               if (lsp->ls_flags & NFS_LOCK_INITIALIZED) {
+               if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) {
                        status = nfs41_test_stateid(server, &lsp->ls_stateid);
                        if (status != NFS_OK) {
                                /* Free the stateid unless the server
@@ -4764,7 +4910,7 @@ static int nfs41_check_expired_locks(struct nfs4_state *state)
                                if (status != -NFS4ERR_BAD_STATEID)
                                        nfs41_free_stateid(server,
                                                        &lsp->ls_stateid);
-                               lsp->ls_flags &= ~NFS_LOCK_INITIALIZED;
+                               clear_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags);
                                ret = status;
                        }
                }
@@ -5267,10 +5413,8 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
        };
 
        nfs4_init_boot_verifier(clp, &verifier);
-       args.id_len = scnprintf(args.id, sizeof(args.id),
-                               "%s/%s",
-                               clp->cl_ipaddr,
-                               clp->cl_rpcclient->cl_nodename);
+       args.id_len = nfs4_init_uniform_client_string(clp, args.id,
+                                                       sizeof(args.id));
        dprintk("NFS call  exchange_id auth=%s, '%.*s'\n",
                clp->cl_rpcclient->cl_auth->au_ops->au_name,
                args.id_len, args.id);
@@ -5391,6 +5535,8 @@ int nfs4_destroy_clientid(struct nfs_client *clp)
                goto out;
        if (clp->cl_exchange_flags == 0)
                goto out;
+       if (clp->cl_preserve_clid)
+               goto out;
        cred = nfs4_get_exchange_id_cred(clp);
        ret = nfs4_proc_destroy_clientid(clp, cred);
        if (cred)
@@ -6196,26 +6342,44 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata)
 static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
 {
        struct nfs4_layoutget *lgp = calldata;
-       struct nfs_server *server = NFS_SERVER(lgp->args.inode);
+       struct inode *inode = lgp->args.inode;
+       struct nfs_server *server = NFS_SERVER(inode);
+       struct pnfs_layout_hdr *lo;
+       struct nfs4_state *state = NULL;
 
        dprintk("--> %s\n", __func__);
 
        if (!nfs4_sequence_done(task, &lgp->res.seq_res))
-               return;
+               goto out;
 
        switch (task->tk_status) {
        case 0:
-               break;
+               goto out;
        case -NFS4ERR_LAYOUTTRYLATER:
        case -NFS4ERR_RECALLCONFLICT:
                task->tk_status = -NFS4ERR_DELAY;
-               /* Fall through */
-       default:
-               if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
-                       rpc_restart_call_prepare(task);
-                       return;
+               break;
+       case -NFS4ERR_EXPIRED:
+       case -NFS4ERR_BAD_STATEID:
+               spin_lock(&inode->i_lock);
+               lo = NFS_I(inode)->layout;
+               if (!lo || list_empty(&lo->plh_segs)) {
+                       spin_unlock(&inode->i_lock);
+                       /* If the open stateid was bad, then recover it. */
+                       state = lgp->args.ctx->state;
+               } else {
+                       LIST_HEAD(head);
+
+                       pnfs_mark_matching_lsegs_invalid(lo, &head, NULL);
+                       spin_unlock(&inode->i_lock);
+                       /* Mark the bad layout state as invalid, then
+                        * retry using the open stateid. */
+                       pnfs_free_lseg_list(&head);
                }
        }
+       if (nfs4_async_handle_error(task, server, state) == -EAGAIN)
+               rpc_restart_call_prepare(task);
+out:
        dprintk("<-- %s\n", __func__);
 }
 
@@ -6282,7 +6446,8 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = {
        .rpc_release = nfs4_layoutget_release,
 };
 
-void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)
+struct pnfs_layout_segment *
+nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)
 {
        struct nfs_server *server = NFS_SERVER(lgp->args.inode);
        size_t max_pages = max_response_pages(server);
@@ -6299,6 +6464,7 @@ void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)
                .callback_data = lgp,
                .flags = RPC_TASK_ASYNC,
        };
+       struct pnfs_layout_segment *lseg = NULL;
        int status = 0;
 
        dprintk("--> %s\n", __func__);
@@ -6306,7 +6472,7 @@ void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)
        lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags);
        if (!lgp->args.layout.pages) {
                nfs4_layoutget_release(lgp);
-               return;
+               return ERR_PTR(-ENOMEM);
        }
        lgp->args.layout.pglen = max_pages * PAGE_SIZE;
 
@@ -6315,15 +6481,17 @@ void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)
        nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0);
        task = rpc_run_task(&task_setup_data);
        if (IS_ERR(task))
-               return;
+               return ERR_CAST(task);
        status = nfs4_wait_for_completion_rpc_task(task);
        if (status == 0)
                status = task->tk_status;
        if (status == 0)
-               status = pnfs_layout_process(lgp);
+               lseg = pnfs_layout_process(lgp);
        rpc_put_task(task);
        dprintk("<-- %s status=%d\n", __func__, status);
-       return;
+       if (status)
+               return ERR_PTR(status);
+       return lseg;
 }
 
 static void
@@ -6342,7 +6510,6 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
 {
        struct nfs4_layoutreturn *lrp = calldata;
        struct nfs_server *server;
-       struct pnfs_layout_hdr *lo = lrp->args.layout;
 
        dprintk("--> %s\n", __func__);
 
@@ -6354,20 +6521,21 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
                rpc_restart_call_prepare(task);
                return;
        }
-       spin_lock(&lo->plh_inode->i_lock);
-       if (task->tk_status == 0 && lrp->res.lrs_present)
-               pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
-       lo->plh_block_lgets--;
-       spin_unlock(&lo->plh_inode->i_lock);
        dprintk("<-- %s\n", __func__);
 }
 
 static void nfs4_layoutreturn_release(void *calldata)
 {
        struct nfs4_layoutreturn *lrp = calldata;
+       struct pnfs_layout_hdr *lo = lrp->args.layout;
 
        dprintk("--> %s\n", __func__);
-       put_layout_hdr(lrp->args.layout);
+       spin_lock(&lo->plh_inode->i_lock);
+       if (lrp->res.lrs_present)
+               pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
+       lo->plh_block_lgets--;
+       spin_unlock(&lo->plh_inode->i_lock);
+       pnfs_put_layout_hdr(lrp->args.layout);
        kfree(calldata);
        dprintk("<-- %s\n", __func__);
 }
@@ -6541,7 +6709,7 @@ static void nfs4_layoutcommit_release(void *calldata)
                list_del_init(&lseg->pls_lc_list);
                if (test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT,
                                       &lseg->pls_flags))
-                       put_lseg(lseg);
+                       pnfs_put_lseg(lseg);
        }
 
        clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock);
@@ -6800,6 +6968,7 @@ static const struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
        .recover_lock   = nfs4_lock_reclaim,
        .establish_clid = nfs4_init_clientid,
        .get_clid_cred  = nfs4_get_setclientid_cred,
+       .detect_trunking = nfs40_discover_server_trunking,
 };
 
 #if defined(CONFIG_NFS_V4_1)
@@ -6811,6 +6980,7 @@ static const struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = {
        .establish_clid = nfs41_init_clientid,
        .get_clid_cred  = nfs4_get_exchange_id_cred,
        .reclaim_complete = nfs41_proc_reclaim_complete,
+       .detect_trunking = nfs41_discover_server_trunking,
 };
 #endif /* CONFIG_NFS_V4_1 */
 
index 55148def5540f325d3a13bea73aa713960ffcd1e..c351e6b398388f7c1b4b09a6240d4ad6c2559295 100644 (file)
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
+#include <linux/sunrpc/clnt.h>
+
 #include "nfs4_fs.h"
 #include "callback.h"
 #include "delegation.h"
 #include "internal.h"
 #include "pnfs.h"
+#include "netns.h"
 
 #define NFSDBG_FACILITY                NFSDBG_STATE
 
 #define OPENOWNER_POOL_SIZE    8
 
 const nfs4_stateid zero_stateid;
-
+static DEFINE_MUTEX(nfs_clid_init_mutex);
 static LIST_HEAD(nfs4_clientid_list);
 
 int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
@@ -73,12 +76,13 @@ int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
        };
        unsigned short port;
        int status;
+       struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
 
        if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state))
                goto do_confirm;
-       port = nfs_callback_tcpport;
+       port = nn->nfs_callback_tcpport;
        if (clp->cl_addr.ss_family == AF_INET6)
-               port = nfs_callback_tcpport6;
+               port = nn->nfs_callback_tcpport6;
 
        status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid);
        if (status != 0)
@@ -96,6 +100,56 @@ out:
        return status;
 }
 
+/**
+ * nfs40_discover_server_trunking - Detect server IP address trunking (mv0)
+ *
+ * @clp: nfs_client under test
+ * @result: OUT: found nfs_client, or clp
+ * @cred: credential to use for trunking test
+ *
+ * Returns zero, a negative errno, or a negative NFS4ERR status.
+ * If zero is returned, an nfs_client pointer is planted in
+ * "result".
+ *
+ * Note: The returned client may not yet be marked ready.
+ */
+int nfs40_discover_server_trunking(struct nfs_client *clp,
+                                  struct nfs_client **result,
+                                  struct rpc_cred *cred)
+{
+       struct nfs4_setclientid_res clid = {
+               .clientid = clp->cl_clientid,
+               .confirm = clp->cl_confirm,
+       };
+       struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
+       unsigned short port;
+       int status;
+
+       port = nn->nfs_callback_tcpport;
+       if (clp->cl_addr.ss_family == AF_INET6)
+               port = nn->nfs_callback_tcpport6;
+
+       status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid);
+       if (status != 0)
+               goto out;
+       clp->cl_clientid = clid.clientid;
+       clp->cl_confirm = clid.confirm;
+
+       status = nfs40_walk_client_list(clp, result, cred);
+       switch (status) {
+       case -NFS4ERR_STALE_CLIENTID:
+               set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
+       case 0:
+               /* Sustain the lease, even if it's empty.  If the clientid4
+                * goes stale it's of no use for trunking discovery. */
+               nfs4_schedule_state_renewal(*result);
+               break;
+       }
+
+out:
+       return status;
+}
+
 struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp)
 {
        struct rpc_cred *cred = NULL;
@@ -275,6 +329,33 @@ out:
        return status;
 }
 
+/**
+ * nfs41_discover_server_trunking - Detect server IP address trunking (mv1)
+ *
+ * @clp: nfs_client under test
+ * @result: OUT: found nfs_client, or clp
+ * @cred: credential to use for trunking test
+ *
+ * Returns NFS4_OK, a negative errno, or a negative NFS4ERR status.
+ * If NFS4_OK is returned, an nfs_client pointer is planted in
+ * "result".
+ *
+ * Note: The returned client may not yet be marked ready.
+ */
+int nfs41_discover_server_trunking(struct nfs_client *clp,
+                                  struct nfs_client **result,
+                                  struct rpc_cred *cred)
+{
+       int status;
+
+       status = nfs4_proc_exchange_id(clp, cred);
+       if (status != NFS4_OK)
+               return status;
+       set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
+
+       return nfs41_walk_client_list(clp, result, cred);
+}
+
 struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp)
 {
        struct rpc_cred *cred;
@@ -729,11 +810,8 @@ static void __nfs4_close(struct nfs4_state *state,
        if (!call_close) {
                nfs4_put_open_state(state);
                nfs4_put_state_owner(owner);
-       } else {
-               bool roc = pnfs_roc(state->inode);
-
-               nfs4_do_close(state, gfp_mask, wait, roc);
-       }
+       } else
+               nfs4_do_close(state, gfp_mask, wait);
 }
 
 void nfs4_close_state(struct nfs4_state *state, fmode_t fmode)
@@ -865,7 +943,7 @@ void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
        if (list_empty(&state->lock_states))
                clear_bit(LK_STATE_IN_USE, &state->flags);
        spin_unlock(&state->state_lock);
-       if (lsp->ls_flags & NFS_LOCK_INITIALIZED) {
+       if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) {
                if (nfs4_release_lockowner(lsp) == 0)
                        return;
        }
@@ -911,17 +989,25 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
 }
 
 static bool nfs4_copy_lock_stateid(nfs4_stateid *dst, struct nfs4_state *state,
-               fl_owner_t fl_owner, pid_t fl_pid)
+               const struct nfs_lockowner *lockowner)
 {
        struct nfs4_lock_state *lsp;
+       fl_owner_t fl_owner;
+       pid_t fl_pid;
        bool ret = false;
 
+
+       if (lockowner == NULL)
+               goto out;
+
        if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
                goto out;
 
+       fl_owner = lockowner->l_owner;
+       fl_pid = lockowner->l_pid;
        spin_lock(&state->state_lock);
        lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE);
-       if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) {
+       if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) {
                nfs4_stateid_copy(dst, &lsp->ls_stateid);
                ret = true;
        }
@@ -946,11 +1032,11 @@ static void nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
  * requests.
  */
 void nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state,
-               fmode_t fmode, fl_owner_t fl_owner, pid_t fl_pid)
+               fmode_t fmode, const struct nfs_lockowner *lockowner)
 {
        if (nfs4_copy_delegation_stateid(dst, state->inode, fmode))
                return;
-       if (nfs4_copy_lock_stateid(dst, state, fl_owner, fl_pid))
+       if (nfs4_copy_lock_stateid(dst, state, lockowner))
                return;
        nfs4_copy_open_stateid(dst, state);
 }
@@ -1289,7 +1375,7 @@ restart:
                        if (status >= 0) {
                                spin_lock(&state->state_lock);
                                list_for_each_entry(lock, &state->lock_states, ls_locks) {
-                                       if (!(lock->ls_flags & NFS_LOCK_INITIALIZED))
+                                       if (!test_bit(NFS_LOCK_INITIALIZED, &lock->ls_flags))
                                                pr_warn_ratelimited("NFS: "
                                                        "%s: Lock reclaim "
                                                        "failed!\n", __func__);
@@ -1361,7 +1447,7 @@ static void nfs4_clear_open_state(struct nfs4_state *state)
        spin_lock(&state->state_lock);
        list_for_each_entry(lock, &state->lock_states, ls_locks) {
                lock->ls_seqid.flags = 0;
-               lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
+               clear_bit(NFS_LOCK_INITIALIZED, &lock->ls_flags);
        }
        spin_unlock(&state->state_lock);
 }
@@ -1595,8 +1681,8 @@ out:
        return nfs4_recovery_handle_error(clp, status);
 }
 
-/* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors
- * on EXCHANGE_ID for v4.1
+/* Set NFS4CLNT_LEASE_EXPIRED and reclaim reboot state for all v4.0 errors
+ * and for recoverable errors on EXCHANGE_ID for v4.1
  */
 static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status)
 {
@@ -1606,8 +1692,12 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status)
                        return -ESERVERFAULT;
                /* Lease confirmation error: retry after purging the lease */
                ssleep(1);
+               clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
+               break;
        case -NFS4ERR_STALE_CLIENTID:
                clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
+               nfs4_state_clear_reclaim_reboot(clp);
+               nfs4_state_start_reclaim_reboot(clp);
                break;
        case -NFS4ERR_CLID_INUSE:
                pr_err("NFS: Server %s reports our clientid is in use\n",
@@ -1698,6 +1788,109 @@ static int nfs4_purge_lease(struct nfs_client *clp)
        return 0;
 }
 
+/**
+ * nfs4_discover_server_trunking - Detect server IP address trunking
+ *
+ * @clp: nfs_client under test
+ * @result: OUT: found nfs_client, or clp
+ *
+ * Returns zero or a negative errno.  If zero is returned,
+ * an nfs_client pointer is planted in "result".
+ *
+ * Note: since we are invoked in process context, and
+ * not from inside the state manager, we cannot use
+ * nfs4_handle_reclaim_lease_error().
+ */
+int nfs4_discover_server_trunking(struct nfs_client *clp,
+                                 struct nfs_client **result)
+{
+       const struct nfs4_state_recovery_ops *ops =
+                               clp->cl_mvops->reboot_recovery_ops;
+       rpc_authflavor_t *flavors, flav, save;
+       struct rpc_clnt *clnt;
+       struct rpc_cred *cred;
+       int i, len, status;
+
+       dprintk("NFS: %s: testing '%s'\n", __func__, clp->cl_hostname);
+
+       len = NFS_MAX_SECFLAVORS;
+       flavors = kcalloc(len, sizeof(*flavors), GFP_KERNEL);
+       if (flavors == NULL) {
+               status = -ENOMEM;
+               goto out;
+       }
+       len = rpcauth_list_flavors(flavors, len);
+       if (len < 0) {
+               status = len;
+               goto out_free;
+       }
+       clnt = clp->cl_rpcclient;
+       save = clnt->cl_auth->au_flavor;
+       i = 0;
+
+       mutex_lock(&nfs_clid_init_mutex);
+       status  = -ENOENT;
+again:
+       cred = ops->get_clid_cred(clp);
+       if (cred == NULL)
+               goto out_unlock;
+
+       status = ops->detect_trunking(clp, result, cred);
+       put_rpccred(cred);
+       switch (status) {
+       case 0:
+               break;
+
+       case -EACCES:
+               if (clp->cl_machine_cred == NULL)
+                       break;
+               /* Handle case where the user hasn't set up machine creds */
+               nfs4_clear_machine_cred(clp);
+       case -NFS4ERR_DELAY:
+       case -ETIMEDOUT:
+       case -EAGAIN:
+               ssleep(1);
+               dprintk("NFS: %s after status %d, retrying\n",
+                       __func__, status);
+               goto again;
+
+       case -NFS4ERR_CLID_INUSE:
+       case -NFS4ERR_WRONGSEC:
+               status = -EPERM;
+               if (i >= len)
+                       break;
+
+               flav = flavors[i++];
+               if (flav == save)
+                       flav = flavors[i++];
+               clnt = rpc_clone_client_set_auth(clnt, flav);
+               if (IS_ERR(clnt)) {
+                       status = PTR_ERR(clnt);
+                       break;
+               }
+               clp->cl_rpcclient = clnt;
+               goto again;
+
+       case -NFS4ERR_MINOR_VERS_MISMATCH:
+               status = -EPROTONOSUPPORT;
+               break;
+
+       case -EKEYEXPIRED:
+               nfs4_warn_keyexpired(clp->cl_hostname);
+       case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
+                                * in nfs4_exchange_id */
+               status = -EKEYEXPIRED;
+       }
+
+out_unlock:
+       mutex_unlock(&nfs_clid_init_mutex);
+out_free:
+       kfree(flavors);
+out:
+       dprintk("NFS: %s: status = %d\n", __func__, status);
+       return status;
+}
+
 #ifdef CONFIG_NFS_V4_1
 void nfs4_schedule_session_recovery(struct nfs4_session *session, int err)
 {
@@ -2008,6 +2201,7 @@ out_error:
        pr_warn_ratelimited("NFS: state manager%s%s failed on NFSv4 server %s"
                        " with error %d\n", section_sep, section,
                        clp->cl_hostname, -status);
+       ssleep(1);
        nfs4_end_drain_session(clp);
        nfs4_clear_state_manager_bit(clp);
 }
index 5729bc8aa75dea9ef18f4211f6c31cb7061a44e7..2628d921b7e3c2d0b668332fd9052e870083df09 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/nfs_idmap.h>
 #include <linux/nfs_fs.h>
 
+#include "nfs4_fs.h"
 #include "callback.h"
 
 static const int nfs_set_port_min = 0;
index 8dba6bd485578695fb791f8aa548bc8ac99b4391..40836ee5dc3a87849b9dc2fc1f1946f4acbe45b6 100644 (file)
@@ -447,12 +447,14 @@ static int nfs4_stat_to_errno(int);
                                encode_sequence_maxsz + \
                                encode_putfh_maxsz + \
                                encode_open_maxsz + \
+                               encode_access_maxsz + \
                                encode_getfh_maxsz + \
                                encode_getattr_maxsz)
 #define NFS4_dec_open_sz        (compound_decode_hdr_maxsz + \
                                decode_sequence_maxsz + \
                                decode_putfh_maxsz + \
                                decode_open_maxsz + \
+                               decode_access_maxsz + \
                                decode_getfh_maxsz + \
                                decode_getattr_maxsz)
 #define NFS4_enc_open_confirm_sz \
@@ -467,11 +469,13 @@ static int nfs4_stat_to_errno(int);
                                        encode_sequence_maxsz + \
                                        encode_putfh_maxsz + \
                                        encode_open_maxsz + \
+                                       encode_access_maxsz + \
                                        encode_getattr_maxsz)
 #define NFS4_dec_open_noattr_sz        (compound_decode_hdr_maxsz + \
                                        decode_sequence_maxsz + \
                                        decode_putfh_maxsz + \
                                        decode_open_maxsz + \
+                                       decode_access_maxsz + \
                                        decode_getattr_maxsz)
 #define NFS4_enc_open_downgrade_sz \
                                (compound_encode_hdr_maxsz + \
@@ -1509,8 +1513,12 @@ static void encode_open_stateid(struct xdr_stream *xdr,
        nfs4_stateid stateid;
 
        if (ctx->state != NULL) {
+               const struct nfs_lockowner *lockowner = NULL;
+
+               if (l_ctx != NULL)
+                       lockowner = &l_ctx->lockowner;
                nfs4_select_rw_stateid(&stateid, ctx->state,
-                               fmode, l_ctx->lockowner, l_ctx->pid);
+                               fmode, lockowner);
                if (zero_seqid)
                        stateid.seqid = 0;
                encode_nfs4_stateid(xdr, &stateid);
@@ -2216,6 +2224,8 @@ static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr,
        encode_putfh(xdr, args->fh, &hdr);
        encode_open(xdr, args, &hdr);
        encode_getfh(xdr, &hdr);
+       if (args->access)
+               encode_access(xdr, args->access, &hdr);
        encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
        encode_nops(&hdr);
 }
@@ -2252,7 +2262,9 @@ static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req,
        encode_sequence(xdr, &args->seq_args, &hdr);
        encode_putfh(xdr, args->fh, &hdr);
        encode_open(xdr, args, &hdr);
-       encode_getfattr(xdr, args->bitmask, &hdr);
+       if (args->access)
+               encode_access(xdr, args->access, &hdr);
+       encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
        encode_nops(&hdr);
 }
 
@@ -4095,7 +4107,7 @@ out_overflow:
        return -EIO;
 }
 
-static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access)
+static int decode_access(struct xdr_stream *xdr, u32 *supported, u32 *access)
 {
        __be32 *p;
        uint32_t supp, acc;
@@ -4109,8 +4121,8 @@ static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access)
                goto out_overflow;
        supp = be32_to_cpup(p++);
        acc = be32_to_cpup(p);
-       access->supported = supp;
-       access->access = acc;
+       *supported = supp;
+       *access = acc;
        return 0;
 out_overflow:
        print_overflow_msg(__func__, xdr);
@@ -5642,7 +5654,8 @@ static int decode_getdeviceinfo(struct xdr_stream *xdr,
         * and places the remaining xdr data in xdr_buf->tail
         */
        pdev->mincount = be32_to_cpup(p);
-       xdr_read_pages(xdr, pdev->mincount); /* include space for the length */
+       if (xdr_read_pages(xdr, pdev->mincount) != pdev->mincount)
+               goto out_overflow;
 
        /* Parse notification bitmap, verifying that it is zero. */
        p = xdr_inline_decode(xdr, 4);
@@ -5887,7 +5900,7 @@ static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
        status = decode_putfh(xdr);
        if (status != 0)
                goto out;
-       status = decode_access(xdr, res);
+       status = decode_access(xdr, &res->supported, &res->access);
        if (status != 0)
                goto out;
        decode_getfattr(xdr, res->fattr, res->server);
@@ -6228,6 +6241,8 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
        status = decode_getfh(xdr, &res->fh);
        if (status)
                goto out;
+       if (res->access_request)
+               decode_access(xdr, &res->access_supported, &res->access_result);
        decode_getfattr(xdr, res->f_attr, res->server);
 out:
        return status;
@@ -6276,6 +6291,8 @@ static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp,
        status = decode_open(xdr, res);
        if (status)
                goto out;
+       if (res->access_request)
+               decode_access(xdr, &res->access_supported, &res->access_result);
        decode_getfattr(xdr, res->f_attr, res->server);
 out:
        return status;
index ea6d111b03e9484c23d5ca3f7997f10d893a57ad..be731e6b7b9cc1781a0a1776f49f7e5aa8219a89 100644 (file)
@@ -41,6 +41,7 @@
 #include <scsi/osd_ore.h>
 
 #include "objlayout.h"
+#include "../internal.h"
 
 #define NFSDBG_FACILITY         NFSDBG_PNFS_LD
 
@@ -606,8 +607,14 @@ static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout,
 void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
        unsigned long stripe_end = 0;
+       u64 wb_size;
 
-       pnfs_generic_pg_init_write(pgio, req);
+       if (pgio->pg_dreq == NULL)
+               wb_size = i_size_read(pgio->pg_inode) - req_offset(req);
+       else
+               wb_size = nfs_dreq_bytes_left(pgio->pg_dreq);
+
+       pnfs_generic_pg_init_write(pgio, req, wb_size);
        if (unlikely(pgio->pg_lseg == NULL))
                return; /* Not pNFS */
 
index 311a79681e2b16311724e25921d922768c999026..e56e846e9d2d61ebef728826a9125bcab61c0597 100644 (file)
@@ -102,6 +102,7 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
                   unsigned int offset, unsigned int count)
 {
        struct nfs_page         *req;
+       struct nfs_lock_context *l_ctx;
 
        /* try to allocate the request struct */
        req = nfs_page_alloc();
@@ -109,11 +110,12 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
                return ERR_PTR(-ENOMEM);
 
        /* get lock context early so we can deal with alloc failures */
-       req->wb_lock_context = nfs_get_lock_context(ctx);
-       if (req->wb_lock_context == NULL) {
+       l_ctx = nfs_get_lock_context(ctx);
+       if (IS_ERR(l_ctx)) {
                nfs_page_free(req);
-               return ERR_PTR(-ENOMEM);
+               return ERR_CAST(l_ctx);
        }
+       req->wb_lock_context = l_ctx;
 
        /* Initialize the request struct. Initially, we assume a
         * long write-back delay. This will be adjusted in
@@ -290,7 +292,9 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev,
 {
        if (req->wb_context->cred != prev->wb_context->cred)
                return false;
-       if (req->wb_lock_context->lockowner != prev->wb_lock_context->lockowner)
+       if (req->wb_lock_context->lockowner.l_owner != prev->wb_lock_context->lockowner.l_owner)
+               return false;
+       if (req->wb_lock_context->lockowner.l_pid != prev->wb_lock_context->lockowner.l_pid)
                return false;
        if (req->wb_context->state != prev->wb_context->state)
                return false;
index 2e00feacd4bee642c59c965612068653f120756c..fe624c91bd006ef11f839f61cab54f833286edfa 100644 (file)
@@ -35,6 +35,7 @@
 #include "iostat.h"
 
 #define NFSDBG_FACILITY                NFSDBG_PNFS
+#define PNFS_LAYOUTGET_RETRY_TIMEOUT (120*HZ)
 
 /* Locking:
  *
@@ -190,7 +191,7 @@ EXPORT_SYMBOL_GPL(pnfs_unregister_layoutdriver);
 
 /* Need to hold i_lock if caller does not already hold reference */
 void
-get_layout_hdr(struct pnfs_layout_hdr *lo)
+pnfs_get_layout_hdr(struct pnfs_layout_hdr *lo)
 {
        atomic_inc(&lo->plh_refcount);
 }
@@ -199,43 +200,107 @@ static struct pnfs_layout_hdr *
 pnfs_alloc_layout_hdr(struct inode *ino, gfp_t gfp_flags)
 {
        struct pnfs_layoutdriver_type *ld = NFS_SERVER(ino)->pnfs_curr_ld;
-       return ld->alloc_layout_hdr ? ld->alloc_layout_hdr(ino, gfp_flags) :
-               kzalloc(sizeof(struct pnfs_layout_hdr), gfp_flags);
+       return ld->alloc_layout_hdr(ino, gfp_flags);
 }
 
 static void
 pnfs_free_layout_hdr(struct pnfs_layout_hdr *lo)
 {
-       struct pnfs_layoutdriver_type *ld = NFS_SERVER(lo->plh_inode)->pnfs_curr_ld;
+       struct nfs_server *server = NFS_SERVER(lo->plh_inode);
+       struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;
+
+       if (!list_empty(&lo->plh_layouts)) {
+               struct nfs_client *clp = server->nfs_client;
+
+               spin_lock(&clp->cl_lock);
+               list_del_init(&lo->plh_layouts);
+               spin_unlock(&clp->cl_lock);
+       }
        put_rpccred(lo->plh_lc_cred);
-       return ld->alloc_layout_hdr ? ld->free_layout_hdr(lo) : kfree(lo);
+       return ld->free_layout_hdr(lo);
 }
 
 static void
-destroy_layout_hdr(struct pnfs_layout_hdr *lo)
+pnfs_detach_layout_hdr(struct pnfs_layout_hdr *lo)
 {
+       struct nfs_inode *nfsi = NFS_I(lo->plh_inode);
        dprintk("%s: freeing layout cache %p\n", __func__, lo);
-       BUG_ON(!list_empty(&lo->plh_layouts));
-       NFS_I(lo->plh_inode)->layout = NULL;
-       pnfs_free_layout_hdr(lo);
+       nfsi->layout = NULL;
+       /* Reset MDS Threshold I/O counters */
+       nfsi->write_io = 0;
+       nfsi->read_io = 0;
+}
+
+void
+pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo)
+{
+       struct inode *inode = lo->plh_inode;
+
+       if (atomic_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) {
+               pnfs_detach_layout_hdr(lo);
+               spin_unlock(&inode->i_lock);
+               pnfs_free_layout_hdr(lo);
+       }
+}
+
+static int
+pnfs_iomode_to_fail_bit(u32 iomode)
+{
+       return iomode == IOMODE_RW ?
+               NFS_LAYOUT_RW_FAILED : NFS_LAYOUT_RO_FAILED;
 }
 
 static void
-put_layout_hdr_locked(struct pnfs_layout_hdr *lo)
+pnfs_layout_set_fail_bit(struct pnfs_layout_hdr *lo, int fail_bit)
 {
-       if (atomic_dec_and_test(&lo->plh_refcount))
-               destroy_layout_hdr(lo);
+       lo->plh_retry_timestamp = jiffies;
+       if (test_and_set_bit(fail_bit, &lo->plh_flags))
+               atomic_inc(&lo->plh_refcount);
 }
 
-void
-put_layout_hdr(struct pnfs_layout_hdr *lo)
+static void
+pnfs_layout_clear_fail_bit(struct pnfs_layout_hdr *lo, int fail_bit)
+{
+       if (test_and_clear_bit(fail_bit, &lo->plh_flags))
+               atomic_dec(&lo->plh_refcount);
+}
+
+static void
+pnfs_layout_io_set_failed(struct pnfs_layout_hdr *lo, u32 iomode)
 {
        struct inode *inode = lo->plh_inode;
+       struct pnfs_layout_range range = {
+               .iomode = iomode,
+               .offset = 0,
+               .length = NFS4_MAX_UINT64,
+       };
+       LIST_HEAD(head);
 
-       if (atomic_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) {
-               destroy_layout_hdr(lo);
-               spin_unlock(&inode->i_lock);
+       spin_lock(&inode->i_lock);
+       pnfs_layout_set_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode));
+       pnfs_mark_matching_lsegs_invalid(lo, &head, &range);
+       spin_unlock(&inode->i_lock);
+       pnfs_free_lseg_list(&head);
+       dprintk("%s Setting layout IOMODE_%s fail bit\n", __func__,
+                       iomode == IOMODE_RW ?  "RW" : "READ");
+}
+
+static bool
+pnfs_layout_io_test_failed(struct pnfs_layout_hdr *lo, u32 iomode)
+{
+       unsigned long start, end;
+       int fail_bit = pnfs_iomode_to_fail_bit(iomode);
+
+       if (test_bit(fail_bit, &lo->plh_flags) == 0)
+               return false;
+       end = jiffies;
+       start = end - PNFS_LAYOUTGET_RETRY_TIMEOUT;
+       if (!time_in_range(lo->plh_retry_timestamp, start, end)) {
+               /* It is time to retry the failed layoutgets */
+               pnfs_layout_clear_fail_bit(lo, fail_bit);
+               return false;
        }
+       return true;
 }
 
 static void
@@ -249,33 +314,32 @@ init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg)
        lseg->pls_layout = lo;
 }
 
-static void free_lseg(struct pnfs_layout_segment *lseg)
+static void pnfs_free_lseg(struct pnfs_layout_segment *lseg)
 {
        struct inode *ino = lseg->pls_layout->plh_inode;
 
        NFS_SERVER(ino)->pnfs_curr_ld->free_lseg(lseg);
-       /* Matched by get_layout_hdr in pnfs_insert_layout */
-       put_layout_hdr(NFS_I(ino)->layout);
 }
 
 static void
-put_lseg_common(struct pnfs_layout_segment *lseg)
+pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo,
+               struct pnfs_layout_segment *lseg)
 {
-       struct inode *inode = lseg->pls_layout->plh_inode;
+       struct inode *inode = lo->plh_inode;
 
        WARN_ON(test_bit(NFS_LSEG_VALID, &lseg->pls_flags));
        list_del_init(&lseg->pls_list);
-       if (list_empty(&lseg->pls_layout->plh_segs)) {
-               set_bit(NFS_LAYOUT_DESTROYED, &lseg->pls_layout->plh_flags);
-               /* Matched by initial refcount set in alloc_init_layout_hdr */
-               put_layout_hdr_locked(lseg->pls_layout);
-       }
+       /* Matched by pnfs_get_layout_hdr in pnfs_layout_insert_lseg */
+       atomic_dec(&lo->plh_refcount);
+       if (list_empty(&lo->plh_segs))
+               clear_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
        rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq);
 }
 
 void
-put_lseg(struct pnfs_layout_segment *lseg)
+pnfs_put_lseg(struct pnfs_layout_segment *lseg)
 {
+       struct pnfs_layout_hdr *lo;
        struct inode *inode;
 
        if (!lseg)
@@ -284,17 +348,17 @@ put_lseg(struct pnfs_layout_segment *lseg)
        dprintk("%s: lseg %p ref %d valid %d\n", __func__, lseg,
                atomic_read(&lseg->pls_refcount),
                test_bit(NFS_LSEG_VALID, &lseg->pls_flags));
-       inode = lseg->pls_layout->plh_inode;
+       lo = lseg->pls_layout;
+       inode = lo->plh_inode;
        if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) {
-               LIST_HEAD(free_me);
-
-               put_lseg_common(lseg);
-               list_add(&lseg->pls_list, &free_me);
+               pnfs_get_layout_hdr(lo);
+               pnfs_layout_remove_lseg(lo, lseg);
                spin_unlock(&inode->i_lock);
-               pnfs_free_lseg_list(&free_me);
+               pnfs_free_lseg(lseg);
+               pnfs_put_layout_hdr(lo);
        }
 }
-EXPORT_SYMBOL_GPL(put_lseg);
+EXPORT_SYMBOL_GPL(pnfs_put_lseg);
 
 static inline u64
 end_offset(u64 start, u64 len)
@@ -378,7 +442,7 @@ static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
                dprintk("%s: lseg %p ref %d\n", __func__, lseg,
                        atomic_read(&lseg->pls_refcount));
                if (atomic_dec_and_test(&lseg->pls_refcount)) {
-                       put_lseg_common(lseg);
+                       pnfs_layout_remove_lseg(lseg->pls_layout, lseg);
                        list_add(&lseg->pls_list, tmp_list);
                        rv = 1;
                }
@@ -390,7 +454,7 @@ static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
  * after call.
  */
 int
-mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
+pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
                            struct list_head *tmp_list,
                            struct pnfs_layout_range *recall_range)
 {
@@ -399,14 +463,8 @@ mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
 
        dprintk("%s:Begin lo %p\n", __func__, lo);
 
-       if (list_empty(&lo->plh_segs)) {
-               /* Reset MDS Threshold I/O counters */
-               NFS_I(lo->plh_inode)->write_io = 0;
-               NFS_I(lo->plh_inode)->read_io = 0;
-               if (!test_and_set_bit(NFS_LAYOUT_DESTROYED, &lo->plh_flags))
-                       put_layout_hdr_locked(lo);
+       if (list_empty(&lo->plh_segs))
                return 0;
-       }
        list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list)
                if (!recall_range ||
                    should_free_lseg(&lseg->pls_range, recall_range)) {
@@ -426,25 +484,13 @@ void
 pnfs_free_lseg_list(struct list_head *free_me)
 {
        struct pnfs_layout_segment *lseg, *tmp;
-       struct pnfs_layout_hdr *lo;
 
        if (list_empty(free_me))
                return;
 
-       lo = list_first_entry(free_me, struct pnfs_layout_segment,
-                             pls_list)->pls_layout;
-
-       if (test_bit(NFS_LAYOUT_DESTROYED, &lo->plh_flags)) {
-               struct nfs_client *clp;
-
-               clp = NFS_SERVER(lo->plh_inode)->nfs_client;
-               spin_lock(&clp->cl_lock);
-               list_del_init(&lo->plh_layouts);
-               spin_unlock(&clp->cl_lock);
-       }
        list_for_each_entry_safe(lseg, tmp, free_me, pls_list) {
                list_del(&lseg->pls_list);
-               free_lseg(lseg);
+               pnfs_free_lseg(lseg);
        }
 }
 
@@ -458,10 +504,15 @@ pnfs_destroy_layout(struct nfs_inode *nfsi)
        lo = nfsi->layout;
        if (lo) {
                lo->plh_block_lgets++; /* permanently block new LAYOUTGETs */
-               mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
-       }
-       spin_unlock(&nfsi->vfs_inode.i_lock);
-       pnfs_free_lseg_list(&tmp_list);
+               pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
+               pnfs_get_layout_hdr(lo);
+               pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RO_FAILED);
+               pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RW_FAILED);
+               spin_unlock(&nfsi->vfs_inode.i_lock);
+               pnfs_free_lseg_list(&tmp_list);
+               pnfs_put_layout_hdr(lo);
+       } else
+               spin_unlock(&nfsi->vfs_inode.i_lock);
 }
 EXPORT_SYMBOL_GPL(pnfs_destroy_layout);
 
@@ -498,46 +549,54 @@ pnfs_destroy_all_layouts(struct nfs_client *clp)
        }
 }
 
+/*
+ * Compare 2 layout stateid sequence ids, to see which is newer,
+ * taking into account wraparound issues.
+ */
+static bool pnfs_seqid_is_newer(u32 s1, u32 s2)
+{
+       return (s32)s1 - (s32)s2 > 0;
+}
+
 /* update lo->plh_stateid with new if is more recent */
 void
 pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new,
                        bool update_barrier)
 {
-       u32 oldseq, newseq;
+       u32 oldseq, newseq, new_barrier;
+       int empty = list_empty(&lo->plh_segs);
 
        oldseq = be32_to_cpu(lo->plh_stateid.seqid);
        newseq = be32_to_cpu(new->seqid);
-       if ((int)(newseq - oldseq) > 0) {
+       if (empty || pnfs_seqid_is_newer(newseq, oldseq)) {
                nfs4_stateid_copy(&lo->plh_stateid, new);
                if (update_barrier) {
-                       u32 new_barrier = be32_to_cpu(new->seqid);
-
-                       if ((int)(new_barrier - lo->plh_barrier))
-                               lo->plh_barrier = new_barrier;
+                       new_barrier = be32_to_cpu(new->seqid);
                } else {
                        /* Because of wraparound, we want to keep the barrier
-                        * "close" to the current seqids.  It needs to be
-                        * within 2**31 to count as "behind", so if it
-                        * gets too near that limit, give us a litle leeway
-                        * and bring it to within 2**30.
-                        * NOTE - and yes, this is all unsigned arithmetic.
+                        * "close" to the current seqids.
                         */
-                       if (unlikely((newseq - lo->plh_barrier) > (3 << 29)))
-                               lo->plh_barrier = newseq - (1 << 30);
+                       new_barrier = newseq - atomic_read(&lo->plh_outstanding);
                }
+               if (empty || pnfs_seqid_is_newer(new_barrier, lo->plh_barrier))
+                       lo->plh_barrier = new_barrier;
        }
 }
 
+static bool
+pnfs_layout_stateid_blocked(const struct pnfs_layout_hdr *lo,
+               const nfs4_stateid *stateid)
+{
+       u32 seqid = be32_to_cpu(stateid->seqid);
+
+       return !pnfs_seqid_is_newer(seqid, lo->plh_barrier);
+}
+
 /* lget is set to 1 if called from inside send_layoutget call chain */
 static bool
-pnfs_layoutgets_blocked(struct pnfs_layout_hdr *lo, nfs4_stateid *stateid,
-                       int lget)
+pnfs_layoutgets_blocked(const struct pnfs_layout_hdr *lo, int lget)
 {
-       if ((stateid) &&
-           (int)(lo->plh_barrier - be32_to_cpu(stateid->seqid)) >= 0)
-               return true;
        return lo->plh_block_lgets ||
-               test_bit(NFS_LAYOUT_DESTROYED, &lo->plh_flags) ||
                test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags) ||
                (list_empty(&lo->plh_segs) &&
                 (atomic_read(&lo->plh_outstanding) > lget));
@@ -551,7 +610,7 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
 
        dprintk("--> %s\n", __func__);
        spin_lock(&lo->plh_inode->i_lock);
-       if (pnfs_layoutgets_blocked(lo, NULL, 1)) {
+       if (pnfs_layoutgets_blocked(lo, 1)) {
                status = -EAGAIN;
        } else if (list_empty(&lo->plh_segs)) {
                int seq;
@@ -582,7 +641,7 @@ send_layoutget(struct pnfs_layout_hdr *lo,
        struct inode *ino = lo->plh_inode;
        struct nfs_server *server = NFS_SERVER(ino);
        struct nfs4_layoutget *lgp;
-       struct pnfs_layout_segment *lseg = NULL;
+       struct pnfs_layout_segment *lseg;
 
        dprintk("--> %s\n", __func__);
 
@@ -599,16 +658,22 @@ send_layoutget(struct pnfs_layout_hdr *lo,
        lgp->args.type = server->pnfs_curr_ld->id;
        lgp->args.inode = ino;
        lgp->args.ctx = get_nfs_open_context(ctx);
-       lgp->lsegpp = &lseg;
        lgp->gfp_flags = gfp_flags;
 
        /* Synchronously retrieve layout information from server and
         * store in lseg.
         */
-       nfs4_proc_layoutget(lgp, gfp_flags);
-       if (!lseg) {
-               /* remember that LAYOUTGET failed and suspend trying */
-               set_bit(lo_fail_bit(range->iomode), &lo->plh_flags);
+       lseg = nfs4_proc_layoutget(lgp, gfp_flags);
+       if (IS_ERR(lseg)) {
+               switch (PTR_ERR(lseg)) {
+               case -ENOMEM:
+               case -ERESTARTSYS:
+                       break;
+               default:
+                       /* remember that LAYOUTGET failed and suspend trying */
+                       pnfs_layout_io_set_failed(lo, range->iomode);
+               }
+               return NULL;
        }
 
        return lseg;
@@ -636,25 +701,24 @@ _pnfs_return_layout(struct inode *ino)
 
        spin_lock(&ino->i_lock);
        lo = nfsi->layout;
-       if (!lo || pnfs_test_layout_returned(lo)) {
+       if (!lo) {
                spin_unlock(&ino->i_lock);
                dprintk("NFS: %s no layout to return\n", __func__);
                goto out;
        }
        stateid = nfsi->layout->plh_stateid;
        /* Reference matched in nfs4_layoutreturn_release */
-       get_layout_hdr(lo);
+       pnfs_get_layout_hdr(lo);
        empty = list_empty(&lo->plh_segs);
-       mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
+       pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
        /* Don't send a LAYOUTRETURN if list was initially empty */
        if (empty) {
                spin_unlock(&ino->i_lock);
-               put_layout_hdr(lo);
+               pnfs_put_layout_hdr(lo);
                dprintk("NFS: %s no layout segments to return\n", __func__);
                goto out;
        }
        lo->plh_block_lgets++;
-       pnfs_mark_layout_returned(lo);
        spin_unlock(&ino->i_lock);
        pnfs_free_lseg_list(&tmp_list);
 
@@ -663,10 +727,10 @@ _pnfs_return_layout(struct inode *ino)
        lrp = kzalloc(sizeof(*lrp), GFP_KERNEL);
        if (unlikely(lrp == NULL)) {
                status = -ENOMEM;
-               set_bit(NFS_LAYOUT_RW_FAILED, &lo->plh_flags);
-               set_bit(NFS_LAYOUT_RO_FAILED, &lo->plh_flags);
-               pnfs_clear_layout_returned(lo);
-               put_layout_hdr(lo);
+               spin_lock(&ino->i_lock);
+               lo->plh_block_lgets--;
+               spin_unlock(&ino->i_lock);
+               pnfs_put_layout_hdr(lo);
                goto out;
        }
 
@@ -703,7 +767,7 @@ bool pnfs_roc(struct inode *ino)
        if (!found)
                goto out_nolayout;
        lo->plh_block_lgets++;
-       get_layout_hdr(lo); /* matched in pnfs_roc_release */
+       pnfs_get_layout_hdr(lo); /* matched in pnfs_roc_release */
        spin_unlock(&ino->i_lock);
        pnfs_free_lseg_list(&tmp_list);
        return true;
@@ -720,8 +784,12 @@ void pnfs_roc_release(struct inode *ino)
        spin_lock(&ino->i_lock);
        lo = NFS_I(ino)->layout;
        lo->plh_block_lgets--;
-       put_layout_hdr_locked(lo);
-       spin_unlock(&ino->i_lock);
+       if (atomic_dec_and_test(&lo->plh_refcount)) {
+               pnfs_detach_layout_hdr(lo);
+               spin_unlock(&ino->i_lock);
+               pnfs_free_layout_hdr(lo);
+       } else
+               spin_unlock(&ino->i_lock);
 }
 
 void pnfs_roc_set_barrier(struct inode *ino, u32 barrier)
@@ -730,32 +798,34 @@ void pnfs_roc_set_barrier(struct inode *ino, u32 barrier)
 
        spin_lock(&ino->i_lock);
        lo = NFS_I(ino)->layout;
-       if ((int)(barrier - lo->plh_barrier) > 0)
+       if (pnfs_seqid_is_newer(barrier, lo->plh_barrier))
                lo->plh_barrier = barrier;
        spin_unlock(&ino->i_lock);
 }
 
-bool pnfs_roc_drain(struct inode *ino, u32 *barrier)
+bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task)
 {
        struct nfs_inode *nfsi = NFS_I(ino);
+       struct pnfs_layout_hdr *lo;
        struct pnfs_layout_segment *lseg;
+       u32 current_seqid;
        bool found = false;
 
        spin_lock(&ino->i_lock);
        list_for_each_entry(lseg, &nfsi->layout->plh_segs, pls_list)
                if (test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) {
+                       rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL);
                        found = true;
-                       break;
+                       goto out;
                }
-       if (!found) {
-               struct pnfs_layout_hdr *lo = nfsi->layout;
-               u32 current_seqid = be32_to_cpu(lo->plh_stateid.seqid);
+       lo = nfsi->layout;
+       current_seqid = be32_to_cpu(lo->plh_stateid.seqid);
 
-               /* Since close does not return a layout stateid for use as
-                * a barrier, we choose the worst-case barrier.
-                */
-               *barrier = current_seqid + atomic_read(&lo->plh_outstanding);
-       }
+       /* Since close does not return a layout stateid for use as
+        * a barrier, we choose the worst-case barrier.
+        */
+       *barrier = current_seqid + atomic_read(&lo->plh_outstanding);
+out:
        spin_unlock(&ino->i_lock);
        return found;
 }
@@ -786,14 +856,13 @@ cmp_layout(struct pnfs_layout_range *l1,
 }
 
 static void
-pnfs_insert_layout(struct pnfs_layout_hdr *lo,
+pnfs_layout_insert_lseg(struct pnfs_layout_hdr *lo,
                   struct pnfs_layout_segment *lseg)
 {
        struct pnfs_layout_segment *lp;
 
        dprintk("%s:Begin\n", __func__);
 
-       assert_spin_locked(&lo->plh_inode->i_lock);
        list_for_each_entry(lp, &lo->plh_segs, pls_list) {
                if (cmp_layout(&lseg->pls_range, &lp->pls_range) > 0)
                        continue;
@@ -813,7 +882,7 @@ pnfs_insert_layout(struct pnfs_layout_hdr *lo,
                __func__, lseg, lseg->pls_range.iomode,
                lseg->pls_range.offset, lseg->pls_range.length);
 out:
-       get_layout_hdr(lo);
+       pnfs_get_layout_hdr(lo);
 
        dprintk("%s:Return\n", __func__);
 }
@@ -847,21 +916,19 @@ pnfs_find_alloc_layout(struct inode *ino,
 
        dprintk("%s Begin ino=%p layout=%p\n", __func__, ino, nfsi->layout);
 
-       assert_spin_locked(&ino->i_lock);
-       if (nfsi->layout) {
-               if (test_bit(NFS_LAYOUT_DESTROYED, &nfsi->layout->plh_flags))
-                       return NULL;
-               else
-                       return nfsi->layout;
-       }
+       if (nfsi->layout != NULL)
+               goto out_existing;
        spin_unlock(&ino->i_lock);
        new = alloc_init_layout_hdr(ino, ctx, gfp_flags);
        spin_lock(&ino->i_lock);
 
-       if (likely(nfsi->layout == NULL))       /* Won the race? */
+       if (likely(nfsi->layout == NULL)) {     /* Won the race? */
                nfsi->layout = new;
-       else
-               pnfs_free_layout_hdr(new);
+               return new;
+       }
+       pnfs_free_layout_hdr(new);
+out_existing:
+       pnfs_get_layout_hdr(nfsi->layout);
        return nfsi->layout;
 }
 
@@ -904,11 +971,10 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo,
 
        dprintk("%s:Begin\n", __func__);
 
-       assert_spin_locked(&lo->plh_inode->i_lock);
        list_for_each_entry(lseg, &lo->plh_segs, pls_list) {
                if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) &&
                    is_matching_lseg(&lseg->pls_range, range)) {
-                       ret = get_lseg(lseg);
+                       ret = pnfs_get_lseg(lseg);
                        break;
                }
                if (lseg->pls_range.offset > range->offset)
@@ -1013,7 +1079,6 @@ pnfs_update_layout(struct inode *ino,
                .length = count,
        };
        unsigned pg_offset;
-       struct nfs_inode *nfsi = NFS_I(ino);
        struct nfs_server *server = NFS_SERVER(ino);
        struct nfs_client *clp = server->nfs_client;
        struct pnfs_layout_hdr *lo;
@@ -1021,16 +1086,16 @@ pnfs_update_layout(struct inode *ino,
        bool first = false;
 
        if (!pnfs_enabled_sb(NFS_SERVER(ino)))
-               return NULL;
+               goto out;
 
        if (pnfs_within_mdsthreshold(ctx, ino, iomode))
-               return NULL;
+               goto out;
 
        spin_lock(&ino->i_lock);
        lo = pnfs_find_alloc_layout(ino, ctx, gfp_flags);
        if (lo == NULL) {
-               dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__);
-               goto out_unlock;
+               spin_unlock(&ino->i_lock);
+               goto out;
        }
 
        /* Do we even need to bother with this? */
@@ -1040,7 +1105,7 @@ pnfs_update_layout(struct inode *ino,
        }
 
        /* if LAYOUTGET already failed once we don't try again */
-       if (test_bit(lo_fail_bit(iomode), &nfsi->layout->plh_flags))
+       if (pnfs_layout_io_test_failed(lo, iomode))
                goto out_unlock;
 
        /* Check to see if the layout for the given range already exists */
@@ -1048,17 +1113,13 @@ pnfs_update_layout(struct inode *ino,
        if (lseg)
                goto out_unlock;
 
-       if (pnfs_layoutgets_blocked(lo, NULL, 0))
+       if (pnfs_layoutgets_blocked(lo, 0))
                goto out_unlock;
        atomic_inc(&lo->plh_outstanding);
 
-       get_layout_hdr(lo);
        if (list_empty(&lo->plh_segs))
                first = true;
 
-       /* Enable LAYOUTRETURNs */
-       pnfs_clear_layout_returned(lo);
-
        spin_unlock(&ino->i_lock);
        if (first) {
                /* The lo must be on the clp list if there is any
@@ -1079,24 +1140,26 @@ pnfs_update_layout(struct inode *ino,
                arg.length = PAGE_CACHE_ALIGN(arg.length);
 
        lseg = send_layoutget(lo, ctx, &arg, gfp_flags);
-       if (!lseg && first) {
-               spin_lock(&clp->cl_lock);
-               list_del_init(&lo->plh_layouts);
-               spin_unlock(&clp->cl_lock);
-       }
        atomic_dec(&lo->plh_outstanding);
-       put_layout_hdr(lo);
+out_put_layout_hdr:
+       pnfs_put_layout_hdr(lo);
 out:
-       dprintk("%s end, state 0x%lx lseg %p\n", __func__,
-               nfsi->layout ? nfsi->layout->plh_flags : -1, lseg);
+       dprintk("%s: inode %s/%llu pNFS layout segment %s for "
+                       "(%s, offset: %llu, length: %llu)\n",
+                       __func__, ino->i_sb->s_id,
+                       (unsigned long long)NFS_FILEID(ino),
+                       lseg == NULL ? "not found" : "found",
+                       iomode==IOMODE_RW ?  "read/write" : "read-only",
+                       (unsigned long long)pos,
+                       (unsigned long long)count);
        return lseg;
 out_unlock:
        spin_unlock(&ino->i_lock);
-       goto out;
+       goto out_put_layout_hdr;
 }
 EXPORT_SYMBOL_GPL(pnfs_update_layout);
 
-int
+struct pnfs_layout_segment *
 pnfs_layout_process(struct nfs4_layoutget *lgp)
 {
        struct pnfs_layout_hdr *lo = NFS_I(lgp->args.inode)->layout;
@@ -1123,25 +1186,29 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
                goto out_forget_reply;
        }
 
-       if (pnfs_layoutgets_blocked(lo, &res->stateid, 1)) {
+       if (pnfs_layoutgets_blocked(lo, 1) ||
+           pnfs_layout_stateid_blocked(lo, &res->stateid)) {
                dprintk("%s forget reply due to state\n", __func__);
                goto out_forget_reply;
        }
+
+       /* Done processing layoutget. Set the layout stateid */
+       pnfs_set_layout_stateid(lo, &res->stateid, false);
+
        init_lseg(lo, lseg);
        lseg->pls_range = res->range;
-       *lgp->lsegpp = get_lseg(lseg);
-       pnfs_insert_layout(lo, lseg);
+       pnfs_get_lseg(lseg);
+       pnfs_layout_insert_lseg(lo, lseg);
 
        if (res->return_on_close) {
                set_bit(NFS_LSEG_ROC, &lseg->pls_flags);
                set_bit(NFS_LAYOUT_ROC, &lo->plh_flags);
        }
 
-       /* Done processing layoutget. Set the layout stateid */
-       pnfs_set_layout_stateid(lo, &res->stateid, false);
        spin_unlock(&ino->i_lock);
+       return lseg;
 out:
-       return status;
+       return ERR_PTR(status);
 
 out_forget_reply:
        spin_unlock(&ino->i_lock);
@@ -1153,16 +1220,24 @@ out_forget_reply:
 void
 pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
+       u64 rd_size = req->wb_bytes;
+
        BUG_ON(pgio->pg_lseg != NULL);
 
        if (req->wb_offset != req->wb_pgbase) {
                nfs_pageio_reset_read_mds(pgio);
                return;
        }
+
+       if (pgio->pg_dreq == NULL)
+               rd_size = i_size_read(pgio->pg_inode) - req_offset(req);
+       else
+               rd_size = nfs_dreq_bytes_left(pgio->pg_dreq);
+
        pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                           req->wb_context,
                                           req_offset(req),
-                                          req->wb_bytes,
+                                          rd_size,
                                           IOMODE_READ,
                                           GFP_KERNEL);
        /* If no lseg, fall back to read through mds */
@@ -1173,7 +1248,8 @@ pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *r
 EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_read);
 
 void
-pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
+                          struct nfs_page *req, u64 wb_size)
 {
        BUG_ON(pgio->pg_lseg != NULL);
 
@@ -1181,10 +1257,11 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *
                nfs_pageio_reset_write_mds(pgio);
                return;
        }
+
        pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                           req->wb_context,
                                           req_offset(req),
-                                          req->wb_bytes,
+                                          wb_size,
                                           IOMODE_RW,
                                           GFP_NOFS);
        /* If no lseg, fall back to write through mds */
@@ -1362,12 +1439,12 @@ pnfs_do_multiple_writes(struct nfs_pageio_descriptor *desc, struct list_head *he
                if (trypnfs == PNFS_NOT_ATTEMPTED)
                        pnfs_write_through_mds(desc, data);
        }
-       put_lseg(lseg);
+       pnfs_put_lseg(lseg);
 }
 
 static void pnfs_writehdr_free(struct nfs_pgio_header *hdr)
 {
-       put_lseg(hdr->lseg);
+       pnfs_put_lseg(hdr->lseg);
        nfs_writehdr_free(hdr);
 }
 EXPORT_SYMBOL_GPL(pnfs_writehdr_free);
@@ -1382,17 +1459,17 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
        whdr = nfs_writehdr_alloc();
        if (!whdr) {
                desc->pg_completion_ops->error_cleanup(&desc->pg_list);
-               put_lseg(desc->pg_lseg);
+               pnfs_put_lseg(desc->pg_lseg);
                desc->pg_lseg = NULL;
                return -ENOMEM;
        }
        hdr = &whdr->header;
        nfs_pgheader_init(desc, hdr, pnfs_writehdr_free);
-       hdr->lseg = get_lseg(desc->pg_lseg);
+       hdr->lseg = pnfs_get_lseg(desc->pg_lseg);
        atomic_inc(&hdr->refcnt);
        ret = nfs_generic_flush(desc, hdr);
        if (ret != 0) {
-               put_lseg(desc->pg_lseg);
+               pnfs_put_lseg(desc->pg_lseg);
                desc->pg_lseg = NULL;
        } else
                pnfs_do_multiple_writes(desc, &hdr->rpc_list, desc->pg_ioflags);
@@ -1517,12 +1594,12 @@ pnfs_do_multiple_reads(struct nfs_pageio_descriptor *desc, struct list_head *hea
                if (trypnfs == PNFS_NOT_ATTEMPTED)
                        pnfs_read_through_mds(desc, data);
        }
-       put_lseg(lseg);
+       pnfs_put_lseg(lseg);
 }
 
 static void pnfs_readhdr_free(struct nfs_pgio_header *hdr)
 {
-       put_lseg(hdr->lseg);
+       pnfs_put_lseg(hdr->lseg);
        nfs_readhdr_free(hdr);
 }
 EXPORT_SYMBOL_GPL(pnfs_readhdr_free);
@@ -1538,17 +1615,17 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
        if (!rhdr) {
                desc->pg_completion_ops->error_cleanup(&desc->pg_list);
                ret = -ENOMEM;
-               put_lseg(desc->pg_lseg);
+               pnfs_put_lseg(desc->pg_lseg);
                desc->pg_lseg = NULL;
                return ret;
        }
        hdr = &rhdr->header;
        nfs_pgheader_init(desc, hdr, pnfs_readhdr_free);
-       hdr->lseg = get_lseg(desc->pg_lseg);
+       hdr->lseg = pnfs_get_lseg(desc->pg_lseg);
        atomic_inc(&hdr->refcnt);
        ret = nfs_generic_pagein(desc, hdr);
        if (ret != 0) {
-               put_lseg(desc->pg_lseg);
+               pnfs_put_lseg(desc->pg_lseg);
                desc->pg_lseg = NULL;
        } else
                pnfs_do_multiple_reads(desc, &hdr->rpc_list);
@@ -1574,13 +1651,7 @@ static void pnfs_list_write_lseg(struct inode *inode, struct list_head *listp)
 
 void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg)
 {
-       if (lseg->pls_range.iomode == IOMODE_RW) {
-               dprintk("%s Setting layout IOMODE_RW fail bit\n", __func__);
-               set_bit(lo_fail_bit(IOMODE_RW), &lseg->pls_layout->plh_flags);
-       } else {
-               dprintk("%s Setting layout IOMODE_READ fail bit\n", __func__);
-               set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags);
-       }
+       pnfs_layout_io_set_failed(lseg->pls_layout, lseg->pls_range.iomode);
 }
 EXPORT_SYMBOL_GPL(pnfs_set_lo_fail);
 
@@ -1601,7 +1672,7 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata)
        }
        if (!test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &hdr->lseg->pls_flags)) {
                /* references matched in nfs4_layoutcommit_release */
-               get_lseg(hdr->lseg);
+               pnfs_get_lseg(hdr->lseg);
        }
        if (end_pos > nfsi->layout->plh_lwb)
                nfsi->layout->plh_lwb = end_pos;
index 745aa1b39e7c3d1e543a1c0beae0113c99a23cac..2d722dba111181377e6f599adae06a8d341abe09 100644 (file)
@@ -62,9 +62,6 @@ enum {
        NFS_LAYOUT_RW_FAILED,           /* get rw layout failed stop trying */
        NFS_LAYOUT_BULK_RECALL,         /* bulk recall affecting layout */
        NFS_LAYOUT_ROC,                 /* some lseg had roc bit set */
-       NFS_LAYOUT_DESTROYED,           /* no new use of layout allowed */
-       NFS_LAYOUT_INVALID,             /* layout is being destroyed */
-       NFS_LAYOUT_RETURNED,            /* layout has already been returned */
 };
 
 enum layoutdriver_policy_flags {
@@ -140,6 +137,7 @@ struct pnfs_layout_hdr {
        atomic_t                plh_outstanding; /* number of RPCs out */
        unsigned long           plh_block_lgets; /* block LAYOUTGET if >0 */
        u32                     plh_barrier; /* ignore lower seqids */
+       unsigned long           plh_retry_timestamp;
        unsigned long           plh_flags;
        loff_t                  plh_lwb; /* last write byte for layoutcommit */
        struct rpc_cred         *plh_lc_cred; /* layoutcommit cred */
@@ -172,12 +170,12 @@ extern int nfs4_proc_getdevicelist(struct nfs_server *server,
                                   struct pnfs_devicelist *devlist);
 extern int nfs4_proc_getdeviceinfo(struct nfs_server *server,
                                   struct pnfs_device *dev);
-extern void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags);
+extern struct pnfs_layout_segment* nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags);
 extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp);
 
 /* pnfs.c */
-void get_layout_hdr(struct pnfs_layout_hdr *lo);
-void put_lseg(struct pnfs_layout_segment *lseg);
+void pnfs_get_layout_hdr(struct pnfs_layout_hdr *lo);
+void pnfs_put_lseg(struct pnfs_layout_segment *lseg);
 
 void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *,
                           const struct nfs_pgio_completion_ops *);
@@ -188,28 +186,29 @@ void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32);
 void unset_pnfs_layoutdriver(struct nfs_server *);
 void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *);
 int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc);
-void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *, struct nfs_page *);
+void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
+                               struct nfs_page *req, u64 wb_size);
 int pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc);
 bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req);
 void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg);
-int pnfs_layout_process(struct nfs4_layoutget *lgp);
+struct pnfs_layout_segment *pnfs_layout_process(struct nfs4_layoutget *lgp);
 void pnfs_free_lseg_list(struct list_head *tmp_list);
 void pnfs_destroy_layout(struct nfs_inode *);
 void pnfs_destroy_all_layouts(struct nfs_client *);
-void put_layout_hdr(struct pnfs_layout_hdr *lo);
+void pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo);
 void pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo,
                             const nfs4_stateid *new,
                             bool update_barrier);
 int pnfs_choose_layoutget_stateid(nfs4_stateid *dst,
                                  struct pnfs_layout_hdr *lo,
                                  struct nfs4_state *open_state);
-int mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
+int pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
                                struct list_head *tmp_list,
                                struct pnfs_layout_range *recall_range);
 bool pnfs_roc(struct inode *ino);
 void pnfs_roc_release(struct inode *ino);
 void pnfs_roc_set_barrier(struct inode *ino, u32 barrier);
-bool pnfs_roc_drain(struct inode *ino, u32 *barrier);
+bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task);
 void pnfs_set_layoutcommit(struct nfs_write_data *wdata);
 void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data);
 int pnfs_layoutcommit_inode(struct inode *inode, bool sync);
@@ -233,6 +232,7 @@ struct nfs4_threshold *pnfs_mdsthreshold_alloc(void);
 /* nfs4_deviceid_flags */
 enum {
        NFS_DEVICEID_INVALID = 0,       /* set when MDS clientid recalled */
+       NFS_DEVICEID_UNAVAILABLE,       /* device temporarily unavailable */
 };
 
 /* pnfs_dev.c */
@@ -242,6 +242,7 @@ struct nfs4_deviceid_node {
        const struct pnfs_layoutdriver_type *ld;
        const struct nfs_client         *nfs_client;
        unsigned long                   flags;
+       unsigned long                   timestamp_unavailable;
        struct nfs4_deviceid            deviceid;
        atomic_t                        ref;
 };
@@ -254,34 +255,12 @@ void nfs4_init_deviceid_node(struct nfs4_deviceid_node *,
                             const struct nfs4_deviceid *);
 struct nfs4_deviceid_node *nfs4_insert_deviceid_node(struct nfs4_deviceid_node *);
 bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *);
+void nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node);
+bool nfs4_test_deviceid_unavailable(struct nfs4_deviceid_node *node);
 void nfs4_deviceid_purge_client(const struct nfs_client *);
 
-static inline void
-pnfs_mark_layout_returned(struct pnfs_layout_hdr *lo)
-{
-       set_bit(NFS_LAYOUT_RETURNED, &lo->plh_flags);
-}
-
-static inline void
-pnfs_clear_layout_returned(struct pnfs_layout_hdr *lo)
-{
-       clear_bit(NFS_LAYOUT_RETURNED, &lo->plh_flags);
-}
-
-static inline bool
-pnfs_test_layout_returned(struct pnfs_layout_hdr *lo)
-{
-       return test_bit(NFS_LAYOUT_RETURNED, &lo->plh_flags);
-}
-
-static inline int lo_fail_bit(u32 iomode)
-{
-       return iomode == IOMODE_RW ?
-                        NFS_LAYOUT_RW_FAILED : NFS_LAYOUT_RO_FAILED;
-}
-
 static inline struct pnfs_layout_segment *
-get_lseg(struct pnfs_layout_segment *lseg)
+pnfs_get_lseg(struct pnfs_layout_segment *lseg)
 {
        if (lseg) {
                atomic_inc(&lseg->pls_refcount);
@@ -406,12 +385,12 @@ static inline void pnfs_destroy_layout(struct nfs_inode *nfsi)
 }
 
 static inline struct pnfs_layout_segment *
-get_lseg(struct pnfs_layout_segment *lseg)
+pnfs_get_lseg(struct pnfs_layout_segment *lseg)
 {
        return NULL;
 }
 
-static inline void put_lseg(struct pnfs_layout_segment *lseg)
+static inline void pnfs_put_lseg(struct pnfs_layout_segment *lseg)
 {
 }
 
@@ -443,7 +422,7 @@ pnfs_roc_set_barrier(struct inode *ino, u32 barrier)
 }
 
 static inline bool
-pnfs_roc_drain(struct inode *ino, u32 *barrier)
+pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task)
 {
        return false;
 }
index 73f701f1f4d3325e2c54efb68e14b1df40eb90e1..d35b62e83ea638e9736587bfaec61c612221f579 100644 (file)
@@ -40,6 +40,8 @@
 #define NFS4_DEVICE_ID_HASH_SIZE       (1 << NFS4_DEVICE_ID_HASH_BITS)
 #define NFS4_DEVICE_ID_HASH_MASK       (NFS4_DEVICE_ID_HASH_SIZE - 1)
 
+#define PNFS_DEVICE_RETRY_TIMEOUT (120*HZ)
+
 static struct hlist_head nfs4_deviceid_cache[NFS4_DEVICE_ID_HASH_SIZE];
 static DEFINE_SPINLOCK(nfs4_deviceid_lock);
 
@@ -218,6 +220,30 @@ nfs4_put_deviceid_node(struct nfs4_deviceid_node *d)
 }
 EXPORT_SYMBOL_GPL(nfs4_put_deviceid_node);
 
+void
+nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node)
+{
+       node->timestamp_unavailable = jiffies;
+       set_bit(NFS_DEVICEID_UNAVAILABLE, &node->flags);
+}
+EXPORT_SYMBOL_GPL(nfs4_mark_deviceid_unavailable);
+
+bool
+nfs4_test_deviceid_unavailable(struct nfs4_deviceid_node *node)
+{
+       if (test_bit(NFS_DEVICEID_UNAVAILABLE, &node->flags)) {
+               unsigned long start, end;
+
+               end = jiffies;
+               start = end - PNFS_DEVICE_RETRY_TIMEOUT;
+               if (time_in_range(node->timestamp_unavailable, start, end))
+                       return true;
+               clear_bit(NFS_DEVICEID_UNAVAILABLE, &node->flags);
+       }
+       return false;
+}
+EXPORT_SYMBOL_GPL(nfs4_test_deviceid_unavailable);
+
 static void
 _deviceid_purge_client(const struct nfs_client *clp, long hash)
 {
@@ -276,3 +302,4 @@ nfs4_deviceid_mark_client_invalid(struct nfs_client *clp)
        }
        rcu_read_unlock();
 }
+
index d2c7f5db0847656bb0f2a9d109b5ad9fc8af5cbc..e831bce497663e809e48bb7cc278f5ad6a74ba7b 100644 (file)
@@ -88,6 +88,7 @@ enum {
        Opt_sharecache, Opt_nosharecache,
        Opt_resvport, Opt_noresvport,
        Opt_fscache, Opt_nofscache,
+       Opt_migration, Opt_nomigration,
 
        /* Mount options that take integer arguments */
        Opt_port,
@@ -147,6 +148,8 @@ static const match_table_t nfs_mount_option_tokens = {
        { Opt_noresvport, "noresvport" },
        { Opt_fscache, "fsc" },
        { Opt_nofscache, "nofsc" },
+       { Opt_migration, "migration" },
+       { Opt_nomigration, "nomigration" },
 
        { Opt_port, "port=%s" },
        { Opt_rsize, "rsize=%s" },
@@ -676,6 +679,9 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
        if (nfss->options & NFS_OPTION_FSCACHE)
                seq_printf(m, ",fsc");
 
+       if (nfss->options & NFS_OPTION_MIGRATION)
+               seq_printf(m, ",migration");
+
        if (nfss->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG) {
                if (nfss->flags & NFS_MOUNT_LOOKUP_CACHE_NONE)
                        seq_printf(m, ",lookupcache=none");
@@ -1106,7 +1112,7 @@ static int nfs_get_option_ul(substring_t args[], unsigned long *option)
        string = match_strdup(args);
        if (string == NULL)
                return -ENOMEM;
-       rc = strict_strtoul(string, 10, option);
+       rc = kstrtoul(string, 10, option);
        kfree(string);
 
        return rc;
@@ -1243,6 +1249,12 @@ static int nfs_parse_mount_options(char *raw,
                        kfree(mnt->fscache_uniq);
                        mnt->fscache_uniq = NULL;
                        break;
+               case Opt_migration:
+                       mnt->options |= NFS_OPTION_MIGRATION;
+                       break;
+               case Opt_nomigration:
+                       mnt->options &= NFS_OPTION_MIGRATION;
+                       break;
 
                /*
                 * options that take numeric values
@@ -1535,6 +1547,10 @@ static int nfs_parse_mount_options(char *raw,
        if (mnt->minorversion && mnt->version != 4)
                goto out_minorversion_mismatch;
 
+       if (mnt->options & NFS_OPTION_MIGRATION &&
+           mnt->version != 4 && mnt->minorversion != 0)
+               goto out_migration_misuse;
+
        /*
         * verify that any proto=/mountproto= options match the address
         * families in the addr=/mountaddr= options.
@@ -1572,6 +1588,10 @@ out_minorversion_mismatch:
        printk(KERN_INFO "NFS: mount option vers=%u does not support "
                         "minorversion=%u\n", mnt->version, mnt->minorversion);
        return 0;
+out_migration_misuse:
+       printk(KERN_INFO
+               "NFS: 'migration' not supported for this NFS version\n");
+       return 0;
 out_nomem:
        printk(KERN_INFO "NFS: not enough memory to parse option\n");
        return 0;
@@ -2494,7 +2514,7 @@ EXPORT_SYMBOL_GPL(nfs_kill_super);
 /*
  * Clone an NFS2/3/4 server record on xdev traversal (FSID-change)
  */
-struct dentry *
+static struct dentry *
 nfs_xdev_mount(struct file_system_type *fs_type, int flags,
                const char *dev_name, void *raw_data)
 {
@@ -2642,6 +2662,7 @@ unsigned int nfs_idmap_cache_timeout = 600;
 bool nfs4_disable_idmapping = true;
 unsigned short max_session_slots = NFS4_DEF_SLOT_TABLE_SIZE;
 unsigned short send_implementation_id = 1;
+char nfs4_client_id_uniquifier[NFS4_CLIENT_ID_UNIQ_LEN] = "";
 
 EXPORT_SYMBOL_GPL(nfs_callback_set_tcpport);
 EXPORT_SYMBOL_GPL(nfs_callback_tcpport);
@@ -2649,6 +2670,7 @@ EXPORT_SYMBOL_GPL(nfs_idmap_cache_timeout);
 EXPORT_SYMBOL_GPL(nfs4_disable_idmapping);
 EXPORT_SYMBOL_GPL(max_session_slots);
 EXPORT_SYMBOL_GPL(send_implementation_id);
+EXPORT_SYMBOL_GPL(nfs4_client_id_uniquifier);
 
 #define NFS_CALLBACK_MAXPORTNR (65535U)
 
@@ -2659,7 +2681,7 @@ static int param_set_portnr(const char *val, const struct kernel_param *kp)
 
        if (!val)
                return -EINVAL;
-       ret = strict_strtoul(val, 0, &num);
+       ret = kstrtoul(val, 0, &num);
        if (ret == -EINVAL || num > NFS_CALLBACK_MAXPORTNR)
                return -EINVAL;
        *((unsigned int *)kp->arg) = num;
@@ -2674,6 +2696,8 @@ static struct kernel_param_ops param_ops_portnr = {
 module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644);
 module_param(nfs_idmap_cache_timeout, int, 0644);
 module_param(nfs4_disable_idmapping, bool, 0644);
+module_param_string(nfs4_unique_id, nfs4_client_id_uniquifier,
+                       NFS4_CLIENT_ID_UNIQ_LEN, 0600);
 MODULE_PARM_DESC(nfs4_disable_idmapping,
                "Turn off NFSv4 idmapping when using 'sec=sys'");
 module_param(max_session_slots, ushort, 0644);
@@ -2682,6 +2706,7 @@ MODULE_PARM_DESC(max_session_slots, "Maximum number of outstanding NFSv4.1 "
 module_param(send_implementation_id, ushort, 0644);
 MODULE_PARM_DESC(send_implementation_id,
                "Send implementation ID with NFSv4.1 exchange_id");
+MODULE_PARM_DESC(nfs4_unique_id, "nfs_client_id4 uniquifier string");
 MODULE_ALIAS("nfs4");
 
 #endif /* CONFIG_NFS_V4 */
index e3b55372726cb0d2a082c62ed86a35e8605c66b5..9347ab7c9574fa3b2468a54449d85d366aaf6b61 100644 (file)
@@ -846,6 +846,7 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page,
 int nfs_flush_incompatible(struct file *file, struct page *page)
 {
        struct nfs_open_context *ctx = nfs_file_open_context(file);
+       struct nfs_lock_context *l_ctx;
        struct nfs_page *req;
        int do_flush, status;
        /*
@@ -860,9 +861,12 @@ int nfs_flush_incompatible(struct file *file, struct page *page)
                req = nfs_page_find_request(page);
                if (req == NULL)
                        return 0;
-               do_flush = req->wb_page != page || req->wb_context != ctx ||
-                       req->wb_lock_context->lockowner != current->files ||
-                       req->wb_lock_context->pid != current->tgid;
+               l_ctx = req->wb_lock_context;
+               do_flush = req->wb_page != page || req->wb_context != ctx;
+               if (l_ctx) {
+                       do_flush |= l_ctx->lockowner.l_owner != current->files
+                               || l_ctx->lockowner.l_pid != current->tgid;
+               }
                nfs_release_request(req);
                if (!do_flush)
                        return 0;
@@ -1576,6 +1580,7 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
                /* We have a mismatch. Write the page again */
                dprintk(" mismatch\n");
                nfs_mark_request_dirty(req);
+               set_bit(NFS_CONTEXT_RESEND_WRITES, &req->wb_context->flags);
        next:
                nfs_unlock_and_release_request(req);
        }
index 6aa5590c3679135279d2731b2af79fd8804b44a2..b314888825d5e939e0a850bcd29553292a87af44 100644 (file)
@@ -218,8 +218,7 @@ static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p,
  * There must be an encoding function for void results so svc_process
  * will work properly.
  */
-int
-nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
+static int nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 {
        return xdr_ressize_check(rqstp, p);
 }
index 9095f3c21df9e93a7bba11160f06896877851c09..97d90d1c86081edf89259bfc1c745082660855fc 100644 (file)
@@ -247,7 +247,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
        /* Now create the file and set attributes */
        nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len,
                                attr, newfhp,
-                               argp->createmode, argp->verf, NULL, NULL);
+                               argp->createmode, (u32 *)argp->verf, NULL, NULL);
 
        RETURN_STATUS(nfserr);
 }
index 4c7bd35b187687915ab4826877dc62aecca707e3..bdf29c96e4cdbed8eff6d25bb28022ead1e0122e 100644 (file)
@@ -1028,7 +1028,6 @@ void nfsd4_cb_recall(struct nfs4_delegation *dp)
        cb->cb_msg.rpc_cred = callback_cred;
 
        cb->cb_ops = &nfsd4_cb_recall_ops;
-       dp->dl_retries = 1;
 
        INIT_LIST_HEAD(&cb->cb_per_client);
        cb->cb_done = true;
index fdc91a6fc9c4e3d50bea67386c463bd50d8c4c12..a1f10c0a62553d0642b02adc7a66bd7a60c0139c 100644 (file)
@@ -478,7 +478,7 @@ nfsd_idmap_init(struct net *net)
                goto destroy_idtoname_cache;
        nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net);
        if (IS_ERR(nn->nametoid_cache)) {
-               rv = PTR_ERR(nn->idtoname_cache);
+               rv = PTR_ERR(nn->nametoid_cache);
                goto unregister_idtoname_cache;
        }
        rv = cache_register_net(nn->nametoid_cache, net);
@@ -598,7 +598,7 @@ numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namel
        /* Just to make sure it's null-terminated: */
        memcpy(buf, name, namelen);
        buf[namelen] = '\0';
-       ret = kstrtouint(name, 10, id);
+       ret = kstrtouint(buf, 10, id);
        return ret == 0;
 }
 
index c9c1c0a254170ebc1de0bc70cdcdcce6c8ff5b6d..6c9a4b291dba2c7e44498a32dc46ab6973e922c9 100644 (file)
@@ -370,7 +370,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                        break;
                case NFS4_OPEN_CLAIM_PREVIOUS:
                        open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
-                       status = nfs4_check_open_reclaim(&open->op_clientid);
+                       status = nfs4_check_open_reclaim(&open->op_clientid, cstate->minorversion);
                        if (status)
                                goto out;
                case NFS4_OPEN_CLAIM_FH:
@@ -1054,8 +1054,8 @@ 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;
+       stateid_getter op_get_currentstateid;
+       stateid_setter op_set_currentstateid;
 };
 
 static struct nfsd4_operation nfsd4_ops[];
index 48a1bad373342b10b689927faf002cf444043b22..d0237f872cc4e1fe49060120d725f729783dc245 100644 (file)
@@ -758,7 +758,7 @@ static void nfsd4_put_drc_mem(int slotsize, int num)
        spin_unlock(&nfsd_drc_lock);
 }
 
-static struct nfsd4_session *alloc_session(int slotsize, int numslots)
+static struct nfsd4_session *__alloc_session(int slotsize, int numslots)
 {
        struct nfsd4_session *new;
        int mem, i;
@@ -852,35 +852,28 @@ static int nfsd4_register_conn(struct nfsd4_conn *conn)
        return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user);
 }
 
-static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses, u32 dir)
+static void nfsd4_init_conn(struct svc_rqst *rqstp, struct nfsd4_conn *conn, struct nfsd4_session *ses)
 {
-       struct nfsd4_conn *conn;
        int ret;
 
-       conn = alloc_conn(rqstp, dir);
-       if (!conn)
-               return nfserr_jukebox;
        nfsd4_hash_conn(conn, ses);
        ret = nfsd4_register_conn(conn);
        if (ret)
                /* oops; xprt is already down: */
                nfsd4_conn_lost(&conn->cn_xpt_user);
-       if (ses->se_client->cl_cb_state == NFSD4_CB_DOWN &&
-               dir & NFS4_CDFC4_BACK) {
+       if (conn->cn_flags & NFS4_CDFC4_BACK) {
                /* callback channel may be back up */
                nfsd4_probe_callback(ses->se_client);
        }
-       return nfs_ok;
 }
 
-static __be32 nfsd4_new_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_session *ses)
+static struct nfsd4_conn *alloc_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_create_session *cses)
 {
        u32 dir = NFS4_CDFC4_FORE;
 
-       if (ses->se_flags & SESSION4_BACK_CHAN)
+       if (cses->flags & SESSION4_BACK_CHAN)
                dir |= NFS4_CDFC4_BACK;
-
-       return nfsd4_new_conn(rqstp, ses, dir);
+       return alloc_conn(rqstp, dir);
 }
 
 /* must be called under client_lock */
@@ -903,20 +896,21 @@ static void nfsd4_del_conns(struct nfsd4_session *s)
        spin_unlock(&clp->cl_lock);
 }
 
+static void __free_session(struct nfsd4_session *ses)
+{
+       nfsd4_put_drc_mem(slot_bytes(&ses->se_fchannel), ses->se_fchannel.maxreqs);
+       free_session_slots(ses);
+       kfree(ses);
+}
+
 static void free_session(struct kref *kref)
 {
        struct nfsd4_session *ses;
-       int mem;
 
        lockdep_assert_held(&client_lock);
        ses = container_of(kref, struct nfsd4_session, se_ref);
        nfsd4_del_conns(ses);
-       spin_lock(&nfsd_drc_lock);
-       mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel);
-       nfsd_drc_mem_used -= mem;
-       spin_unlock(&nfsd_drc_lock);
-       free_session_slots(ses);
-       kfree(ses);
+       __free_session(ses);
 }
 
 void nfsd4_put_session(struct nfsd4_session *ses)
@@ -926,14 +920,10 @@ void nfsd4_put_session(struct nfsd4_session *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)
+static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan)
 {
        struct nfsd4_session *new;
-       struct nfsd4_channel_attrs *fchan = &cses->fore_channel;
        int numslots, slotsize;
-       __be32 status;
-       int idx;
-
        /*
         * Note decreasing slot size below client's request may
         * make it difficult for client to function correctly, whereas
@@ -946,12 +936,18 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n
        if (numslots < 1)
                return NULL;
 
-       new = alloc_session(slotsize, numslots);
+       new = __alloc_session(slotsize, numslots);
        if (!new) {
                nfsd4_put_drc_mem(slotsize, fchan->maxreqs);
                return NULL;
        }
        init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize);
+       return new;
+}
+
+static struct nfsd4_session *init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses)
+{
+       int idx;
 
        new->se_client = clp;
        gen_sessionid(new);
@@ -970,14 +966,6 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n
        spin_unlock(&clp->cl_lock);
        spin_unlock(&client_lock);
 
-       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) {
                struct sockaddr *sa = svc_addr(rqstp);
                /*
@@ -990,7 +978,6 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n
                rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa);
                clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
        }
-       nfsd4_probe_callback(clp);
        return new;
 }
 
@@ -1131,7 +1118,7 @@ unhash_client_locked(struct nfs4_client *clp)
 }
 
 static void
-expire_client(struct nfs4_client *clp)
+destroy_client(struct nfs4_client *clp)
 {
        struct nfs4_openowner *oo;
        struct nfs4_delegation *dp;
@@ -1165,6 +1152,12 @@ expire_client(struct nfs4_client *clp)
        spin_unlock(&client_lock);
 }
 
+static void expire_client(struct nfs4_client *clp)
+{
+       nfsd4_client_record_remove(clp);
+       destroy_client(clp);
+}
+
 static void copy_verf(struct nfs4_client *target, nfs4_verifier *source)
 {
        memcpy(target->cl_verifier.data, source->data,
@@ -1223,10 +1216,26 @@ static bool groups_equal(struct group_info *g1, struct group_info *g2)
        return true;
 }
 
+/*
+ * RFC 3530 language requires clid_inuse be returned when the
+ * "principal" associated with a requests differs from that previously
+ * used.  We use uid, gid's, and gss principal string as our best
+ * approximation.  We also don't want to allow non-gss use of a client
+ * established using gss: in theory cr_principal should catch that
+ * change, but in practice cr_principal can be null even in the gss case
+ * since gssd doesn't always pass down a principal string.
+ */
+static bool is_gss_cred(struct svc_cred *cr)
+{
+       /* Is cr_flavor one of the gss "pseudoflavors"?: */
+       return (cr->cr_flavor > RPC_AUTH_MAXFLAVOR);
+}
+
+
 static bool
 same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
 {
-       if ((cr1->cr_flavor != cr2->cr_flavor)
+       if ((is_gss_cred(cr1) != is_gss_cred(cr2))
                || (cr1->cr_uid != cr2->cr_uid)
                || (cr1->cr_gid != cr2->cr_gid)
                || !groups_equal(cr1->cr_group_info, cr2->cr_group_info))
@@ -1340,13 +1349,15 @@ move_to_confirmed(struct nfs4_client *clp)
 }
 
 static struct nfs4_client *
-find_confirmed_client(clientid_t *clid)
+find_confirmed_client(clientid_t *clid, bool sessions)
 {
        struct nfs4_client *clp;
        unsigned int idhashval = clientid_hashval(clid->cl_id);
 
        list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
                if (same_clid(&clp->cl_clientid, clid)) {
+                       if ((bool)clp->cl_minorversion != sessions)
+                               return NULL;
                        renew_client(clp);
                        return clp;
                }
@@ -1355,14 +1366,17 @@ find_confirmed_client(clientid_t *clid)
 }
 
 static struct nfs4_client *
-find_unconfirmed_client(clientid_t *clid)
+find_unconfirmed_client(clientid_t *clid, bool sessions)
 {
        struct nfs4_client *clp;
        unsigned int idhashval = clientid_hashval(clid->cl_id);
 
        list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
-               if (same_clid(&clp->cl_clientid, clid))
+               if (same_clid(&clp->cl_clientid, clid)) {
+                       if ((bool)clp->cl_minorversion != sessions)
+                               return NULL;
                        return clp;
+               }
        }
        return NULL;
 }
@@ -1651,6 +1665,7 @@ out_new:
                status = nfserr_jukebox;
                goto out;
        }
+       new->cl_minorversion = 1;
 
        gen_clid(new);
        add_to_unconfirmed(new, strhashval);
@@ -1743,67 +1758,71 @@ nfsd4_create_session(struct svc_rqst *rqstp,
        struct sockaddr *sa = svc_addr(rqstp);
        struct nfs4_client *conf, *unconf;
        struct nfsd4_session *new;
+       struct nfsd4_conn *conn;
        struct nfsd4_clid_slot *cs_slot = NULL;
-       bool confirm_me = false;
        __be32 status = 0;
 
        if (cr_ses->flags & ~SESSION4_FLAG_MASK_A)
                return nfserr_inval;
+       if (check_forechannel_attrs(cr_ses->fore_channel))
+               return nfserr_toosmall;
+       new = alloc_session(&cr_ses->fore_channel);
+       if (!new)
+               return nfserr_jukebox;
+       status = nfserr_jukebox;
+       conn = alloc_conn_from_crses(rqstp, cr_ses);
+       if (!conn)
+               goto out_free_session;
 
        nfs4_lock_state();
-       unconf = find_unconfirmed_client(&cr_ses->clientid);
-       conf = find_confirmed_client(&cr_ses->clientid);
+       unconf = find_unconfirmed_client(&cr_ses->clientid, true);
+       conf = find_confirmed_client(&cr_ses->clientid, true);
 
        if (conf) {
                cs_slot = &conf->cl_cs_slot;
                status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
                if (status == nfserr_replay_cache) {
                        status = nfsd4_replay_create_session(cr_ses, cs_slot);
-                       goto out;
+                       goto out_free_conn;
                } else if (cr_ses->seqid != cs_slot->sl_seqid + 1) {
                        status = nfserr_seq_misordered;
-                       goto out;
+                       goto out_free_conn;
                }
        } else if (unconf) {
+               unsigned int hash;
+               struct nfs4_client *old;
                if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) ||
                    !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) {
                        status = nfserr_clid_inuse;
-                       goto out;
+                       goto out_free_conn;
                }
                cs_slot = &unconf->cl_cs_slot;
                status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
                if (status) {
                        /* an unconfirmed replay returns misordered */
                        status = nfserr_seq_misordered;
-                       goto out;
+                       goto out_free_conn;
                }
-               confirm_me = true;
+               hash = clientstr_hashval(unconf->cl_recdir);
+               old = find_confirmed_client_by_str(unconf->cl_recdir, hash);
+               if (old)
+                       expire_client(old);
+               move_to_confirmed(unconf);
                conf = unconf;
        } else {
                status = nfserr_stale_clientid;
-               goto out;
+               goto out_free_conn;
        }
-
-       /*
-        * XXX: we should probably set this at creation time, and check
-        * for consistent minorversion use throughout:
-        */
-       conf->cl_minorversion = 1;
+       status = nfs_ok;
        /*
         * We do not support RDMA or persistent sessions
         */
        cr_ses->flags &= ~SESSION4_PERSIST;
        cr_ses->flags &= ~SESSION4_RDMA;
 
-       status = nfserr_toosmall;
-       if (check_forechannel_attrs(cr_ses->fore_channel))
-               goto out;
+       init_session(rqstp, new, conf, cr_ses);
+       nfsd4_init_conn(rqstp, conn, new);
 
-       status = nfserr_jukebox;
-       new = alloc_init_session(rqstp, conf, cr_ses);
-       if (!new)
-               goto out;
-       status = nfs_ok;
        memcpy(cr_ses->sessionid.data, new->se_sessionid.data,
               NFS4_MAX_SESSIONID_LEN);
        memcpy(&cr_ses->fore_channel, &new->se_fchannel,
@@ -1813,18 +1832,15 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 
        /* cache solo and embedded create sessions under the state lock */
        nfsd4_cache_create_session(cr_ses, cs_slot, status);
-       if (confirm_me) {
-               unsigned int hash = clientstr_hashval(unconf->cl_recdir);
-               struct nfs4_client *old =
-                       find_confirmed_client_by_str(conf->cl_recdir, hash);
-               if (old)
-                       expire_client(old);
-               move_to_confirmed(conf);
-       }
 out:
        nfs4_unlock_state();
        dprintk("%s returns %d\n", __func__, ntohl(status));
        return status;
+out_free_conn:
+       free_conn(conn);
+out_free_session:
+       __free_session(new);
+       goto out;
 }
 
 static bool nfsd4_last_compound_op(struct svc_rqst *rqstp)
@@ -1854,6 +1870,7 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
                     struct nfsd4_bind_conn_to_session *bcts)
 {
        __be32 status;
+       struct nfsd4_conn *conn;
 
        if (!nfsd4_last_compound_op(rqstp))
                return nfserr_not_only_op;
@@ -1870,9 +1887,13 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
                return nfserr_badsession;
 
        status = nfsd4_map_bcts_dir(&bcts->dir);
-       if (!status)
-               nfsd4_new_conn(rqstp, cstate->session, bcts->dir);
-       return status;
+       if (status)
+               return status;
+       conn = alloc_conn(rqstp, bcts->dir);
+       if (!conn)
+               return nfserr_jukebox;
+       nfsd4_init_conn(rqstp, conn, cstate->session);
+       return nfs_ok;
 }
 
 static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid)
@@ -2085,8 +2106,8 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
        __be32 status = 0;
 
        nfs4_lock_state();
-       unconf = find_unconfirmed_client(&dc->clientid);
-       conf = find_confirmed_client(&dc->clientid);
+       unconf = find_unconfirmed_client(&dc->clientid, true);
+       conf = find_confirmed_client(&dc->clientid, true);
 
        if (conf) {
                clp = conf;
@@ -2200,10 +2221,6 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                copy_clid(new, conf);
        else /* case 4 (new client) or cases 2, 3 (client reboot): */
                gen_clid(new);
-       /*
-        * XXX: we should probably set this at creation time, and check
-        * for consistent minorversion use throughout:
-        */
        new->cl_minorversion = 0;
        gen_callback(new, setclid, rqstp);
        add_to_unconfirmed(new, strhashval);
@@ -2232,8 +2249,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
                return nfserr_stale_clientid;
        nfs4_lock_state();
 
-       conf = find_confirmed_client(clid);
-       unconf = find_unconfirmed_client(clid);
+       conf = find_confirmed_client(clid, false);
+       unconf = find_unconfirmed_client(clid, false);
        /*
         * We try hard to give out unique clientid's, so if we get an
         * attempt to confirm the same clientid with a different cred,
@@ -2262,10 +2279,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
                unsigned int hash = clientstr_hashval(unconf->cl_recdir);
 
                conf = find_confirmed_client_by_str(unconf->cl_recdir, hash);
-               if (conf) {
-                       nfsd4_client_record_remove(conf);
+               if (conf)
                        expire_client(conf);
-               }
                move_to_confirmed(unconf);
                nfsd4_probe_callback(unconf);
        }
@@ -2447,16 +2462,20 @@ same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner,
 }
 
 static struct nfs4_openowner *
-find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open)
+find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, bool sessions)
 {
        struct nfs4_stateowner *so;
        struct nfs4_openowner *oo;
+       struct nfs4_client *clp;
 
        list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) {
                if (!so->so_is_open_owner)
                        continue;
                if (same_owner_str(so, &open->op_owner, &open->op_clientid)) {
                        oo = openowner(so);
+                       clp = oo->oo_owner.so_client;
+                       if ((bool)clp->cl_minorversion != sessions)
+                               return NULL;
                        renew_client(oo->oo_owner.so_client);
                        return oo;
                }
@@ -2600,10 +2619,10 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate,
                return nfserr_jukebox;
 
        strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner);
-       oo = find_openstateowner_str(strhashval, open);
+       oo = find_openstateowner_str(strhashval, open, cstate->minorversion);
        open->op_openowner = oo;
        if (!oo) {
-               clp = find_confirmed_client(clientid);
+               clp = find_confirmed_client(clientid, cstate->minorversion);
                if (clp == NULL)
                        return nfserr_expired;
                goto new_owner;
@@ -2705,11 +2724,6 @@ nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_ol_st
        return nfs_ok;
 }
 
-static void nfs4_free_stateid(struct nfs4_ol_stateid *s)
-{
-       kmem_cache_free(stateid_slab, s);
-}
-
 static inline int nfs4_access_to_access(u32 nfs4_access)
 {
        int flags = 0;
@@ -3087,7 +3101,7 @@ void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status)
        if (open->op_file)
                nfsd4_free_file(open->op_file);
        if (open->op_stp)
-               nfs4_free_stateid(open->op_stp);
+               free_generic_stateid(open->op_stp);
 }
 
 __be32
@@ -3104,7 +3118,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        status = nfserr_stale_clientid;
        if (STALE_CLIENTID(clid, nn))
                goto out;
-       clp = find_confirmed_client(clid);
+       clp = find_confirmed_client(clid, cstate->minorversion);
        status = nfserr_expired;
        if (clp == NULL) {
                /* We assume the client took too long to RENEW. */
@@ -3180,7 +3194,6 @@ 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_client_record_remove(clp);
                expire_client(clp);
        }
        spin_lock(&recall_lock);
@@ -3372,7 +3385,7 @@ static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
        return nfs_ok;
 }
 
-static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s)
+static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s, bool sessions)
 {
        struct nfs4_client *cl;
        struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
@@ -3381,7 +3394,7 @@ static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, s
                return nfserr_bad_stateid;
        if (STALE_STATEID(stateid, nn))
                return nfserr_stale_stateid;
-       cl = find_confirmed_client(&stateid->si_opaque.so_clid);
+       cl = find_confirmed_client(&stateid->si_opaque.so_clid, sessions);
        if (!cl)
                return nfserr_expired;
        *s = find_stateid_by_type(cl, stateid, typemask);
@@ -3414,7 +3427,7 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
        if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
                return check_special_stateids(net, current_fh, stateid, flags);
 
-       status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s);
+       status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s, cstate->minorversion);
        if (status)
                return status;
        status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate));
@@ -3564,7 +3577,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
                seqid, STATEID_VAL(stateid));
 
        *stpp = NULL;
-       status = nfsd4_lookup_stateid(stateid, typemask, &s);
+       status = nfsd4_lookup_stateid(stateid, typemask, &s, cstate->minorversion);
        if (status)
                return status;
        *stpp = openlockstateid(s);
@@ -3765,6 +3778,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
 
        nfsd4_close_open_stateid(stp);
+       release_last_closed_stateid(oo);
        oo->oo_last_closed_stid = stp;
 
        if (list_empty(&oo->oo_owner.so_stateids)) {
@@ -3801,7 +3815,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        inode = cstate->current_fh.fh_dentry->d_inode;
 
        nfs4_lock_state();
-       status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s);
+       status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s, cstate->minorversion);
        if (status)
                goto out;
        dp = delegstateid(s);
@@ -4045,8 +4059,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        struct nfs4_lockowner *lock_sop = NULL;
        struct nfs4_ol_stateid *lock_stp;
        struct file *filp = NULL;
-       struct file_lock file_lock;
-       struct file_lock conflock;
+       struct file_lock *file_lock = NULL;
+       struct file_lock *conflock = NULL;
        __be32 status = 0;
        bool new_state = false;
        int lkflg;
@@ -4116,21 +4130,28 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim)
                goto out;
 
-       locks_init_lock(&file_lock);
+       file_lock = locks_alloc_lock();
+       if (!file_lock) {
+               dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
+               status = nfserr_jukebox;
+               goto out;
+       }
+
+       locks_init_lock(file_lock);
        switch (lock->lk_type) {
                case NFS4_READ_LT:
                case NFS4_READW_LT:
                        filp = find_readable_file(lock_stp->st_file);
                        if (filp)
                                get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ);
-                       file_lock.fl_type = F_RDLCK;
+                       file_lock->fl_type = F_RDLCK;
                        break;
                case NFS4_WRITE_LT:
                case NFS4_WRITEW_LT:
                        filp = find_writeable_file(lock_stp->st_file);
                        if (filp)
                                get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE);
-                       file_lock.fl_type = F_WRLCK;
+                       file_lock->fl_type = F_WRLCK;
                        break;
                default:
                        status = nfserr_inval;
@@ -4140,22 +4161,23 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                status = nfserr_openmode;
                goto out;
        }
-       file_lock.fl_owner = (fl_owner_t)lock_sop;
-       file_lock.fl_pid = current->tgid;
-       file_lock.fl_file = filp;
-       file_lock.fl_flags = FL_POSIX;
-       file_lock.fl_lmops = &nfsd_posix_mng_ops;
-
-       file_lock.fl_start = lock->lk_offset;
-       file_lock.fl_end = last_byte_offset(lock->lk_offset, lock->lk_length);
-       nfs4_transform_lock_offset(&file_lock);
-
-       /*
-       * Try to lock the file in the VFS.
-       * Note: locks.c uses the BKL to protect the inode's lock list.
-       */
+       file_lock->fl_owner = (fl_owner_t)lock_sop;
+       file_lock->fl_pid = current->tgid;
+       file_lock->fl_file = filp;
+       file_lock->fl_flags = FL_POSIX;
+       file_lock->fl_lmops = &nfsd_posix_mng_ops;
+       file_lock->fl_start = lock->lk_offset;
+       file_lock->fl_end = last_byte_offset(lock->lk_offset, lock->lk_length);
+       nfs4_transform_lock_offset(file_lock);
+
+       conflock = locks_alloc_lock();
+       if (!conflock) {
+               dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
+               status = nfserr_jukebox;
+               goto out;
+       }
 
-       err = vfs_lock_file(filp, F_SETLK, &file_lock, &conflock);
+       err = vfs_lock_file(filp, F_SETLK, file_lock, conflock);
        switch (-err) {
        case 0: /* success! */
                update_stateid(&lock_stp->st_stid.sc_stateid);
@@ -4166,7 +4188,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        case (EAGAIN):          /* conflock holds conflicting lock */
                status = nfserr_denied;
                dprintk("NFSD: nfsd4_lock: conflicting lock found!\n");
-               nfs4_set_lock_denied(&conflock, &lock->lk_denied);
+               nfs4_set_lock_denied(conflock, &lock->lk_denied);
                break;
        case (EDEADLK):
                status = nfserr_deadlock;
@@ -4181,6 +4203,10 @@ out:
                release_lockowner(lock_sop);
        if (!cstate->replay_owner)
                nfs4_unlock_state();
+       if (file_lock)
+               locks_free_lock(file_lock);
+       if (conflock)
+               locks_free_lock(conflock);
        return status;
 }
 
@@ -4209,7 +4235,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
            struct nfsd4_lockt *lockt)
 {
        struct inode *inode;
-       struct file_lock file_lock;
+       struct file_lock *file_lock = NULL;
        struct nfs4_lockowner *lo;
        __be32 status;
        struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
@@ -4230,15 +4256,21 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                goto out;
 
        inode = cstate->current_fh.fh_dentry->d_inode;
-       locks_init_lock(&file_lock);
+       file_lock = locks_alloc_lock();
+       if (!file_lock) {
+               dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
+               status = nfserr_jukebox;
+               goto out;
+       }
+       locks_init_lock(file_lock);
        switch (lockt->lt_type) {
                case NFS4_READ_LT:
                case NFS4_READW_LT:
-                       file_lock.fl_type = F_RDLCK;
+                       file_lock->fl_type = F_RDLCK;
                break;
                case NFS4_WRITE_LT:
                case NFS4_WRITEW_LT:
-                       file_lock.fl_type = F_WRLCK;
+                       file_lock->fl_type = F_WRLCK;
                break;
                default:
                        dprintk("NFSD: nfs4_lockt: bad lock type!\n");
@@ -4248,25 +4280,27 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner);
        if (lo)
-               file_lock.fl_owner = (fl_owner_t)lo;
-       file_lock.fl_pid = current->tgid;
-       file_lock.fl_flags = FL_POSIX;
+               file_lock->fl_owner = (fl_owner_t)lo;
+       file_lock->fl_pid = current->tgid;
+       file_lock->fl_flags = FL_POSIX;
 
-       file_lock.fl_start = lockt->lt_offset;
-       file_lock.fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length);
+       file_lock->fl_start = lockt->lt_offset;
+       file_lock->fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length);
 
-       nfs4_transform_lock_offset(&file_lock);
+       nfs4_transform_lock_offset(file_lock);
 
-       status = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock);
+       status = nfsd_test_lock(rqstp, &cstate->current_fh, file_lock);
        if (status)
                goto out;
 
-       if (file_lock.fl_type != F_UNLCK) {
+       if (file_lock->fl_type != F_UNLCK) {
                status = nfserr_denied;
-               nfs4_set_lock_denied(&file_lock, &lockt->lt_denied);
+               nfs4_set_lock_denied(file_lock, &lockt->lt_denied);
        }
 out:
        nfs4_unlock_state();
+       if (file_lock)
+               locks_free_lock(file_lock);
        return status;
 }
 
@@ -4276,7 +4310,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 {
        struct nfs4_ol_stateid *stp;
        struct file *filp = NULL;
-       struct file_lock file_lock;
+       struct file_lock *file_lock = NULL;
        __be32 status;
        int err;
                                                        
@@ -4298,23 +4332,29 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                status = nfserr_lock_range;
                goto out;
        }
-       BUG_ON(!filp);
-       locks_init_lock(&file_lock);
-       file_lock.fl_type = F_UNLCK;
-       file_lock.fl_owner = (fl_owner_t)lockowner(stp->st_stateowner);
-       file_lock.fl_pid = current->tgid;
-       file_lock.fl_file = filp;
-       file_lock.fl_flags = FL_POSIX; 
-       file_lock.fl_lmops = &nfsd_posix_mng_ops;
-       file_lock.fl_start = locku->lu_offset;
-
-       file_lock.fl_end = last_byte_offset(locku->lu_offset, locku->lu_length);
-       nfs4_transform_lock_offset(&file_lock);
+       file_lock = locks_alloc_lock();
+       if (!file_lock) {
+               dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
+               status = nfserr_jukebox;
+               goto out;
+       }
+       locks_init_lock(file_lock);
+       file_lock->fl_type = F_UNLCK;
+       file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner);
+       file_lock->fl_pid = current->tgid;
+       file_lock->fl_file = filp;
+       file_lock->fl_flags = FL_POSIX;
+       file_lock->fl_lmops = &nfsd_posix_mng_ops;
+       file_lock->fl_start = locku->lu_offset;
+
+       file_lock->fl_end = last_byte_offset(locku->lu_offset,
+                                               locku->lu_length);
+       nfs4_transform_lock_offset(file_lock);
 
        /*
        *  Try to unlock the file in the VFS.
        */
-       err = vfs_lock_file(filp, F_SETLK, &file_lock, NULL);
+       err = vfs_lock_file(filp, F_SETLK, file_lock, NULL);
        if (err) {
                dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n");
                goto out_nfserr;
@@ -4328,6 +4368,8 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 out:
        if (!cstate->replay_owner)
                nfs4_unlock_state();
+       if (file_lock)
+               locks_free_lock(file_lock);
        return status;
 
 out_nfserr:
@@ -4501,12 +4543,12 @@ nfsd4_find_reclaim_client(struct nfs4_client *clp)
 * Called from OPEN. Look for clientid in reclaim list.
 */
 __be32
-nfs4_check_open_reclaim(clientid_t *clid)
+nfs4_check_open_reclaim(clientid_t *clid, bool sessions)
 {
        struct nfs4_client *clp;
 
        /* find clientid in conf_id_hashtbl */
-       clp = find_confirmed_client(clid);
+       clp = find_confirmed_client(clid, sessions);
        if (clp == NULL)
                return nfserr_reclaim_bad;
 
@@ -4522,7 +4564,6 @@ void nfsd_forget_clients(u64 num)
 
        nfs4_lock_state();
        list_for_each_entry_safe(clp, next, &client_lru, cl_lru) {
-               nfsd4_client_record_remove(clp);
                expire_client(clp);
                if (++count == num)
                        break;
@@ -4582,7 +4623,7 @@ void nfsd_forget_openowners(u64 num)
        printk(KERN_INFO "NFSD: Forgot %d open owners", count);
 }
 
-int nfsd_process_n_delegations(u64 num, struct list_head *list)
+static int nfsd_process_n_delegations(u64 num, struct list_head *list)
 {
        int i, count = 0;
        struct nfs4_file *fp, *fnext;
@@ -4747,11 +4788,11 @@ __nfs4_state_shutdown(void)
        for (i = 0; i < CLIENT_HASH_SIZE; i++) {
                while (!list_empty(&conf_id_hashtbl[i])) {
                        clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
-                       expire_client(clp);
+                       destroy_client(clp);
                }
                while (!list_empty(&unconf_str_hashtbl[i])) {
                        clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash);
-                       expire_client(clp);
+                       destroy_client(clp);
                }
        }
        INIT_LIST_HEAD(&reaplist);
index 6322df36031f34c62f273f2d36630a472e991416..fd548d1550882a78abb7cbe3e632bff6021f6030 100644 (file)
@@ -2659,7 +2659,7 @@ static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp,
                RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8);
                WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN);
                WRITE32(bcts->dir);
-               /* XXX: ? */
+               /* Sorry, we do not yet support RDMA over 4.1: */
                WRITE32(0);
                ADJUST_ARGS();
        }
index fa49cff5ee651b9aa0b16f9cb43804f616aedc4e..dab350dfc376e48435817b2b136129bfb92de799 100644 (file)
@@ -406,7 +406,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
                        return rv;
                if (newthreads < 0)
                        return -EINVAL;
-               rv = nfsd_svc(NFS_PORT, newthreads);
+               rv = nfsd_svc(newthreads);
                if (rv < 0)
                        return rv;
        } else
@@ -682,25 +682,6 @@ static ssize_t __write_ports_addfd(char *buf)
        return err;
 }
 
-/*
- * A '-' followed by the 'name' of a socket means we close the socket.
- */
-static ssize_t __write_ports_delfd(char *buf)
-{
-       char *toclose;
-       int len = 0;
-
-       toclose = kstrdup(buf + 1, GFP_KERNEL);
-       if (toclose == NULL)
-               return -ENOMEM;
-
-       if (nfsd_serv != NULL)
-               len = svc_sock_names(nfsd_serv, buf,
-                                       SIMPLE_TRANSACTION_LIMIT, toclose);
-       kfree(toclose);
-       return len;
-}
-
 /*
  * A transport listener is added by writing it's transport name and
  * a port number.
@@ -712,7 +693,7 @@ static ssize_t __write_ports_addxprt(char *buf)
        int port, err;
        struct net *net = &init_net;
 
-       if (sscanf(buf, "%15s %4u", transport, &port) != 2)
+       if (sscanf(buf, "%15s %5u", transport, &port) != 2)
                return -EINVAL;
 
        if (port < 1 || port > USHRT_MAX)
@@ -746,31 +727,6 @@ out_err:
        return err;
 }
 
-/*
- * A transport listener is removed by writing a "-", it's transport
- * name, and it's port number.
- */
-static ssize_t __write_ports_delxprt(char *buf)
-{
-       struct svc_xprt *xprt;
-       char transport[16];
-       int port;
-
-       if (sscanf(&buf[1], "%15s %4u", transport, &port) != 2)
-               return -EINVAL;
-
-       if (port < 1 || port > USHRT_MAX || nfsd_serv == NULL)
-               return -EINVAL;
-
-       xprt = svc_find_xprt(nfsd_serv, transport, &init_net, AF_UNSPEC, port);
-       if (xprt == NULL)
-               return -ENOTCONN;
-
-       svc_close_xprt(xprt);
-       svc_xprt_put(xprt);
-       return 0;
-}
-
 static ssize_t __write_ports(struct file *file, char *buf, size_t size)
 {
        if (size == 0)
@@ -779,15 +735,9 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
        if (isdigit(buf[0]))
                return __write_ports_addfd(buf);
 
-       if (buf[0] == '-' && isdigit(buf[1]))
-               return __write_ports_delfd(buf);
-
        if (isalpha(buf[0]))
                return __write_ports_addxprt(buf);
 
-       if (buf[0] == '-' && isalpha(buf[1]))
-               return __write_ports_delxprt(buf);
-
        return -EINVAL;
 }
 
@@ -825,21 +775,6 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
  * OR
  *
  * Input:
- *                     buf:            C string containing a "-" followed
- *                                     by an integer value representing a
- *                                     previously passed in socket file
- *                                     descriptor
- *                     size:           non-zero length of C string in @buf
- * Output:
- *     On success:     NFS service no longer listens on that socket;
- *                     passed-in buffer filled with a '\n'-terminated C
- *                     string containing a unique name of the listener;
- *                     return code is the size in bytes of the string
- *     On error:       return code is a negative errno value
- *
- * OR
- *
- * Input:
  *                     buf:            C string containing a transport
  *                                     name and an unsigned integer value
  *                                     representing the port to listen on,
@@ -848,19 +783,6 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
  * Output:
  *     On success:     returns zero; NFS service is started
  *     On error:       return code is a negative errno value
- *
- * OR
- *
- * Input:
- *                     buf:            C string containing a "-" followed
- *                                     by a transport name and an unsigned
- *                                     integer value representing the port
- *                                     to listen on, separated by whitespace
- *                     size:           non-zero length of C string in @buf
- * Output:
- *     On success:     returns zero; NFS service no longer listens
- *                     on that transport
- *     On error:       return code is a negative errno value
  */
 static ssize_t write_ports(struct file *file, char *buf, size_t size)
 {
@@ -1008,8 +930,6 @@ static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
        return nfsd4_write_time(file, buf, size, &nfsd4_grace);
 }
 
-extern char *nfs4_recoverydir(void);
-
 static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
 {
        char *mesg = buf;
index 2244222368ab29cf4681d0d94012055bc5861f02..80d5ce40aadb02f024316c90f6460fef7ef406ec 100644 (file)
@@ -65,7 +65,7 @@ extern const struct seq_operations nfs_exports_op;
 /*
  * Function prototypes.
  */
-int            nfsd_svc(unsigned short port, int nrservs);
+int            nfsd_svc(int nrservs);
 int            nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp);
 
 int            nfsd_nrthreads(void);
@@ -124,6 +124,7 @@ int nfs4_state_start(void);
 void nfs4_state_shutdown(void);
 void nfs4_reset_lease(time_t leasetime);
 int nfs4_reset_recoverydir(char *recdir);
+char * nfs4_recoverydir(void);
 #else
 static inline void nfs4_state_init(void) { }
 static inline int nfsd4_init_slabs(void) { return 0; }
@@ -132,6 +133,7 @@ static inline int nfs4_state_start(void) { return 0; }
 static inline void nfs4_state_shutdown(void) { }
 static inline void nfs4_reset_lease(time_t leasetime) { }
 static inline int nfs4_reset_recoverydir(char *recdir) { return 0; }
+static inline char * nfs4_recoverydir(void) {return NULL; }
 #endif
 
 /*
index 240473cb708ff8a726d2b881d9d7ec2b42339653..2013aa001dab620e2e631872c57497b1cdef7afd 100644 (file)
@@ -183,18 +183,18 @@ int nfsd_nrthreads(void)
        return rv;
 }
 
-static int nfsd_init_socks(int port)
+static int nfsd_init_socks(void)
 {
        int error;
        if (!list_empty(&nfsd_serv->sv_permsocks))
                return 0;
 
-       error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, port,
+       error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, NFS_PORT,
                                        SVC_SOCK_DEFAULTS);
        if (error < 0)
                return error;
 
-       error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, port,
+       error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, NFS_PORT,
                                        SVC_SOCK_DEFAULTS);
        if (error < 0)
                return error;
@@ -204,7 +204,7 @@ static int nfsd_init_socks(int port)
 
 static bool nfsd_up = false;
 
-static int nfsd_startup(unsigned short port, int nrservs)
+static int nfsd_startup(int nrservs)
 {
        int ret;
 
@@ -218,7 +218,7 @@ static int nfsd_startup(unsigned short port, int nrservs)
        ret = nfsd_racache_init(2*nrservs);
        if (ret)
                return ret;
-       ret = nfsd_init_socks(port);
+       ret = nfsd_init_socks();
        if (ret)
                goto out_racache;
        ret = lockd_up(&init_net);
@@ -436,7 +436,7 @@ int nfsd_set_nrthreads(int n, int *nthreads)
  * this is the first time nrservs is nonzero.
  */
 int
-nfsd_svc(unsigned short port, int nrservs)
+nfsd_svc(int nrservs)
 {
        int     error;
        bool    nfsd_up_before;
@@ -458,7 +458,7 @@ nfsd_svc(unsigned short port, int nrservs)
 
        nfsd_up_before = nfsd_up;
 
-       error = nfsd_startup(port, nrservs);
+       error = nfsd_startup(nrservs);
        if (error)
                goto out_destroy;
        error = svc_set_num_threads(nfsd_serv, NULL, nrservs);
@@ -487,7 +487,7 @@ static int
 nfsd(void *vrqstp)
 {
        struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
-       int err, preverr = 0;
+       int err;
 
        /* Lock module and set up kernel thread */
        mutex_lock(&nfsd_mutex);
@@ -534,16 +534,6 @@ nfsd(void *vrqstp)
                        ;
                if (err == -EINTR)
                        break;
-               else if (err < 0) {
-                       if (err != preverr) {
-                               printk(KERN_WARNING "%s: unexpected error "
-                                       "from svc_recv (%d)\n", __func__, -err);
-                               preverr = err;
-                       }
-                       schedule_timeout_uninterruptible(HZ);
-                       continue;
-               }
-
                validate_process_creds();
                svc_process(rqstp);
                validate_process_creds();
index 22bd0a66c3566465ee77ca228b1979134b625ab2..e036894bce57edad09d6a57cf2a69dcb5efb0890 100644 (file)
@@ -373,11 +373,7 @@ static inline struct nfs4_lockowner * lockowner(struct nfs4_stateowner *so)
        return container_of(so, struct nfs4_lockowner, lo_owner);
 }
 
-/*
-*  nfs4_file: a file opened by some number of (open) nfs4_stateowners.
-*    o fi_perfile list is used to search for conflicting 
-*      share_acces, share_deny on the file.
-*/
+/* nfs4_file: a file opened by some number of (open) nfs4_stateowners. */
 struct nfs4_file {
        atomic_t                fi_ref;
        struct list_head        fi_hash;    /* hash by "struct inode *" */
@@ -459,7 +455,7 @@ 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 __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions);
 extern void nfs4_free_openowner(struct nfs4_openowner *);
 extern void nfs4_free_lockowner(struct nfs4_lockowner *);
 extern int set_callback_cred(void);
index 3f67b8e122515302709e606ef38881ba01aae581..c120b48ec305bed3b15aec207b1dd2dac57e952b 100644 (file)
@@ -1581,7 +1581,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
         */
 
        oldfs = get_fs(); set_fs(KERNEL_DS);
-       host_err = inode->i_op->readlink(path.dentry, buf, *lenp);
+       host_err = inode->i_op->readlink(path.dentry, (char __user *)buf, *lenp);
        set_fs(oldfs);
 
        if (host_err < 0)
index 44da0feeca2c94c980c2723bda63b1fcf74caedc..59071f55bf7fe97545cc691e5dc845a05cbe8f64 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -478,7 +478,7 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
 
        file = fget(fd);
        if (file) {
-               audit_inode(NULL, file->f_path.dentry);
+               audit_inode(NULL, file->f_path.dentry, 0);
                err = chmod_common(&file->f_path, mode);
                fput(file);
        }
@@ -588,7 +588,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
        error = mnt_want_write_file(f.file);
        if (error)
                goto out_fput;
-       audit_inode(NULL, f.file->f_path.dentry);
+       audit_inode(NULL, f.file->f_path.dentry, 0);
        error = chown_common(&f.file->f_path, user, group);
        mnt_drop_write_file(f.file);
 out_fput:
@@ -858,6 +858,24 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
        return lookup_flags;
 }
 
+/**
+ * file_open_name - open file and return file pointer
+ *
+ * @name:      struct filename containing path to open
+ * @flags:     open flags as per the open(2) second argument
+ * @mode:      mode for the new file if O_CREAT is set, else ignored
+ *
+ * This is the helper to open a file from kernelspace if you really
+ * have to.  But in generally you should not do this, so please move
+ * along, nothing to see here..
+ */
+struct file *file_open_name(struct filename *name, int flags, umode_t mode)
+{
+       struct open_flags op;
+       int lookup = build_open_flags(flags, mode, &op);
+       return do_filp_open(AT_FDCWD, name, &op, lookup);
+}
+
 /**
  * filp_open - open file and return file pointer
  *
@@ -871,9 +889,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
  */
 struct file *filp_open(const char *filename, int flags, umode_t mode)
 {
-       struct open_flags op;
-       int lookup = build_open_flags(flags, mode, &op);
-       return do_filp_open(AT_FDCWD, filename, &op, lookup);
+       struct filename name = {.name = filename};
+       return file_open_name(&name, flags, mode);
 }
 EXPORT_SYMBOL(filp_open);
 
@@ -895,7 +912,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
 {
        struct open_flags op;
        int lookup = build_open_flags(flags, mode, &op);
-       char *tmp = getname(filename);
+       struct filename *tmp = getname(filename);
        int fd = PTR_ERR(tmp);
 
        if (!IS_ERR(tmp)) {
index ef5c84be66f90d58c830be7f1634b76f1936537a..144a96732dd7d602df0d5f8a504e435cfdb07229 100644 (file)
@@ -2258,7 +2258,8 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
        pid_t tgid = task_tgid_nr_ns(current, ns);
        char *name = ERR_PTR(-ENOENT);
        if (tgid) {
-               name = __getname();
+               /* 11 for max length of signed int in decimal + NULL term */
+               name = kmalloc(12, GFP_KERNEL);
                if (!name)
                        name = ERR_PTR(-ENOMEM);
                else
@@ -2273,7 +2274,7 @@ static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
 {
        char *s = nd_get_link(nd);
        if (!IS_ERR(s))
-               __putname(s);
+               kfree(s);
 }
 
 static const struct inode_operations proc_self_inode_operations = {
index ff0135d6bc51a5d8ddbe1eb16f845a2b9d37c009..af1661f7a54f1700faa9a129ec76dad81e7e0961 100644 (file)
@@ -331,11 +331,11 @@ static struct super_block *quotactl_block(const char __user *special, int cmd)
 #ifdef CONFIG_BLOCK
        struct block_device *bdev;
        struct super_block *sb;
-       char *tmp = getname(special);
+       struct filename *tmp = getname(special);
 
        if (IS_ERR(tmp))
                return ERR_CAST(tmp);
-       bdev = lookup_bdev(tmp);
+       bdev = lookup_bdev(tmp->name);
        putname(tmp);
        if (IS_ERR(bdev))
                return ERR_CAST(bdev);
index 46485557cdc63b037994c05e82735605bbb4069a..f27f01a98aa2c9573c6cc61fe093c821ce6e107c 100644 (file)
@@ -1573,8 +1573,10 @@ struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
                        reiserfs_warning(sb, "reiserfs-13077",
                                "nfsd/reiserfs, fhtype=%d, len=%d - odd",
                                fh_type, fh_len);
-               fh_type = 5;
+               fh_type = fh_len;
        }
+       if (fh_len < 2)
+               return NULL;
 
        return reiserfs_get_dentry(sb, fid->raw[0], fid->raw[1],
                (fh_type == 3 || fh_type >= 5) ? fid->raw[2] : 0);
@@ -1583,6 +1585,8 @@ struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
 struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid,
                int fh_len, int fh_type)
 {
+       if (fh_type > fh_len)
+               fh_type = fh_len;
        if (fh_type < 4)
                return NULL;
 
index a3bc935069d9d5c643657793602ea42201263ed4..12f123712161c2cb10d20eae673e4b53de965d31 100644 (file)
@@ -186,14 +186,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags)
                spin_lock_init(&s->s_inode_lru_lock);
                INIT_LIST_HEAD(&s->s_mounts);
                init_rwsem(&s->s_umount);
-               mutex_init(&s->s_lock);
                lockdep_set_class(&s->s_umount, &type->s_umount_key);
-               /*
-                * The locking rules for s_lock are up to the
-                * filesystem. For example ext3fs has different
-                * lock ordering than usbfs:
-                */
-               lockdep_set_class(&s->s_lock, &type->s_lock_key);
                /*
                 * sget() can have s_umount recursion.
                 *
@@ -394,22 +387,6 @@ bool grab_super_passive(struct super_block *sb)
        return false;
 }
 
-/*
- * Superblock locking.  We really ought to get rid of these two.
- */
-void lock_super(struct super_block * sb)
-{
-       mutex_lock(&sb->s_lock);
-}
-
-void unlock_super(struct super_block * sb)
-{
-       mutex_unlock(&sb->s_lock);
-}
-
-EXPORT_SYMBOL(lock_super);
-EXPORT_SYMBOL(unlock_super);
-
 /**
  *     generic_shutdown_super  -       common helper for ->kill_sb()
  *     @sb: superblock to kill
index 9a6ad96acf2704ad32d6bc20d57abea7e2c2a26a..921c053fc052e4f53617c6fc79491dd9d086ab8c 100644 (file)
@@ -60,12 +60,12 @@ void sysv_free_block(struct super_block * sb, sysv_zone_t nr)
                return;
        }
 
-       lock_super(sb);
+       mutex_lock(&sbi->s_lock);
        count = fs16_to_cpu(sbi, *sbi->s_bcache_count);
 
        if (count > sbi->s_flc_size) {
                printk("sysv_free_block: flc_count > flc_size\n");
-               unlock_super(sb);
+               mutex_unlock(&sbi->s_lock);
                return;
        }
        /* If the free list head in super-block is full, it is copied
@@ -77,7 +77,7 @@ void sysv_free_block(struct super_block * sb, sysv_zone_t nr)
                bh = sb_getblk(sb, block);
                if (!bh) {
                        printk("sysv_free_block: getblk() failed\n");
-                       unlock_super(sb);
+                       mutex_unlock(&sbi->s_lock);
                        return;
                }
                memset(bh->b_data, 0, sb->s_blocksize);
@@ -93,7 +93,7 @@ void sysv_free_block(struct super_block * sb, sysv_zone_t nr)
        *sbi->s_bcache_count = cpu_to_fs16(sbi, count);
        fs32_add(sbi, sbi->s_free_blocks, 1);
        dirty_sb(sb);
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_lock);
 }
 
 sysv_zone_t sysv_new_block(struct super_block * sb)
@@ -104,7 +104,7 @@ sysv_zone_t sysv_new_block(struct super_block * sb)
        struct buffer_head * bh;
        unsigned count;
 
-       lock_super(sb);
+       mutex_lock(&sbi->s_lock);
        count = fs16_to_cpu(sbi, *sbi->s_bcache_count);
 
        if (count == 0) /* Applies only to Coherent FS */
@@ -147,11 +147,11 @@ sysv_zone_t sysv_new_block(struct super_block * sb)
        /* Now the free list head in the superblock is valid again. */
        fs32_add(sbi, sbi->s_free_blocks, -1);
        dirty_sb(sb);
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_lock);
        return nr;
 
 Enospc:
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_lock);
        return 0;
 }
 
@@ -173,7 +173,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
        if (sbi->s_type == FSTYPE_AFS)
                return 0;
 
-       lock_super(sb);
+       mutex_lock(&sbi->s_lock);
        sb_count = fs32_to_cpu(sbi, *sbi->s_free_blocks);
 
        if (0)
@@ -211,7 +211,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
        if (count != sb_count)
                goto Ecount;
 done:
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_lock);
        return count;
 
 Einval:
index 8233b02eccaebc1eb7b60f2db3b66fad3fe939e2..f9db4eb31db4d64aeef36acd351ca02cfe8dd66b 100644 (file)
@@ -118,7 +118,7 @@ void sysv_free_inode(struct inode * inode)
                       "%s\n", inode->i_sb->s_id);
                return;
        }
-       lock_super(sb);
+       mutex_lock(&sbi->s_lock);
        count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count);
        if (count < sbi->s_fic_size) {
                *sv_sb_fic_inode(sb,count++) = cpu_to_fs16(sbi, ino);
@@ -128,7 +128,7 @@ void sysv_free_inode(struct inode * inode)
        dirty_sb(sb);
        memset(raw_inode, 0, sizeof(struct sysv_inode));
        mark_buffer_dirty(bh);
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_lock);
        brelse(bh);
 }
 
@@ -147,13 +147,13 @@ struct inode * sysv_new_inode(const struct inode * dir, umode_t mode)
        if (!inode)
                return ERR_PTR(-ENOMEM);
 
-       lock_super(sb);
+       mutex_lock(&sbi->s_lock);
        count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count);
        if (count == 0 || (*sv_sb_fic_inode(sb,count-1) == 0)) {
                count = refill_free_cache(sb);
                if (count == 0) {
                        iput(inode);
-                       unlock_super(sb);
+                       mutex_unlock(&sbi->s_lock);
                        return ERR_PTR(-ENOSPC);
                }
        }
@@ -174,7 +174,7 @@ struct inode * sysv_new_inode(const struct inode * dir, umode_t mode)
        sysv_write_inode(inode, &wbc);  /* ensure inode not allocated again */
        mark_inode_dirty(inode);        /* cleared by sysv_write_inode() */
        /* That's it. */
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_lock);
        return inode;
 }
 
@@ -185,7 +185,7 @@ unsigned long sysv_count_free_inodes(struct super_block * sb)
        struct sysv_inode * raw_inode;
        int ino, count, sb_count;
 
-       lock_super(sb);
+       mutex_lock(&sbi->s_lock);
 
        sb_count = fs16_to_cpu(sbi, *sbi->s_sb_total_free_inodes);
 
@@ -213,7 +213,7 @@ unsigned long sysv_count_free_inodes(struct super_block * sb)
        if (count != sb_count)
                goto Einval;
 out:
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_lock);
        return count;
 
 Einval:
index d33e506c1eacabcebfd354f6ceedf52a3111a6d7..c327d4ee1235494e05ae1587b86ca357577b2292 100644 (file)
@@ -36,7 +36,7 @@ static int sysv_sync_fs(struct super_block *sb, int wait)
        struct sysv_sb_info *sbi = SYSV_SB(sb);
        unsigned long time = get_seconds(), old_time;
 
-       lock_super(sb);
+       mutex_lock(&sbi->s_lock);
 
        /*
         * If we are going to write out the super block,
@@ -51,7 +51,7 @@ static int sysv_sync_fs(struct super_block *sb, int wait)
                mark_buffer_dirty(sbi->s_bh2);
        }
 
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_lock);
 
        return 0;
 }
index 7491c33b6468738522b519f729d58f80de002859..a38e87bdd78dcb6fa112f954b30a93de9dc06420 100644 (file)
@@ -368,6 +368,7 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent)
 
        sbi->s_sb = sb;
        sbi->s_block_base = 0;
+       mutex_init(&sbi->s_lock);
        sb->s_fs_info = sbi;
 
        sb_set_blocksize(sb, BLOCK_SIZE);
index 0bc35fdc58e2981fc455fc043c43f00deb10a0d8..69d488986cce4923860c6d1f4c7ab325370fc5ce 100644 (file)
@@ -58,6 +58,7 @@ struct sysv_sb_info {
        u32            s_nzones;        /* same as s_sbd->s_fsize */
        u16            s_namelen;       /* max length of dir entry */
        int            s_forced_ro;
+       struct mutex s_lock;
 };
 
 /*
index 1b3e410bf334b206eea15615d52b1ab16656de88..a7ea492ae66072d34cb4daa4c99c51f3a5ea281c 100644 (file)
@@ -54,7 +54,7 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
        if (ufs_fragnum(fragment) + count > uspi->s_fpg)
                ufs_error (sb, "ufs_free_fragments", "internal error");
        
-       lock_super(sb);
+       mutex_lock(&UFS_SB(sb)->s_lock);
        
        cgno = ufs_dtog(uspi, fragment);
        bit = ufs_dtogd(uspi, fragment);
@@ -118,12 +118,12 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
                ubh_sync_block(UCPI_UBH(ucpi));
        ufs_mark_sb_dirty(sb);
        
-       unlock_super (sb);
+       mutex_unlock(&UFS_SB(sb)->s_lock);
        UFSD("EXIT\n");
        return;
 
 failed:
-       unlock_super (sb);
+       mutex_unlock(&UFS_SB(sb)->s_lock);
        UFSD("EXIT (FAILED)\n");
        return;
 }
@@ -155,7 +155,7 @@ void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count)
                goto failed;
        }
 
-       lock_super(sb);
+       mutex_lock(&UFS_SB(sb)->s_lock);
        
 do_more:
        overflow = 0;
@@ -215,12 +215,12 @@ do_more:
        }
 
        ufs_mark_sb_dirty(sb);
-       unlock_super (sb);
+       mutex_unlock(&UFS_SB(sb)->s_lock);
        UFSD("EXIT\n");
        return;
 
 failed_unlock:
-       unlock_super (sb);
+       mutex_unlock(&UFS_SB(sb)->s_lock);
 failed:
        UFSD("EXIT (FAILED)\n");
        return;
@@ -361,7 +361,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
        usb1 = ubh_get_usb_first(uspi);
        *err = -ENOSPC;
 
-       lock_super (sb);
+       mutex_lock(&UFS_SB(sb)->s_lock);
        tmp = ufs_data_ptr_to_cpu(sb, p);
 
        if (count + ufs_fragnum(fragment) > uspi->s_fpb) {
@@ -382,19 +382,19 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
                                  "fragment %llu, tmp %llu\n",
                                  (unsigned long long)fragment,
                                  (unsigned long long)tmp);
-                       unlock_super(sb);
+                       mutex_unlock(&UFS_SB(sb)->s_lock);
                        return INVBLOCK;
                }
                if (fragment < UFS_I(inode)->i_lastfrag) {
                        UFSD("EXIT (ALREADY ALLOCATED)\n");
-                       unlock_super (sb);
+                       mutex_unlock(&UFS_SB(sb)->s_lock);
                        return 0;
                }
        }
        else {
                if (tmp) {
                        UFSD("EXIT (ALREADY ALLOCATED)\n");
-                       unlock_super(sb);
+                       mutex_unlock(&UFS_SB(sb)->s_lock);
                        return 0;
                }
        }
@@ -403,7 +403,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
         * There is not enough space for user on the device
         */
        if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(uspi, UFS_MINFREE) <= 0) {
-               unlock_super (sb);
+               mutex_unlock(&UFS_SB(sb)->s_lock);
                UFSD("EXIT (FAILED)\n");
                return 0;
        }
@@ -428,7 +428,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
                        ufs_clear_frags(inode, result + oldcount,
                                        newcount - oldcount, locked_page != NULL);
                }
-               unlock_super(sb);
+               mutex_unlock(&UFS_SB(sb)->s_lock);
                UFSD("EXIT, result %llu\n", (unsigned long long)result);
                return result;
        }
@@ -443,7 +443,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
                                                fragment + count);
                ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
                                locked_page != NULL);
-               unlock_super(sb);
+               mutex_unlock(&UFS_SB(sb)->s_lock);
                UFSD("EXIT, result %llu\n", (unsigned long long)result);
                return result;
        }
@@ -481,7 +481,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
                *err = 0;
                UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag,
                                                fragment + count);
-               unlock_super(sb);
+               mutex_unlock(&UFS_SB(sb)->s_lock);
                if (newcount < request)
                        ufs_free_fragments (inode, result + newcount, request - newcount);
                ufs_free_fragments (inode, tmp, oldcount);
@@ -489,7 +489,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
                return result;
        }
 
-       unlock_super(sb);
+       mutex_unlock(&UFS_SB(sb)->s_lock);
        UFSD("EXIT (FAILED)\n");
        return 0;
 }              
index e84cbe21b9867d1f50ebe9d4c0fc3c7e1d05e7d0..d0426d74817b68402e97a9794b2c54c7ac4690c2 100644 (file)
@@ -71,11 +71,11 @@ void ufs_free_inode (struct inode * inode)
        
        ino = inode->i_ino;
 
-       lock_super (sb);
+       mutex_lock(&UFS_SB(sb)->s_lock);
 
        if (!((ino > 1) && (ino < (uspi->s_ncg * uspi->s_ipg )))) {
                ufs_warning(sb, "ufs_free_inode", "reserved inode or nonexistent inode %u\n", ino);
-               unlock_super (sb);
+               mutex_unlock(&UFS_SB(sb)->s_lock);
                return;
        }
        
@@ -83,7 +83,7 @@ void ufs_free_inode (struct inode * inode)
        bit = ufs_inotocgoff (ino);
        ucpi = ufs_load_cylinder (sb, cg);
        if (!ucpi) {
-               unlock_super (sb);
+               mutex_unlock(&UFS_SB(sb)->s_lock);
                return;
        }
        ucg = ubh_get_ucg(UCPI_UBH(ucpi));
@@ -117,7 +117,7 @@ void ufs_free_inode (struct inode * inode)
                ubh_sync_block(UCPI_UBH(ucpi));
        
        ufs_mark_sb_dirty(sb);
-       unlock_super (sb);
+       mutex_unlock(&UFS_SB(sb)->s_lock);
        UFSD("EXIT\n");
 }
 
@@ -197,7 +197,7 @@ struct inode *ufs_new_inode(struct inode *dir, umode_t mode)
        uspi = sbi->s_uspi;
        usb1 = ubh_get_usb_first(uspi);
 
-       lock_super (sb);
+       mutex_lock(&sbi->s_lock);
 
        /*
         * Try to place the inode in its parent directory
@@ -333,20 +333,20 @@ cg_found:
                brelse(bh);
        }
 
-       unlock_super (sb);
+       mutex_unlock(&sbi->s_lock);
 
        UFSD("allocating inode %lu\n", inode->i_ino);
        UFSD("EXIT\n");
        return inode;
 
 fail_remove_inode:
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_lock);
        clear_nlink(inode);
        iput(inode);
        UFSD("EXIT (FAILED): err %d\n", err);
        return ERR_PTR(err);
 failed:
-       unlock_super (sb);
+       mutex_unlock(&sbi->s_lock);
        make_bad_inode(inode);
        iput (inode);
        UFSD("EXIT (FAILED): err %d\n", err);
index f7cfecfe1caba90f9c6dc8d1cde2938e5128cb79..dc8e3a861d0fcddc79d3113b179672d7b59978e8 100644 (file)
@@ -699,7 +699,7 @@ static int ufs_sync_fs(struct super_block *sb, int wait)
        unsigned flags;
 
        lock_ufs(sb);
-       lock_super(sb);
+       mutex_lock(&UFS_SB(sb)->s_lock);
 
        UFSD("ENTER\n");
 
@@ -717,7 +717,7 @@ static int ufs_sync_fs(struct super_block *sb, int wait)
        ufs_put_cstotal(sb);
 
        UFSD("EXIT\n");
-       unlock_super(sb);
+       mutex_unlock(&UFS_SB(sb)->s_lock);
        unlock_ufs(sb);
 
        return 0;
@@ -805,6 +805,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
        }
 #endif
        mutex_init(&sbi->mutex);
+       mutex_init(&sbi->s_lock);
        spin_lock_init(&sbi->work_lock);
        INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs);
        /*
@@ -1280,7 +1281,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
        unsigned flags;
 
        lock_ufs(sb);
-       lock_super(sb);
+       mutex_lock(&UFS_SB(sb)->s_lock);
        uspi = UFS_SB(sb)->s_uspi;
        flags = UFS_SB(sb)->s_flags;
        usb1 = ubh_get_usb_first(uspi);
@@ -1294,7 +1295,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
        new_mount_opt = 0;
        ufs_set_opt (new_mount_opt, ONERROR_LOCK);
        if (!ufs_parse_options (data, &new_mount_opt)) {
-               unlock_super(sb);
+               mutex_unlock(&UFS_SB(sb)->s_lock);
                unlock_ufs(sb);
                return -EINVAL;
        }
@@ -1302,14 +1303,14 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
                new_mount_opt |= ufstype;
        } else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) {
                printk("ufstype can't be changed during remount\n");
-               unlock_super(sb);
+               mutex_unlock(&UFS_SB(sb)->s_lock);
                unlock_ufs(sb);
                return -EINVAL;
        }
 
        if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
                UFS_SB(sb)->s_mount_opt = new_mount_opt;
-               unlock_super(sb);
+               mutex_unlock(&UFS_SB(sb)->s_lock);
                unlock_ufs(sb);
                return 0;
        }
@@ -1334,7 +1335,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 #ifndef CONFIG_UFS_FS_WRITE
                printk("ufs was compiled with read-only support, "
                "can't be mounted as read-write\n");
-               unlock_super(sb);
+               mutex_unlock(&UFS_SB(sb)->s_lock);
                unlock_ufs(sb);
                return -EINVAL;
 #else
@@ -1344,13 +1345,13 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
                    ufstype != UFS_MOUNT_UFSTYPE_SUNx86 &&
                    ufstype != UFS_MOUNT_UFSTYPE_UFS2) {
                        printk("this ufstype is read-only supported\n");
-                       unlock_super(sb);
+                       mutex_unlock(&UFS_SB(sb)->s_lock);
                        unlock_ufs(sb);
                        return -EINVAL;
                }
                if (!ufs_read_cylinder_structures(sb)) {
                        printk("failed during remounting\n");
-                       unlock_super(sb);
+                       mutex_unlock(&UFS_SB(sb)->s_lock);
                        unlock_ufs(sb);
                        return -EPERM;
                }
@@ -1358,7 +1359,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 #endif
        }
        UFS_SB(sb)->s_mount_opt = new_mount_opt;
-       unlock_super(sb);
+       mutex_unlock(&UFS_SB(sb)->s_lock);
        unlock_ufs(sb);
        return 0;
 }
index 343e6fc571e5b3976b6132d43dccb03b538d9380..ff2c15ab81aaa05c06409966c03f9bb912e87c4a 100644 (file)
@@ -24,6 +24,7 @@ struct ufs_sb_info {
        int work_queued; /* non-zero if the delayed work is queued */
        struct delayed_work sync_work; /* FS sync delayed work */
        spinlock_t work_lock; /* protects sync_work and work_queued */
+       struct mutex s_lock;
 };
 
 struct ufs_inode_info {
index 1780f062dbaf1cd504f491af5962f3dfbd8db4ee..e164dddb8e9660dc1de0cfb1d6a6abd3da13ed6b 100644 (file)
@@ -412,7 +412,7 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
        if (!f.file)
                return error;
        dentry = f.file->f_path.dentry;
-       audit_inode(NULL, dentry);
+       audit_inode(NULL, dentry, 0);
        error = mnt_want_write_file(f.file);
        if (!error) {
                error = setxattr(dentry, name, value, size, flags);
@@ -507,7 +507,7 @@ SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
 
        if (!f.file)
                return error;
-       audit_inode(NULL, f.file->f_path.dentry);
+       audit_inode(NULL, f.file->f_path.dentry, 0);
        error = getxattr(f.file->f_path.dentry, name, value, size);
        fdput(f);
        return error;
@@ -586,7 +586,7 @@ SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
 
        if (!f.file)
                return error;
-       audit_inode(NULL, f.file->f_path.dentry);
+       audit_inode(NULL, f.file->f_path.dentry, 0);
        error = listxattr(f.file->f_path.dentry, list, size);
        fdput(f);
        return error;
@@ -655,7 +655,7 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
        if (!f.file)
                return error;
        dentry = f.file->f_path.dentry;
-       audit_inode(NULL, dentry);
+       audit_inode(NULL, dentry, 0);
        error = mnt_want_write_file(f.file);
        if (!error) {
                error = removexattr(dentry, name);
index 42679223a0fde641e3013980fbd1e733dc6ec60e..8c6d1d70278cc6e71dbc093cbbfc5f2c5d44df19 100644 (file)
@@ -189,6 +189,9 @@ xfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid,
        struct xfs_fid64        *fid64 = (struct xfs_fid64 *)fid;
        struct inode            *inode = NULL;
 
+       if (fh_len < xfs_fileid_length(fileid_type))
+               return NULL;
+
        switch (fileid_type) {
        case FILEID_INO32_GEN_PARENT:
                inode = xfs_nfs_get_inode(sb, fid->i32.parent_ino,
index 96c5c249b08628309e860367e11470e9ae5bd0e9..9069694e70eb9eee8b1bf4e229f29f7959ce3b46 100644 (file)
@@ -21,7 +21,6 @@ enum alarmtimer_restart {
 
 #define ALARMTIMER_STATE_INACTIVE      0x00
 #define ALARMTIMER_STATE_ENQUEUED      0x01
-#define ALARMTIMER_STATE_CALLBACK      0x02
 
 /**
  * struct alarm - Alarm timer structure
@@ -35,6 +34,7 @@ enum alarmtimer_restart {
  */
 struct alarm {
        struct timerqueue_node  node;
+       struct hrtimer          timer;
        enum alarmtimer_restart (*function)(struct alarm *, ktime_t now);
        enum alarmtimer_type    type;
        int                     state;
@@ -43,39 +43,12 @@ struct alarm {
 
 void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
                enum alarmtimer_restart (*function)(struct alarm *, ktime_t));
-void alarm_start(struct alarm *alarm, ktime_t start);
+int alarm_start(struct alarm *alarm, ktime_t start);
 int alarm_try_to_cancel(struct alarm *alarm);
 int alarm_cancel(struct alarm *alarm);
 
 u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval);
 
-/*
- * A alarmtimer is active, when it is enqueued into timerqueue or the
- * callback function is running.
- */
-static inline int alarmtimer_active(const struct alarm *timer)
-{
-       return timer->state != ALARMTIMER_STATE_INACTIVE;
-}
-
-/*
- * Helper function to check, whether the timer is on one of the queues
- */
-static inline int alarmtimer_is_queued(struct alarm *timer)
-{
-       return timer->state & ALARMTIMER_STATE_ENQUEUED;
-}
-
-/*
- * Helper function to check, whether the timer is running the callback
- * function
- */
-static inline int alarmtimer_callback_running(struct alarm *timer)
-{
-       return timer->state & ALARMTIMER_STATE_CALLBACK;
-}
-
-
 /* Provide way to access the rtc device being used by alarmtimers */
 struct rtc_device *alarmtimer_get_rtcdev(void);
 
index 2c83e5f7edb12882330d2958f9c1db6b2d708c69..e5884f950b4bac3160b667e44d258bda1e522550 100644 (file)
@@ -452,6 +452,16 @@ struct audit_field {
 extern int __init audit_register_class(int class, unsigned *list);
 extern int audit_classify_syscall(int abi, unsigned syscall);
 extern int audit_classify_arch(int arch);
+
+/* audit_names->type values */
+#define        AUDIT_TYPE_UNKNOWN      0       /* we don't know yet */
+#define        AUDIT_TYPE_NORMAL       1       /* a "normal" audit record */
+#define        AUDIT_TYPE_PARENT       2       /* a parent audit record */
+#define        AUDIT_TYPE_CHILD_DELETE 3       /* a child being deleted */
+#define        AUDIT_TYPE_CHILD_CREATE 4       /* a child being created */
+
+struct filename;
+
 #ifdef CONFIG_AUDITSYSCALL
 /* These are defined in auditsc.c */
                                /* Public API */
@@ -461,11 +471,14 @@ extern void __audit_syscall_entry(int arch,
                                  int major, unsigned long a0, unsigned long a1,
                                  unsigned long a2, unsigned long a3);
 extern void __audit_syscall_exit(int ret_success, long ret_value);
-extern void __audit_getname(const char *name);
-extern void audit_putname(const char *name);
-extern void __audit_inode(const char *name, const struct dentry *dentry);
-extern void __audit_inode_child(const struct dentry *dentry,
-                               const struct inode *parent);
+extern struct filename *__audit_reusename(const __user char *uptr);
+extern void __audit_getname(struct filename *name);
+extern void audit_putname(struct filename *name);
+extern void __audit_inode(struct filename *name, const struct dentry *dentry,
+                               unsigned int parent);
+extern void __audit_inode_child(const struct inode *parent,
+                               const struct dentry *dentry,
+                               const unsigned char type);
 extern void __audit_seccomp(unsigned long syscall, long signr, int code);
 extern void __audit_ptrace(struct task_struct *t);
 
@@ -495,19 +508,27 @@ static inline void audit_syscall_exit(void *pt_regs)
                __audit_syscall_exit(success, return_code);
        }
 }
-static inline void audit_getname(const char *name)
+static inline struct filename *audit_reusename(const __user char *name)
+{
+       if (unlikely(!audit_dummy_context()))
+               return __audit_reusename(name);
+       return NULL;
+}
+static inline void audit_getname(struct filename *name)
 {
        if (unlikely(!audit_dummy_context()))
                __audit_getname(name);
 }
-static inline void audit_inode(const char *name, const struct dentry *dentry) {
+static inline void audit_inode(struct filename *name, const struct dentry *dentry,
+                               unsigned int parent) {
        if (unlikely(!audit_dummy_context()))
-               __audit_inode(name, dentry);
+               __audit_inode(name, dentry, parent);
 }
-static inline void audit_inode_child(const struct dentry *dentry,
-                                    const struct inode *parent) {
+static inline void audit_inode_child(const struct inode *parent,
+                                    const struct dentry *dentry,
+                                    const unsigned char type) {
        if (unlikely(!audit_dummy_context()))
-               __audit_inode_child(dentry, parent);
+               __audit_inode_child(parent, dentry, type);
 }
 void audit_core_dumps(long signr);
 
@@ -651,19 +672,29 @@ static inline int audit_dummy_context(void)
 {
        return 1;
 }
-static inline void audit_getname(const char *name)
+static inline struct filename *audit_reusename(const __user char *name)
+{
+       return NULL;
+}
+static inline void audit_getname(struct filename *name)
 { }
-static inline void audit_putname(const char *name)
+static inline void audit_putname(struct filename *name)
 { }
-static inline void __audit_inode(const char *name, const struct dentry *dentry)
+static inline void __audit_inode(struct filename *name,
+                                       const struct dentry *dentry,
+                                       unsigned int parent)
 { }
-static inline void __audit_inode_child(const struct dentry *dentry,
-                                       const struct inode *parent)
+static inline void __audit_inode_child(const struct inode *parent,
+                                       const struct dentry *dentry,
+                                       const unsigned char type)
 { }
-static inline void audit_inode(const char *name, const struct dentry *dentry)
+static inline void audit_inode(struct filename *name,
+                               const struct dentry *dentry,
+                               unsigned int parent)
 { }
-static inline void audit_inode_child(const struct dentry *dentry,
-                                    const struct inode *parent)
+static inline void audit_inode_child(const struct inode *parent,
+                                    const struct dentry *dentry,
+                                    const unsigned char type)
 { }
 static inline void audit_core_dumps(long signr)
 { }
index 6ba45d2b99db2e153be43225addaabdb39060072..1cf1749440ac66dabd8b0f797e80690bbde9961d 100644 (file)
@@ -522,6 +522,8 @@ struct bcma_sflash {
        u32 blocksize;
        u16 numblocks;
        u32 size;
+
+       struct mtd_info *mtd;
 };
 #endif
 
index 37935c2d2e8f1eb1a4b071a38e3af6fd14bb1296..26531f32bbb2d29793979c1c240642f9463073e5 100644 (file)
@@ -19,6 +19,8 @@ struct pt_regs;
 
 #ifdef __KERNEL__
 #include <linux/sched.h>
+#include <linux/unistd.h>
+#include <asm/exec.h>
 
 #define CORENAME_MAX_SIZE 128
 
@@ -135,5 +137,9 @@ extern void install_exec_creds(struct linux_binprm *bprm);
 extern void set_binfmt(struct linux_binfmt *new);
 extern void free_bprm(struct linux_binprm *);
 
+#ifdef __ARCH_WANT_KERNEL_EXECVE
+extern void ret_from_kernel_execve(struct pt_regs *normal) __noreturn;
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_BINFMTS_H */
index 26435890dc87a6c3b9d37f14571833fb1afe0164..820e7aaad4fdbbf432b188b083662b5015bd3905 100644 (file)
@@ -212,20 +212,41 @@ extern void bio_pair_release(struct bio_pair *dbio);
 extern struct bio_set *bioset_create(unsigned int, unsigned int);
 extern void bioset_free(struct bio_set *);
 
-extern struct bio *bio_alloc(gfp_t, unsigned int);
-extern struct bio *bio_kmalloc(gfp_t, unsigned int);
 extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *);
 extern void bio_put(struct bio *);
-extern void bio_free(struct bio *, struct bio_set *);
+
+extern void __bio_clone(struct bio *, struct bio *);
+extern struct bio *bio_clone_bioset(struct bio *, gfp_t, struct bio_set *bs);
+
+extern struct bio_set *fs_bio_set;
+
+static inline struct bio *bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs)
+{
+       return bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
+}
+
+static inline struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask)
+{
+       return bio_clone_bioset(bio, gfp_mask, fs_bio_set);
+}
+
+static inline struct bio *bio_kmalloc(gfp_t gfp_mask, unsigned int nr_iovecs)
+{
+       return bio_alloc_bioset(gfp_mask, nr_iovecs, NULL);
+}
+
+static inline struct bio *bio_clone_kmalloc(struct bio *bio, gfp_t gfp_mask)
+{
+       return bio_clone_bioset(bio, gfp_mask, NULL);
+
+}
 
 extern void bio_endio(struct bio *, int);
 struct request_queue;
 extern int bio_phys_segments(struct request_queue *, struct bio *);
 
-extern void __bio_clone(struct bio *, struct bio *);
-extern struct bio *bio_clone(struct bio *, gfp_t);
-
 extern void bio_init(struct bio *);
+extern void bio_reset(struct bio *);
 
 extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int);
 extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *,
@@ -304,8 +325,6 @@ struct biovec_slab {
        struct kmem_cache *slab;
 };
 
-extern struct bio_set *fs_bio_set;
-
 /*
  * a small number of entries is fine, not going to be performance critical.
  * basically we just need to survive
@@ -367,9 +386,31 @@ static inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx,
 /*
  * Check whether this bio carries any data or not. A NULL bio is allowed.
  */
-static inline int bio_has_data(struct bio *bio)
+static inline bool bio_has_data(struct bio *bio)
 {
-       return bio && bio->bi_io_vec != NULL;
+       if (bio && bio->bi_vcnt)
+               return true;
+
+       return false;
+}
+
+static inline bool bio_is_rw(struct bio *bio)
+{
+       if (!bio_has_data(bio))
+               return false;
+
+       if (bio->bi_rw & REQ_WRITE_SAME)
+               return false;
+
+       return true;
+}
+
+static inline bool bio_mergeable(struct bio *bio)
+{
+       if (bio->bi_rw & REQ_NOMERGE_FLAGS)
+               return false;
+
+       return true;
 }
 
 /*
@@ -505,9 +546,8 @@ static inline struct bio *bio_list_get(struct bio_list *bl)
 
 #define bio_integrity(bio) (bio->bi_integrity != NULL)
 
-extern struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *, gfp_t, unsigned int, struct bio_set *);
 extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int);
-extern void bio_integrity_free(struct bio *, struct bio_set *);
+extern void bio_integrity_free(struct bio *);
 extern int bio_integrity_add_page(struct bio *, struct page *, unsigned int, unsigned int);
 extern int bio_integrity_enabled(struct bio *bio);
 extern int bio_integrity_set_tag(struct bio *, void *, unsigned int);
@@ -517,7 +557,7 @@ extern void bio_integrity_endio(struct bio *, int);
 extern void bio_integrity_advance(struct bio *, unsigned int);
 extern void bio_integrity_trim(struct bio *, unsigned int, unsigned int);
 extern void bio_integrity_split(struct bio *, struct bio_pair *, int);
-extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t, struct bio_set *);
+extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t);
 extern int bioset_integrity_create(struct bio_set *, int);
 extern void bioset_integrity_free(struct bio_set *);
 extern void bio_integrity_init(void);
@@ -549,13 +589,13 @@ static inline int bio_integrity_prep(struct bio *bio)
        return 0;
 }
 
-static inline void bio_integrity_free(struct bio *bio, struct bio_set *bs)
+static inline void bio_integrity_free(struct bio *bio)
 {
        return;
 }
 
 static inline int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
-                                     gfp_t gfp_mask, struct bio_set *bs)
+                                     gfp_t gfp_mask)
 {
        return 0;
 }
index 7b7ac9ccec7af5900b469166e7bdda9aa578b4d2..cdf11191e6450fa680b7a8b71352c3642633b9fb 100644 (file)
@@ -59,12 +59,6 @@ struct bio {
        unsigned int            bi_seg_front_size;
        unsigned int            bi_seg_back_size;
 
-       unsigned int            bi_max_vecs;    /* max bvl_vecs we can hold */
-
-       atomic_t                bi_cnt;         /* pin count */
-
-       struct bio_vec          *bi_io_vec;     /* the actual vec list */
-
        bio_end_io_t            *bi_end_io;
 
        void                    *bi_private;
@@ -80,7 +74,17 @@ struct bio {
        struct bio_integrity_payload *bi_integrity;  /* data integrity */
 #endif
 
-       bio_destructor_t        *bi_destructor; /* destructor */
+       /*
+        * Everything starting with bi_max_vecs will be preserved by bio_reset()
+        */
+
+       unsigned int            bi_max_vecs;    /* max bvl_vecs we can hold */
+
+       atomic_t                bi_cnt;         /* pin count */
+
+       struct bio_vec          *bi_io_vec;     /* the actual vec list */
+
+       struct bio_set          *bi_pool;
 
        /*
         * We can inline a number of vecs at the end of the bio, to avoid
@@ -90,6 +94,8 @@ struct bio {
        struct bio_vec          bi_inline_vecs[0];
 };
 
+#define BIO_RESET_BYTES                offsetof(struct bio, bi_max_vecs)
+
 /*
  * bio flags
  */
@@ -105,6 +111,13 @@ struct bio {
 #define BIO_FS_INTEGRITY 9     /* fs owns integrity data, not block layer */
 #define BIO_QUIET      10      /* Make BIO Quiet */
 #define BIO_MAPPED_INTEGRITY 11/* integrity metadata has been remapped */
+
+/*
+ * Flags starting here get preserved by bio_reset() - this includes
+ * BIO_POOL_IDX()
+ */
+#define BIO_RESET_BITS 12
+
 #define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag)))
 
 /*
@@ -134,6 +147,7 @@ enum rq_flag_bits {
        __REQ_PRIO,             /* boost priority in cfq */
        __REQ_DISCARD,          /* request to discard sectors */
        __REQ_SECURE,           /* secure discard (used with __REQ_DISCARD) */
+       __REQ_WRITE_SAME,       /* write same block many times */
 
        __REQ_NOIDLE,           /* don't anticipate more IO after this one */
        __REQ_FUA,              /* forced unit access */
@@ -172,15 +186,21 @@ enum rq_flag_bits {
 #define REQ_META               (1 << __REQ_META)
 #define REQ_PRIO               (1 << __REQ_PRIO)
 #define REQ_DISCARD            (1 << __REQ_DISCARD)
+#define REQ_WRITE_SAME         (1 << __REQ_WRITE_SAME)
 #define REQ_NOIDLE             (1 << __REQ_NOIDLE)
 
 #define REQ_FAILFAST_MASK \
        (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER)
 #define REQ_COMMON_MASK \
        (REQ_WRITE | REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_PRIO | \
-        REQ_DISCARD | REQ_NOIDLE | REQ_FLUSH | REQ_FUA | REQ_SECURE)
+        REQ_DISCARD | REQ_WRITE_SAME | REQ_NOIDLE | REQ_FLUSH | REQ_FUA | \
+        REQ_SECURE)
 #define REQ_CLONE_MASK         REQ_COMMON_MASK
 
+/* This mask is used for both bio and request merge checking */
+#define REQ_NOMERGE_FLAGS \
+       (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA)
+
 #define REQ_RAHEAD             (1 << __REQ_RAHEAD)
 #define REQ_THROTTLED          (1 << __REQ_THROTTLED)
 
index 4a2ab7c85393df48fd8d93e085f3b7ead5de7be2..1756001210d23a7f32037a3bfb21579202c8c380 100644 (file)
@@ -270,6 +270,7 @@ struct queue_limits {
        unsigned int            io_min;
        unsigned int            io_opt;
        unsigned int            max_discard_sectors;
+       unsigned int            max_write_same_sectors;
        unsigned int            discard_granularity;
        unsigned int            discard_alignment;
 
@@ -540,8 +541,7 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q)
 
 #define blk_account_rq(rq) \
        (((rq)->cmd_flags & REQ_STARTED) && \
-        ((rq)->cmd_type == REQ_TYPE_FS || \
-         ((rq)->cmd_flags & REQ_DISCARD)))
+        ((rq)->cmd_type == REQ_TYPE_FS))
 
 #define blk_pm_request(rq)     \
        ((rq)->cmd_type == REQ_TYPE_PM_SUSPEND || \
@@ -595,17 +595,39 @@ static inline void blk_clear_rl_full(struct request_list *rl, bool sync)
        rl->flags &= ~flag;
 }
 
+static inline bool rq_mergeable(struct request *rq)
+{
+       if (rq->cmd_type != REQ_TYPE_FS)
+               return false;
 
-/*
- * mergeable request must not have _NOMERGE or _BARRIER bit set, nor may
- * it already be started by driver.
- */
-#define RQ_NOMERGE_FLAGS       \
-       (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA | REQ_DISCARD)
-#define rq_mergeable(rq)       \
-       (!((rq)->cmd_flags & RQ_NOMERGE_FLAGS) && \
-        (((rq)->cmd_flags & REQ_DISCARD) || \
-         (rq)->cmd_type == REQ_TYPE_FS))
+       if (rq->cmd_flags & REQ_NOMERGE_FLAGS)
+               return false;
+
+       return true;
+}
+
+static inline bool blk_check_merge_flags(unsigned int flags1,
+                                        unsigned int flags2)
+{
+       if ((flags1 & REQ_DISCARD) != (flags2 & REQ_DISCARD))
+               return false;
+
+       if ((flags1 & REQ_SECURE) != (flags2 & REQ_SECURE))
+               return false;
+
+       if ((flags1 & REQ_WRITE_SAME) != (flags2 & REQ_WRITE_SAME))
+               return false;
+
+       return true;
+}
+
+static inline bool blk_write_same_mergeable(struct bio *a, struct bio *b)
+{
+       if (bio_data(a) == bio_data(b))
+               return true;
+
+       return false;
+}
 
 /*
  * q->prep_rq_fn return values
@@ -802,6 +824,28 @@ static inline unsigned int blk_rq_cur_sectors(const struct request *rq)
        return blk_rq_cur_bytes(rq) >> 9;
 }
 
+static inline unsigned int blk_queue_get_max_sectors(struct request_queue *q,
+                                                    unsigned int cmd_flags)
+{
+       if (unlikely(cmd_flags & REQ_DISCARD))
+               return q->limits.max_discard_sectors;
+
+       if (unlikely(cmd_flags & REQ_WRITE_SAME))
+               return q->limits.max_write_same_sectors;
+
+       return q->limits.max_sectors;
+}
+
+static inline unsigned int blk_rq_get_max_sectors(struct request *rq)
+{
+       struct request_queue *q = rq->q;
+
+       if (unlikely(rq->cmd_type == REQ_TYPE_BLOCK_PC))
+               return q->limits.max_hw_sectors;
+
+       return blk_queue_get_max_sectors(q, rq->cmd_flags);
+}
+
 /*
  * Request issue related functions.
  */
@@ -857,6 +901,8 @@ extern void blk_queue_max_segments(struct request_queue *, unsigned short);
 extern void blk_queue_max_segment_size(struct request_queue *, unsigned int);
 extern void blk_queue_max_discard_sectors(struct request_queue *q,
                unsigned int max_discard_sectors);
+extern void blk_queue_max_write_same_sectors(struct request_queue *q,
+               unsigned int max_write_same_sectors);
 extern void blk_queue_logical_block_size(struct request_queue *, unsigned short);
 extern void blk_queue_physical_block_size(struct request_queue *, unsigned int);
 extern void blk_queue_alignment_offset(struct request_queue *q,
@@ -987,6 +1033,8 @@ static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt,
 extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *);
 extern int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
                sector_t nr_sects, gfp_t gfp_mask, unsigned long flags);
+extern int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
+               sector_t nr_sects, gfp_t gfp_mask, struct page *page);
 extern int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
                        sector_t nr_sects, gfp_t gfp_mask);
 static inline int sb_issue_discard(struct super_block *sb, sector_t block,
@@ -1164,6 +1212,16 @@ static inline unsigned int bdev_discard_zeroes_data(struct block_device *bdev)
        return queue_discard_zeroes_data(bdev_get_queue(bdev));
 }
 
+static inline unsigned int bdev_write_same(struct block_device *bdev)
+{
+       struct request_queue *q = bdev_get_queue(bdev);
+
+       if (q)
+               return q->limits.max_write_same_sectors;
+
+       return 0;
+}
+
 static inline int queue_dma_alignment(struct request_queue *q)
 {
        return q ? q->dma_alignment : 511;
index a9cf250689dc2eb5a025a6897c0016e9a51d0b26..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,2 +0,0 @@
-header-y += caif_socket.h
-header-y += if_caif.h
index c62b7f1728f9ec24befce333161bfa8f48a3dcc9..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,5 +0,0 @@
-header-y += raw.h
-header-y += bcm.h
-header-y += gw.h
-header-y += error.h
-header-y += netlink.h
index fbe89e17124e9924bc3185e7a571d91bcada28f5..4dceaf8ae1525e57a0d6f7911e8dddac7047da4d 100644 (file)
@@ -319,22 +319,6 @@ static inline void __clocksource_updatefreq_khz(struct clocksource *cs, u32 khz)
        __clocksource_updatefreq_scale(cs, 1000, khz);
 }
 
-#ifdef CONFIG_GENERIC_TIME_VSYSCALL
-extern void
-update_vsyscall(struct timespec *ts, struct timespec *wtm,
-                       struct clocksource *c, u32 mult);
-extern void update_vsyscall_tz(void);
-#else
-static inline void
-update_vsyscall(struct timespec *ts, struct timespec *wtm,
-                       struct clocksource *c, u32 mult)
-{
-}
-
-static inline void update_vsyscall_tz(void)
-{
-}
-#endif
 
 extern void timekeeping_notify(struct clocksource *clock);
 
index 3f53d002c7c5c88521874e2e0085f0a083f2e7d1..d0ced1011f2fa28cf96087880d6cddda011de13f 100644 (file)
@@ -284,8 +284,12 @@ asmlinkage ssize_t compat_sys_pwritev(unsigned long fd,
                const struct compat_iovec __user *vec,
                unsigned long vlen, u32 pos_low, u32 pos_high);
 
-int compat_do_execve(char *filename, compat_uptr_t __user *argv,
-                    compat_uptr_t __user *envp, struct pt_regs *regs);
+int compat_do_execve(const char *filename, const compat_uptr_t __user *argv,
+                    const compat_uptr_t __user *envp, struct pt_regs *regs);
+#ifdef __ARCH_WANT_SYS_EXECVE
+asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv,
+                    const compat_uptr_t __user *envp);
+#endif
 
 asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
                compat_ulong_t __user *outp, compat_ulong_t __user *exp,
index 934bc34d5f993892f75c3b803d412b43e62dc072..412bc6c2b02358bd48f87cc0d029bd753dbae613 100644 (file)
@@ -59,7 +59,7 @@
 #if __GNUC_MINOR__ > 0
 #define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
 #endif
-#if __GNUC_MINOR__ >= 4 && !defined(__CHECKER__)
+#if __GNUC_MINOR__ >= 3 && !defined(__CHECKER__)
 #define __compiletime_warning(message) __attribute__((warning(message)))
 #define __compiletime_error(message) __attribute__((error(message)))
 #endif
index 7201ce4280caceb594e4cd11cf6ca4e7a072efee..dedb082fe50fde9e62190569b0c362238a46f1b0 100644 (file)
@@ -83,8 +83,14 @@ void give_up_console(const struct consw *sw);
 int con_debug_enter(struct vc_data *vc);
 int con_debug_leave(void);
 #else
-#define con_debug_enter(vc) (0)
-#define con_debug_leave() (0)
+static inline int con_debug_enter(struct vc_data *vc)
+{
+       return 0;
+}
+static inline int con_debug_leave(void)
+{
+       return 0;
+}
 #endif
 
 /* scroll */
index 20e5eac2ffd3f70688e35b7964fbdc0e172e8c4a..827cce7e33e330510c012e9857c40a77ea13b106 100644 (file)
@@ -24,6 +24,6 @@
 #define _DVBVERSION_H_
 
 #define DVB_API_VERSION 5
-#define DVB_API_VERSION_MINOR 8
+#define DVB_API_VERSION_MINOR 9
 
 #endif /*_DVBVERSION_H_*/
index 2412e02d7c0f78796202315002474c09c7c7558a..e1c8c9e919ac74401b566ccc08f9eeee67ca0a45 100644 (file)
  * @nr_channels: Number of channels supported by hardware (max 8)
  * @is_private: The device channels should be marked as private and not for
  *     by the general purpose DMA channel allocator.
+ * @block_size: Maximum block size supported by the controller
+ * @nr_masters: Number of AHB masters supported by the controller
+ * @data_width: Maximum data width supported by hardware per AHB master
+ *             (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
  */
 struct dw_dma_platform_data {
        unsigned int    nr_channels;
@@ -29,6 +33,9 @@ struct dw_dma_platform_data {
 #define CHAN_PRIORITY_ASCENDING                0       /* chan0 highest */
 #define CHAN_PRIORITY_DESCENDING       1       /* chan7 highest */
        unsigned char   chan_priority;
+       unsigned short  block_size;
+       unsigned char   nr_masters;
+       unsigned char   data_width[4];
 };
 
 /* bursts size */
diff --git a/include/linux/edma.h b/include/linux/edma.h
new file mode 100644 (file)
index 0000000..a1307e7
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * TI EDMA DMA engine driver
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * 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_EDMA_H
+#define __LINUX_EDMA_H
+
+struct dma_chan;
+
+#if defined(CONFIG_TI_EDMA) || defined(CONFIG_TI_EDMA_MODULE)
+bool edma_filter_fn(struct dma_chan *, void *);
+#else
+static inline bool edma_filter_fn(struct dma_chan *chan, void *param)
+{
+       return false;
+}
+#endif
+
+#endif
index c617ed024df87b952e968da04f988119b0db2d13..65fbf571023f6f8f2ffb48f686e7fc33fab023c7 100644 (file)
@@ -335,6 +335,7 @@ struct inodes_stat_t {
 #define BLKDISCARDZEROES _IO(0x12,124)
 #define BLKSECDISCARD _IO(0x12,125)
 #define BLKROTATIONAL _IO(0x12,126)
+#define BLKZEROOUT _IO(0x12,127)
 
 #define BMAP_IOCTL 1           /* obsolete - kept for compatibility */
 #define FIBMAP    _IO(0x00,1)  /* bmap access */
@@ -415,6 +416,7 @@ struct inodes_stat_t {
 #include <linux/migrate_mode.h>
 #include <linux/uidgid.h>
 #include <linux/lockdep.h>
+#include <linux/percpu-rwsem.h>
 
 #include <asm/byteorder.h>
 
@@ -724,6 +726,8 @@ struct block_device {
        int                     bd_fsfreeze_count;
        /* Mutex for freeze */
        struct mutex            bd_fsfreeze_mutex;
+       /* A semaphore that prevents I/O while block size is being changed */
+       struct percpu_rw_semaphore      bd_block_size_semaphore;
 };
 
 /*
@@ -1132,7 +1136,7 @@ static inline int file_check_writeable(struct file *filp)
 #if BITS_PER_LONG==32
 #define MAX_LFS_FILESIZE       (((loff_t)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1) 
 #elif BITS_PER_LONG==64
-#define MAX_LFS_FILESIZE       ((loff_t)0x7fffffffffffffff)
+#define MAX_LFS_FILESIZE       ((loff_t)0x7fffffffffffffffLL)
 #endif
 
 #define FL_POSIX       1
@@ -1507,7 +1511,6 @@ struct super_block {
        unsigned long           s_magic;
        struct dentry           *s_root;
        struct rw_semaphore     s_umount;
-       struct mutex            s_lock;
        int                     s_count;
        atomic_t                s_active;
 #ifdef CONFIG_SECURITY
@@ -2076,7 +2079,7 @@ extern struct vfsmount *kern_mount_data(struct file_system_type *, void *data);
 extern void kern_unmount(struct vfsmount *mnt);
 extern int may_umount_tree(struct vfsmount *);
 extern int may_umount(struct vfsmount *);
-extern long do_mount(char *, char *, char *, unsigned long, void *);
+extern long do_mount(const char *, const char *, const char *, unsigned long, void *);
 extern struct vfsmount *collect_mounts(struct path *);
 extern void drop_collected_mounts(struct vfsmount *);
 extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *,
@@ -2193,6 +2196,13 @@ static inline int break_lease(struct inode *inode, unsigned int mode)
 #endif /* CONFIG_FILE_LOCKING */
 
 /* fs/open.c */
+struct audit_names;
+struct filename {
+       const char              *name;  /* pointer to actual string */
+       const __user char       *uptr;  /* original userland pointer */
+       struct audit_names      *aname;
+       bool                    separate; /* should "name" be freed? */
+};
 
 extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
                       struct file *filp);
@@ -2200,12 +2210,15 @@ extern int do_fallocate(struct file *file, int mode, loff_t offset,
                        loff_t len);
 extern long do_sys_open(int dfd, const char __user *filename, int flags,
                        umode_t mode);
+extern struct file *file_open_name(struct filename *, int, umode_t);
 extern struct file *filp_open(const char *, int, umode_t);
 extern struct file *file_open_root(struct dentry *, struct vfsmount *,
                                   const char *, int);
 extern struct file * dentry_open(const struct path *, int, const struct cred *);
 extern int filp_close(struct file *, fl_owner_t id);
-extern char * getname(const char __user *);
+
+extern struct filename *getname(const char __user *);
+
 enum {
        FILE_CREATED = 1,
        FILE_OPENED = 2
@@ -2225,13 +2238,14 @@ extern void __init vfs_caches_init(unsigned long);
 
 extern struct kmem_cache *names_cachep;
 
-#define __getname_gfp(gfp)     kmem_cache_alloc(names_cachep, (gfp))
-#define __getname()            __getname_gfp(GFP_KERNEL)
+extern void final_putname(struct filename *name);
+
+#define __getname()            kmem_cache_alloc(names_cachep, GFP_KERNEL)
 #define __putname(name)                kmem_cache_free(names_cachep, (void *)(name))
 #ifndef CONFIG_AUDITSYSCALL
-#define putname(name)   __putname(name)
+#define putname(name)          final_putname(name)
 #else
-extern void putname(const char *name);
+extern void putname(struct filename *name);
 #endif
 
 #ifdef CONFIG_BLOCK
@@ -2570,6 +2584,8 @@ extern int generic_segment_checks(const struct iovec *iov,
                unsigned long *nr_segs, size_t *count, int access_flags);
 
 /* fs/block_dev.c */
+extern ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov,
+                              unsigned long nr_segs, loff_t pos);
 extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
                                unsigned long nr_segs, loff_t pos);
 extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
index a6dfe6944564018d070529e5e42642b8aca31de4..0fbfb4646d1b0e98542908415eef69205e554642 100644 (file)
@@ -109,7 +109,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
 
        if (source)
                fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0);
-       audit_inode_child(moved, new_dir);
+       audit_inode_child(new_dir, moved, AUDIT_TYPE_CHILD_CREATE);
 }
 
 /*
@@ -155,7 +155,7 @@ static inline void fsnotify_inoderemove(struct inode *inode)
  */
 static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
 {
-       audit_inode_child(dentry, inode);
+       audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
 
        fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
 }
@@ -168,7 +168,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
 static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry)
 {
        fsnotify_link_count(inode);
-       audit_inode_child(new_dentry, dir);
+       audit_inode_child(dir, new_dentry, AUDIT_TYPE_CHILD_CREATE);
 
        fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0);
 }
@@ -181,7 +181,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
        __u32 mask = (FS_CREATE | FS_ISDIR);
        struct inode *d_inode = dentry->d_inode;
 
-       audit_inode_child(dentry, inode);
+       audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
 
        fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
 }
index 1364d62e2fbe4c171d3146313bb767ffab421fe3..a3c3ecd59f08cf5ab801cd890edad28eb117340c 100644 (file)
@@ -62,6 +62,7 @@ struct i2c_algo_pca_data {
         * 330000, 288000, 217000, 146000, 88000, 59000, 44000, 36000
         * For PCA9665, use the frequency you want here. */
        unsigned int                    i2c_clock;
+       unsigned int                    chip;
 };
 
 int i2c_pca_add_bus(struct i2c_adapter *);
index 92a0dc75bc74661541e5b5c15f4cdd095c922b38..df804ba73e0b2ae97d935ba2c3797cd36b1499de 100644 (file)
@@ -34,7 +34,6 @@ struct omap_i2c_bus_platform_data {
        u32             clkrate;
        u32             rev;
        u32             flags;
-       void            (*set_mpu_wkup_lat)(struct device *dev, long set);
 };
 
 #endif
diff --git a/include/linux/i2c/i2c-rcar.h b/include/linux/i2c/i2c-rcar.h
new file mode 100644 (file)
index 0000000..496f5c2
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __I2C_R_CAR_H__
+#define __I2C_R_CAR_H__
+
+#include <linux/platform_device.h>
+
+struct i2c_rcar_platform_data {
+       u32 bus_speed;
+};
+
+#endif /* __I2C_R_CAR_H__ */
index e4dad4ddf0855b43ed30747ed565203d273acf2d..3265f332998a54c9722fd2d6825aa63f60f3aba2 100644 (file)
@@ -284,10 +284,16 @@ enum {
        IFLA_VXLAN_LEARNING,
        IFLA_VXLAN_AGEING,
        IFLA_VXLAN_LIMIT,
+       IFLA_VXLAN_PORT_RANGE,
        __IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
 
+struct ifla_vxlan_port_range {
+       __be16  low;
+       __be16  high;
+};
+
 /* SR-IOV virtual function management section */
 
 enum {
index e6ff12dd717baf338d2e8ef88cb524c912304ad0..c0ff748d0aa546671293ba5b42c46d108b7a6e26 100644 (file)
@@ -80,6 +80,8 @@ static inline int is_vlan_dev(struct net_device *dev)
 }
 
 #define vlan_tx_tag_present(__skb)     ((__skb)->vlan_tci & VLAN_TAG_PRESENT)
+#define vlan_tx_nonzero_tag_present(__skb) \
+       (vlan_tx_tag_present(__skb) && ((__skb)->vlan_tci & VLAN_VID_MASK))
 #define vlan_tx_tag_get(__skb)         ((__skb)->vlan_tci & ~VLAN_TAG_PRESENT)
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
@@ -89,7 +91,7 @@ extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev,
 extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
 extern u16 vlan_dev_vlan_id(const struct net_device *dev);
 
-extern bool vlan_do_receive(struct sk_buff **skb, bool last_handler);
+extern bool vlan_do_receive(struct sk_buff **skb);
 extern struct sk_buff *vlan_untag(struct sk_buff *skb);
 
 extern int vlan_vid_add(struct net_device *dev, unsigned short vid);
@@ -120,10 +122,8 @@ static inline u16 vlan_dev_vlan_id(const struct net_device *dev)
        return 0;
 }
 
-static inline bool vlan_do_receive(struct sk_buff **skb, bool last_handler)
+static inline bool vlan_do_receive(struct sk_buff **skb)
 {
-       if (((*skb)->vlan_tci & VLAN_VID_MASK) && last_handler)
-               (*skb)->pkt_type = PACKET_OTHERHOST;
        return false;
 }
 
index ba4874302939a8a645c99ac8c53f35772f57cd37..15464ba6bf53e9d19abcdcb8b9c5d28683c57957 100644 (file)
@@ -1396,8 +1396,8 @@ struct input_handle;
  * @start: starts handler for given handle. This function is called by
  *     input core right after connect() method and also when a process
  *     that "grabbed" a device releases it
- * @fops: file operations this driver implements
- * @minor: beginning of range of 32 minors for devices this driver
+ * @legacy_minors: set to %true by drivers using legacy minor ranges
+ * @minor: beginning of range of 32 legacy minors for devices this driver
  *     can provide
  * @name: name of the handler, to be shown in /proc/bus/input/handlers
  * @id_table: pointer to a table of input_device_ids this driver can
@@ -1431,7 +1431,7 @@ struct input_handler {
        void (*disconnect)(struct input_handle *handle);
        void (*start)(struct input_handle *handle);
 
-       const struct file_operations *fops;
+       bool legacy_minors;
        int minor;
        const char *name;
 
@@ -1499,6 +1499,10 @@ void input_reset_device(struct input_dev *);
 int __must_check input_register_handler(struct input_handler *);
 void input_unregister_handler(struct input_handler *);
 
+int __must_check input_get_new_minor(int legacy_base, unsigned int legacy_num,
+                                    bool allow_dynamic);
+void input_free_minor(unsigned int minor);
+
 int input_handler_for_each_handle(struct input_handler *, void *data,
                                  int (*fn)(struct input_handle *, void *));
 
index 991cdb29ab2e49c3348c7045921c5fc300cad15f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1 +0,0 @@
-header-y += capicmd.h
index 05e3c2c7a8cf81e2184f49a531a8158fa45639b4..6b87413da9d68877bf3f65f5d85023b1f9702fc4 100644 (file)
 #define SH_DIV(NOM,DEN,LSH) (   (((NOM) / (DEN)) << (LSH))              \
                              + ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN))
 
-#ifdef CLOCK_TICK_RATE
 /* LATCH is used in the interval timer and ftape setup. */
-# define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
+#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ)  /* For divider */
 
-/*
- * HZ is the requested value. However the CLOCK_TICK_RATE may not allow
- * for exactly HZ. So SHIFTED_HZ is high res HZ ("<< 8" is for accuracy)
- */
-# define SHIFTED_HZ (SH_DIV(CLOCK_TICK_RATE, LATCH, 8))
-#else
-# define SHIFTED_HZ (HZ << 8)
-#endif
+extern int register_refined_jiffies(long clock_tick_rate);
 
 /* TICK_NSEC is the time between ticks in nsec assuming SHIFTED_HZ */
-#define TICK_NSEC (SH_DIV(1000000UL * 1000, SHIFTED_HZ, 8))
+#define TICK_NSEC ((NSEC_PER_SEC+HZ/2)/HZ)
 
 /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */
 #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ)
 
-/*
- * TICK_USEC_TO_NSEC is the time between ticks in nsec assuming SHIFTED_HZ and
- * a value TUSEC for TICK_USEC (can be set bij adjtimex)
- */
-#define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV(TUSEC * USER_HZ * 1000, SHIFTED_HZ, 8))
-
 /* some arch's have a small-data section that can be accessed register-relative
  * but that can only take up to, say, 4-byte variables. jiffies being part of
  * an 8-byte variable may not be correctly accessed unless we force the issue
index 2694289babd08bd337ce5240d6f463ec8cb28aba..727877fb406d7eb526b9ede546c8d130e32e2995 100644 (file)
@@ -26,6 +26,7 @@
 /* See Documentation/leds/leds-lp5523.txt */
 
 struct lp5523_led_config {
+       const char      *name;
        u8              chan_nr;
        u8              led_current; /* mA x10, 0 if led is not connected */
        u8              max_current;
index c6f8dad2ceb08c5d778289025604bcb9a9ada5e4..6e53bb31c220d9f33224f2660bc52a1d9c44f0db 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/spinlock.h>
 #include <linux/rwsem.h>
 #include <linux/timer.h>
+#include <linux/workqueue.h>
 
 struct device;
 /*
@@ -69,6 +70,9 @@ struct led_classdev {
        struct timer_list        blink_timer;
        int                      blink_brightness;
 
+       struct work_struct      set_brightness_work;
+       int                     delayed_set_value;
+
 #ifdef CONFIG_LEDS_TRIGGERS
        /* Protects the trigger data below */
        struct rw_semaphore      trigger_lock;
index f01e5f6d1f07a4966927bb7acd5707f8f77904c8..0d24e932db0b62c97337069985f794276a455b83 100644 (file)
 #define br_write_lock(name)    lg_global_lock(name)
 #define br_write_unlock(name)  lg_global_unlock(name)
 
-#define DEFINE_BRLOCK(name)    DEFINE_LGLOCK(name)
+#define DEFINE_BRLOCK(name)            DEFINE_LGLOCK(name)
+#define DEFINE_STATIC_BRLOCK(name)     DEFINE_STATIC_LGLOCK(name)
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 #define LOCKDEP_INIT_MAP lockdep_init_map
-
-#define DEFINE_LGLOCK_LOCKDEP(name)                                    \
- struct lock_class_key name##_lock_key;                                        \
- struct lockdep_map name##_lock_dep_map;                               \
- EXPORT_SYMBOL(name##_lock_dep_map)
-
 #else
 #define LOCKDEP_INIT_MAP(a, b, c, d)
-
-#define DEFINE_LGLOCK_LOCKDEP(name)
 #endif
 
 struct lglock {
@@ -57,11 +50,15 @@ struct lglock {
 };
 
 #define DEFINE_LGLOCK(name)                                            \
-       DEFINE_LGLOCK_LOCKDEP(name);                                    \
-       DEFINE_PER_CPU(arch_spinlock_t, name ## _lock)                  \
+       static DEFINE_PER_CPU(arch_spinlock_t, name ## _lock)           \
        = __ARCH_SPIN_LOCK_UNLOCKED;                                    \
        struct lglock name = { .lock = &name ## _lock }
 
+#define DEFINE_STATIC_LGLOCK(name)                                     \
+       static DEFINE_PER_CPU(arch_spinlock_t, name ## _lock)           \
+       = __ARCH_SPIN_LOCK_UNLOCKED;                                    \
+       static struct lglock name = { .lock = &name ## _lock }
+
 void lg_lock_init(struct lglock *lg, char *name);
 void lg_local_lock(struct lglock *lg);
 void lg_local_unlock(struct lglock *lg);
index fd0e6d53836ee5f0064cdce06ed06959b0ba1f8e..11ddc7ffeba88972f21937a8b45d65191d40fc35 100644 (file)
@@ -396,7 +396,7 @@ enum {
 };
 
 struct sock;
-#ifdef CONFIG_MEMCG_KMEM
+#if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
 void sock_update_memcg(struct sock *sk);
 void sock_release_memcg(struct sock *sk);
 #else
@@ -406,6 +406,6 @@ static inline void sock_update_memcg(struct sock *sk)
 static inline void sock_release_memcg(struct sock *sk)
 {
 }
-#endif /* CONFIG_MEMCG_KMEM */
+#endif /* CONFIG_INET && CONFIG_MEMCG_KMEM */
 #endif /* _LINUX_MEMCONTROL_H */
 
index 1fb26448faa9ccb2a7ca85c9dcca74d52413f87c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1 +0,0 @@
-header-y += ioctl.h
index 4b27f9f503e4a25a18f664ea7bd84c9b385d11be..943550dfe9ea7f7f372c1a5d64d5a6328a371727 100644 (file)
@@ -57,6 +57,7 @@ struct mmc_ext_csd {
        unsigned int            sa_timeout;             /* Units: 100ns */
        unsigned int            generic_cmd6_time;      /* Units: 10ms */
        unsigned int            power_off_longtime;     /* Units: ms */
+       u8                      power_off_notification; /* state */
        unsigned int            hs_max_dtr;
 #define MMC_HIGH_26_MAX_DTR    26000000
 #define MMC_HIGH_52_MAX_DTR    52000000
@@ -76,10 +77,13 @@ struct mmc_ext_csd {
        bool                    hpi_en;                 /* HPI enablebit */
        bool                    hpi;                    /* HPI support bit */
        unsigned int            hpi_cmd;                /* cmd used as HPI */
+       bool                    bkops;          /* background support bit */
+       bool                    bkops_en;       /* background enable bit */
        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_exception_status;   /* 53 */
        u8                      raw_partition_support;  /* 160 */
        u8                      raw_erased_mem_count;   /* 181 */
        u8                      raw_ext_csd_structure;  /* 194 */
@@ -93,6 +97,7 @@ struct mmc_ext_csd {
        u8                      raw_sec_erase_mult;     /* 230 */
        u8                      raw_sec_feature_support;/* 231 */
        u8                      raw_trim_mult;          /* 232 */
+       u8                      raw_bkops_status;       /* 246 */
        u8                      raw_sectors[4];         /* 212 - 4 bytes */
 
        unsigned int            feature_support;
@@ -225,7 +230,7 @@ struct mmc_card {
 #define MMC_CARD_SDXC          (1<<6)          /* card is SDXC */
 #define MMC_CARD_REMOVED       (1<<7)          /* card has been removed */
 #define MMC_STATE_HIGHSPEED_200        (1<<8)          /* card is in HS200 mode */
-#define MMC_STATE_SLEEP                (1<<9)          /* card is in sleep state */
+#define MMC_STATE_DOING_BKOPS  (1<<10)         /* card is doing BKOPS */
        unsigned int            quirks;         /* card quirks */
 #define MMC_QUIRK_LENIENT_FN0  (1<<0)          /* allow SDIO FN0 writes outside of the VS CCCR range */
 #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)   /* use func->cur_blksize */
@@ -241,11 +246,6 @@ struct mmc_card {
 #define MMC_QUIRK_LONG_READ_TIME (1<<9)                /* Data read time > CSD says */
 #define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10)        /* Skip secure for erase/trim */
                                                /* byte mode */
-       unsigned int    poweroff_notify_state;  /* eMMC4.5 notify feature */
-#define MMC_NO_POWER_NOTIFICATION      0
-#define MMC_POWERED_ON                 1
-#define MMC_POWEROFF_SHORT             2
-#define MMC_POWEROFF_LONG              3
 
        unsigned int            erase_size;     /* erase size in sectors */
        unsigned int            erase_shift;    /* if erase unit is power 2 */
@@ -392,7 +392,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 #define mmc_sd_card_uhs(c)     ((c)->state & MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
 #define mmc_card_removed(c)    ((c) && ((c)->state & MMC_CARD_REMOVED))
-#define mmc_card_is_sleep(c)   ((c)->state & MMC_STATE_SLEEP)
+#define mmc_card_doing_bkops(c)        ((c)->state & MMC_STATE_DOING_BKOPS)
 
 #define mmc_card_set_present(c)        ((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
@@ -404,9 +404,9 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 #define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
 #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
-#define mmc_card_set_sleep(c)  ((c)->state |= MMC_STATE_SLEEP)
+#define mmc_card_set_doing_bkops(c)    ((c)->state |= MMC_STATE_DOING_BKOPS)
+#define mmc_card_clr_doing_bkops(c)    ((c)->state &= ~MMC_STATE_DOING_BKOPS)
 
-#define mmc_card_clr_sleep(c)  ((c)->state &= ~MMC_STATE_SLEEP)
 /*
  * Quirk add/remove for MMC products.
  */
index 1b431c728b9a057a150dff532fb3a47a4897e048..9b9cdafc7737931f12bcd790112faa907edc8bc1 100644 (file)
@@ -134,6 +134,8 @@ struct mmc_host;
 struct mmc_card;
 struct mmc_async_req;
 
+extern int mmc_stop_bkops(struct mmc_card *);
+extern int mmc_read_bkops_status(struct mmc_card *);
 extern struct mmc_async_req *mmc_start_req(struct mmc_host *,
                                           struct mmc_async_req *, int *);
 extern int mmc_interrupt_hpi(struct mmc_card *);
@@ -142,6 +144,8 @@ extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
 extern int mmc_app_cmd(struct mmc_host *, struct mmc_card *);
 extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
        struct mmc_command *, int);
+extern void mmc_start_bkops(struct mmc_card *card, bool from_exception);
+extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool);
 extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
 
 #define MMC_ERASE_ARG          0x00000000
index 7a7ebd367cfdd2591e01b3c69346c4c43464b74e..7c6a1139d8faf9ad54af671c68cd81ea3dcebf2f 100644 (file)
@@ -78,6 +78,10 @@ struct mmc_data;
  * @data_offset: Set the offset of DATA register according to VERID.
  * @dev: Device associated with the MMC controller.
  * @pdata: Platform data associated with the MMC controller.
+ * @drv_data: Driver specific data for identified variant of the controller
+ * @priv: Implementation defined private data.
+ * @biu_clk: Pointer to bus interface unit clock instance.
+ * @ciu_clk: Pointer to card interface unit clock instance.
  * @slot: Slots sharing this MMC controller.
  * @fifo_depth: depth of FIFO.
  * @data_shift: log2 of FIFO item size.
@@ -156,8 +160,12 @@ struct dw_mci {
        u32                     fifoth_val;
        u16                     verid;
        u16                     data_offset;
-       struct device           dev;
+       struct device           *dev;
        struct dw_mci_board     *pdata;
+       struct dw_mci_drv_data  *drv_data;
+       void                    *priv;
+       struct clk              *biu_clk;
+       struct clk              *ciu_clk;
        struct dw_mci_slot      *slot[MAX_MCI_SLOTS];
 
        /* FIFO push and pull */
@@ -201,7 +209,8 @@ struct dw_mci_dma_ops {
 #define DW_MCI_QUIRK_HIGHSPEED                 BIT(2)
 /* Unreliable card detection */
 #define DW_MCI_QUIRK_BROKEN_CARD_DETECTION     BIT(3)
-
+/* Write Protect detection not available */
+#define DW_MCI_QUIRK_NO_WRITE_PROTECT          BIT(4)
 
 struct dma_pdata;
 
@@ -218,7 +227,7 @@ struct dw_mci_board {
        u32 num_slots;
 
        u32 quirks; /* Workaround / Quirk flags */
-       unsigned int bus_hz; /* Bus speed */
+       unsigned int bus_hz; /* Clock speed at the cclk_in pad */
 
        unsigned int caps;      /* Capabilities */
        unsigned int caps2;     /* More capabilities */
index f578a71d82a6b71bd1c9203b53e77713c4543065..7abb0e1f7bda5b4a72f1477078abfd6d86232ffa 100644 (file)
@@ -259,10 +259,6 @@ struct mmc_host {
 #define MMC_CAP2_RO_ACTIVE_HIGH        (1 << 11)       /* Write-protect signal active high */
 
        mmc_pm_flag_t           pm_caps;        /* supported pm features */
-       unsigned int        power_notify_type;
-#define MMC_HOST_PW_NOTIFY_NONE                0
-#define MMC_HOST_PW_NOTIFY_SHORT       1
-#define MMC_HOST_PW_NOTIFY_LONG                2
 
 #ifdef CONFIG_MMC_CLKGATE
        int                     clk_requests;   /* internal reference counter */
@@ -300,6 +296,7 @@ struct mmc_host {
 #endif
 
        int                     rescan_disable; /* disable card detection */
+       int                     rescan_entered; /* used with nonremovable devices */
 
        struct mmc_card         *card;          /* device attached to this host */
 
index d425cab144d9ee752657b6de6053329f19f70436..01e4b394029b1bf15fc6d0bd70f0295b0ee28986 100644 (file)
@@ -139,6 +139,7 @@ static inline bool mmc_op_multi(u32 opcode)
 #define R1_CURRENT_STATE(x)    ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
 #define R1_READY_FOR_DATA      (1 << 8)        /* sx, a */
 #define R1_SWITCH_ERROR                (1 << 7)        /* sx, c */
+#define R1_EXCEPTION_EVENT     (1 << 6)        /* sx, a */
 #define R1_APP_CMD             (1 << 5)        /* sr, c */
 
 #define R1_STATE_IDLE  0
@@ -274,12 +275,15 @@ 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_EXP_EVENTS_STATUS      54      /* RO */
 #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 */
 #define EXT_CSD_HPI_MGMT               161     /* R/W */
 #define EXT_CSD_RST_N_FUNCTION         162     /* R/W */
+#define EXT_CSD_BKOPS_EN               163     /* R/W */
+#define EXT_CSD_BKOPS_START            164     /* W */
 #define EXT_CSD_SANITIZE_START         165     /* W */
 #define EXT_CSD_WR_REL_PARAM           166     /* RO */
 #define EXT_CSD_BOOT_WP                        173     /* R/W */
@@ -313,11 +317,13 @@ struct _mmc_csd {
 #define EXT_CSD_PWR_CL_200_360         237     /* RO */
 #define EXT_CSD_PWR_CL_DDR_52_195      238     /* RO */
 #define EXT_CSD_PWR_CL_DDR_52_360      239     /* RO */
+#define EXT_CSD_BKOPS_STATUS           246     /* RO */
 #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_BKOPS_SUPPORT          502     /* RO */
 #define EXT_CSD_HPI_FEATURES           503     /* RO */
 
 /*
@@ -377,6 +383,19 @@ struct _mmc_csd {
 #define EXT_CSD_PWR_CL_4BIT_MASK       0x0F    /* 8 bit PWR CLS */
 #define EXT_CSD_PWR_CL_8BIT_SHIFT      4
 #define EXT_CSD_PWR_CL_4BIT_SHIFT      0
+/*
+ * EXCEPTION_EVENT_STATUS field
+ */
+#define EXT_CSD_URGENT_BKOPS           BIT(0)
+#define EXT_CSD_DYNCAP_NEEDED          BIT(1)
+#define EXT_CSD_SYSPOOL_EXHAUSTED      BIT(2)
+#define EXT_CSD_PACKED_FAILURE         BIT(3)
+
+/*
+ * BKOPS status level
+ */
+#define EXT_CSD_BKOPS_LEVEL_2          0x2
+
 /*
  * MMC_SWITCH access modes
  */
index ac83b105bedd66d2fb051ead198d11297ab650c3..fa8529a859b8b7637a6b25e76e15ba7848cd9f79 100644 (file)
@@ -97,7 +97,8 @@ struct sdhci_host {
 
        const struct sdhci_ops *ops;    /* Low level hw interface */
 
-       struct regulator *vmmc; /* Power regulator */
+       struct regulator *vmmc;         /* Power regulator (vmmc) */
+       struct regulator *vqmmc;        /* Signaling regulator (vccq) */
 
        /* Internal data */
        struct mmc_host *mmc;   /* MMC structure */
index 650ef352f045f48ec9874b611faf18fc2a2b94cb..211ff67e8b0d0c3def3389ed474ab098112fa749 100644 (file)
@@ -78,8 +78,6 @@ struct nand_bbt_descr {
 #define NAND_BBT_LASTBLOCK     0x00000010
 /* The bbt is at the given page, else we must scan for the bbt */
 #define NAND_BBT_ABSPAGE       0x00000020
-/* The bbt is at the given page, else we must scan for the bbt */
-#define NAND_BBT_SEARCH                0x00000040
 /* bbt is stored per chip on multichip devices */
 #define NAND_BBT_PERCHIP       0x00000080
 /* bbt has a version counter at offset veroffs */
@@ -110,7 +108,10 @@ struct nand_bbt_descr {
  * OOB area. This option is passed to the default bad block table function.
  */
 #define NAND_BBT_USE_FLASH     0x00020000
-/* Do not store flash based bad block table in OOB area; store it in-band */
+/*
+ * Do not store flash based bad block table marker in the OOB area; store it
+ * in-band.
+ */
 #define NAND_BBT_NO_OOB                0x00040000
 /*
  * Do not write new bad block markers to OOB; useful, e.g., when ECC covers
diff --git a/include/linux/mtd/lpc32xx_mlc.h b/include/linux/mtd/lpc32xx_mlc.h
new file mode 100644 (file)
index 0000000..d91b1e3
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Platform data for LPC32xx SoC MLC NAND controller
+ *
+ * Copyright Â© 2012 Roland Stigge
+ *
+ * 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 __LINUX_MTD_LPC32XX_MLC_H
+#define __LINUX_MTD_LPC32XX_MLC_H
+
+#include <linux/dmaengine.h>
+
+struct lpc32xx_mlc_platform_data {
+       bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
+};
+
+#endif  /* __LINUX_MTD_LPC32XX_MLC_H */
diff --git a/include/linux/mtd/lpc32xx_slc.h b/include/linux/mtd/lpc32xx_slc.h
new file mode 100644 (file)
index 0000000..1169548
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Platform data for LPC32xx SoC SLC NAND controller
+ *
+ * Copyright Â© 2012 Roland Stigge
+ *
+ * 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 __LINUX_MTD_LPC32XX_SLC_H
+#define __LINUX_MTD_LPC32XX_SLC_H
+
+#include <linux/dmaengine.h>
+
+struct lpc32xx_slc_platform_data {
+       bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
+};
+
+#endif  /* __LINUX_MTD_LPC32XX_SLC_H */
index 63dadc0dfb629a74f6e578a16255ffc4cdb4d56a..81d61e70459938e6aab57239898e31fc8389e25c 100644 (file)
@@ -265,14 +265,7 @@ int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
                    const u_char *buf);
 
-static inline int mtd_read_oob(struct mtd_info *mtd, loff_t from,
-                              struct mtd_oob_ops *ops)
-{
-       ops->retlen = ops->oobretlen = 0;
-       if (!mtd->_read_oob)
-               return -EOPNOTSUPP;
-       return mtd->_read_oob(mtd, from, ops);
-}
+int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops);
 
 static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to,
                                struct mtd_oob_ops *ops)
index 57977c6405292347f8026fd23f7bc4572312e345..24e915957e4f0080fae4ed2545d8811917a5ab55 100644 (file)
@@ -56,7 +56,7 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
  * is supported now. If you add a chip with bigger oobsize/page
  * adjust this accordingly.
  */
-#define NAND_MAX_OOBSIZE       576
+#define NAND_MAX_OOBSIZE       640
 #define NAND_MAX_PAGESIZE      8192
 
 /*
@@ -92,6 +92,8 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 #define NAND_CMD_READID                0x90
 #define NAND_CMD_ERASE2                0xd0
 #define NAND_CMD_PARAM         0xec
+#define NAND_CMD_GET_FEATURES  0xee
+#define NAND_CMD_SET_FEATURES  0xef
 #define NAND_CMD_RESET         0xff
 
 #define NAND_CMD_LOCK          0x2a
@@ -185,12 +187,6 @@ typedef enum {
  * This happens with the Renesas AG-AND chips, possibly others.
  */
 #define BBT_AUTO_REFRESH       0x00000080
-/*
- * Chip does not require ready check on read. True
- * for all large page devices, as they do not support
- * autoincrement.
- */
-#define NAND_NO_READRDY                0x00000100
 /* Chip does not allow subpage writes */
 #define NAND_NO_SUBPAGE_WRITE  0x00000200
 
@@ -200,6 +196,9 @@ typedef enum {
 /* Device behaves just like nand, but is readonly */
 #define NAND_ROM               0x00000800
 
+/* Device supports subpage reads */
+#define NAND_SUBPAGE_READ      0x00001000
+
 /* Options valid for Samsung large page devices */
 #define NAND_SAMSUNG_LP_OPTIONS \
        (NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK)
@@ -208,12 +207,7 @@ typedef enum {
 #define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING))
 #define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG))
 #define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK))
-/* Large page NAND with SOFT_ECC should support subpage reads */
-#define NAND_SUBPAGE_READ(chip) ((chip->ecc.mode == NAND_ECC_SOFT) \
-                                       && (chip->page_shift > 9))
-
-/* Mask to zero out the chip options, which come from the id table */
-#define NAND_CHIPOPTIONS_MSK   0x0000ffff
+#define NAND_HAS_SUBPAGE_READ(chip) ((chip->options & NAND_SUBPAGE_READ))
 
 /* Non chip related options */
 /* This option skips the bbt scan during initialization. */
@@ -237,6 +231,21 @@ typedef enum {
 /* Keep gcc happy */
 struct nand_chip;
 
+/* ONFI timing mode, used in both asynchronous and synchronous mode */
+#define ONFI_TIMING_MODE_0             (1 << 0)
+#define ONFI_TIMING_MODE_1             (1 << 1)
+#define ONFI_TIMING_MODE_2             (1 << 2)
+#define ONFI_TIMING_MODE_3             (1 << 3)
+#define ONFI_TIMING_MODE_4             (1 << 4)
+#define ONFI_TIMING_MODE_5             (1 << 5)
+#define ONFI_TIMING_MODE_UNKNOWN       (1 << 6)
+
+/* ONFI feature address */
+#define ONFI_FEATURE_ADDR_TIMING_MODE  0x1
+
+/* ONFI subfeature parameters length */
+#define ONFI_SUBFEATURE_PARAM_LEN      4
+
 struct nand_onfi_params {
        /* rev info and features block */
        /* 'O' 'N' 'F' 'I'  */
@@ -334,8 +343,10 @@ struct nand_hw_control {
  * @read_page_raw:     function to read a raw page without ECC
  * @write_page_raw:    function to write a raw page without ECC
  * @read_page: function to read a page according to the ECC generator
- *             requirements.
- * @read_subpage:      function to read parts of the page covered by ECC.
+ *             requirements; returns maximum number of bitflips corrected in
+ *             any single ECC step, 0 if bitflips uncorrectable, -EIO hw error
+ * @read_subpage:      function to read parts of the page covered by ECC;
+ *                     returns same as read_page()
  * @write_page:        function to write a page according to the ECC generator
  *             requirements.
  * @write_oob_raw:     function to write chip OOB data without ECC
@@ -361,13 +372,13 @@ struct nand_ecc_ctrl {
                        uint8_t *calc_ecc);
        int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
                        uint8_t *buf, int oob_required, int page);
-       void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
+       int (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
                        const uint8_t *buf, int oob_required);
        int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
                        uint8_t *buf, int oob_required, int page);
        int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
                        uint32_t offs, uint32_t len, uint8_t *buf);
-       void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
+       int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
                        const uint8_t *buf, int oob_required);
        int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip,
                        int page);
@@ -403,8 +414,6 @@ struct nand_buffers {
  * @read_word:         [REPLACEABLE] read one word from the chip
  * @write_buf:         [REPLACEABLE] write data from the buffer to the chip
  * @read_buf:          [REPLACEABLE] read data from the chip into the buffer
- * @verify_buf:                [REPLACEABLE] verify buffer contents against the chip
- *                     data.
  * @select_chip:       [REPLACEABLE] select chip nr
  * @block_bad:         [REPLACEABLE] check, if the block is bad
  * @block_markbad:     [REPLACEABLE] mark the block bad
@@ -462,6 +471,8 @@ struct nand_buffers {
  *                     non 0 if ONFI supported.
  * @onfi_params:       [INTERN] holds the ONFI page parameter when ONFI is
  *                     supported, 0 otherwise.
+ * @onfi_set_features  [REPLACEABLE] set the features for ONFI nand
+ * @onfi_get_features  [REPLACEABLE] get the features for ONFI nand
  * @ecclayout:         [REPLACEABLE] the default ECC placement scheme
  * @bbt:               [INTERN] bad block table pointer
  * @bbt_td:            [REPLACEABLE] bad block table descriptor for flash
@@ -487,7 +498,6 @@ struct nand_chip {
        u16 (*read_word)(struct mtd_info *mtd);
        void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
        void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
-       int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
        void (*select_chip)(struct mtd_info *mtd, int chip);
        int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
        int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
@@ -505,6 +515,10 @@ struct nand_chip {
        int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
                        const uint8_t *buf, int oob_required, int page,
                        int cached, int raw);
+       int (*onfi_set_features)(struct mtd_info *mtd, struct nand_chip *chip,
+                       int feature_addr, uint8_t *subfeature_para);
+       int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip,
+                       int feature_addr, uint8_t *subfeature_para);
 
        int chip_delay;
        unsigned int options;
@@ -559,6 +573,7 @@ struct nand_chip {
 #define NAND_MFR_MICRON                0x2c
 #define NAND_MFR_AMD           0x01
 #define NAND_MFR_MACRONIX      0xc2
+#define NAND_MFR_EON           0x92
 
 /**
  * struct nand_flash_dev - NAND Flash Device ID Structure
@@ -641,6 +656,7 @@ struct platform_device;
  *                     ALE/CLE/nCE. Also used to write command and address
  * @write_buf:         platform specific function for write buffer
  * @read_buf:          platform specific function for read buffer
+ * @read_byte:         platform specific function to read one byte from chip
  * @priv:              private data to transport driver specific settings
  *
  * All fields are optional and depend on the hardware driver requirements
@@ -677,4 +693,20 @@ struct platform_nand_chip *get_platform_nandchip(struct mtd_info *mtd)
        return chip->priv;
 }
 
+/* return the supported asynchronous timing mode. */
+static inline int onfi_get_async_timing_mode(struct nand_chip *chip)
+{
+       if (!chip->onfi_version)
+               return ONFI_TIMING_MODE_UNKNOWN;
+       return le16_to_cpu(chip->onfi_params.async_timing_mode);
+}
+
+/* return the supported synchronous timing mode. */
+static inline int onfi_get_sync_timing_mode(struct nand_chip *chip)
+{
+       if (!chip->onfi_version)
+               return ONFI_TIMING_MODE_UNKNOWN;
+       return le16_to_cpu(chip->onfi_params.src_sync_timing_mode);
+}
+
 #endif /* __LINUX_MTD_NAND_H */
index a38e1fa8af0194d5e2ac43be29f3a65a313afd76..01e4b15b280ec2ca6ae135248eb1817c30d1efac 100644 (file)
@@ -49,7 +49,6 @@
 #define        FLERRADR(f)             (f->reg + 0x98)
 
 /* FLCMNCR control bits */
-#define ECCPOS2                (0x1 << 25)
 #define _4ECCCNTEN     (0x1 << 24)
 #define _4ECCEN                (0x1 << 23)
 #define _4ECCCORRECT   (0x1 << 22)
@@ -59,9 +58,6 @@
 #define QTSEL_E                (0x1 << 17)
 #define ENDIAN         (0x1 << 16)     /* 1 = little endian */
 #define FCKSEL_E       (0x1 << 15)
-#define ECCPOS_00      (0x00 << 12)
-#define ECCPOS_01      (0x01 << 12)
-#define ECCPOS_02      (0x02 << 12)
 #define ACM_SACCES_MODE        (0x01 << 10)
 #define NANWF_E                (0x1 << 9)
 #define SE_D           (0x1 << 8)      /* Spare area disable */
 #define DOCMD2_E       (0x1 << 17)     /* 2nd cmd stage execute */
 #define DOCMD1_E       (0x1 << 16)     /* 1st cmd stage execute */
 
+/* FLINTDMACR control bits */
+#define ESTERINTE      (0x1 << 24)     /* ECC error interrupt enable */
+#define AC1CLR         (0x1 << 19)     /* ECC FIFO clear */
+#define AC0CLR         (0x1 << 18)     /* Data FIFO clear */
+#define ECERB          (0x1 << 9)      /* ECC error */
+#define STERB          (0x1 << 8)      /* Status error */
+#define STERINTE       (0x1 << 4)      /* Status error enable */
+
 /* FLTRCR control bits */
 #define TRSTRT         (0x1 << 0)      /* translation start */
 #define TREND          (0x1 << 1)      /* translation end */
 #define        _4ECCEND        (0x1 << 1)      /* 4 symbols end */
 #define        _4ECCEXST       (0x1 << 0)      /* 4 symbols exist */
 
-#define INIT_FL4ECCRESULT_VAL  0x03FF03FF
 #define LOOP_TIMEOUT_MAX       0x00010000
 
+enum flctl_ecc_res_t {
+       FL_SUCCESS,
+       FL_REPAIRABLE,
+       FL_ERROR,
+       FL_TIMEOUT
+};
+
 struct sh_flctl {
        struct mtd_info         mtd;
        struct nand_chip        chip;
@@ -145,8 +155,7 @@ struct sh_flctl {
        uint32_t erase_ADRCNT;          /* bits of FLCMDCR in ERASE1 cmd */
        uint32_t rw_ADRCNT;     /* bits of FLCMDCR in READ WRITE cmd */
        uint32_t flcmncr_base;  /* base value of FLCMNCR */
-
-       int     hwecc_cant_correct[4];
+       uint32_t flintdmacr_base;       /* irq enable bits */
 
        unsigned page_size:1;   /* NAND page size (0 = 512, 1 = 2048) */
        unsigned hwecc:1;       /* Hardware ECC (0 = disabled, 1 = enabled) */
index 01646aa53b0e6c30be6de8afb406516a2f4b69a5..561c8bc8976dce2b65245aba6aa051cdc590c69f 100644 (file)
@@ -1497,19 +1497,25 @@ struct napi_gro_cb {
        /* This indicates where we are processing relative to skb->data. */
        int data_offset;
 
-       /* This is non-zero if the packet may be of the same flow. */
-       int same_flow;
-
        /* This is non-zero if the packet cannot be merged with the new skb. */
        int flush;
 
        /* Number of segments aggregated. */
-       int count;
+       u16     count;
+
+       /* This is non-zero if the packet may be of the same flow. */
+       u8      same_flow;
 
        /* Free the skb? */
-       int free;
+       u8      free;
 #define NAPI_GRO_FREE            1
 #define NAPI_GRO_FREE_STOLEN_HEAD 2
+
+       /* jiffies when first packet was created/queued */
+       unsigned long age;
+
+       /* Used in ipv6_gro_receive() */
+       int     proto;
 };
 
 #define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb)
@@ -1663,7 +1669,6 @@ extern int                netpoll_trap(void);
 #endif
 extern int            skb_gro_receive(struct sk_buff **head,
                                       struct sk_buff *skb);
-extern void           skb_gro_reset_offset(struct sk_buff *skb);
 
 static inline unsigned int skb_gro_offset(const struct sk_buff *skb)
 {
@@ -2157,7 +2162,7 @@ extern gro_result_t       dev_gro_receive(struct napi_struct *napi,
 extern gro_result_t    napi_skb_finish(gro_result_t ret, struct sk_buff *skb);
 extern gro_result_t    napi_gro_receive(struct napi_struct *napi,
                                         struct sk_buff *skb);
-extern void            napi_gro_flush(struct napi_struct *napi);
+extern void            napi_gro_flush(struct napi_struct *napi, bool flush_old);
 extern struct sk_buff *        napi_get_frags(struct napi_struct *napi);
 extern gro_result_t    napi_frags_finish(struct napi_struct *napi,
                                          struct sk_buff *skb,
index 874ae8f2706b16572654faee8b1db74cab84a2bf..b3322023e9a5141e7304f2642ed7cff5aff38584 100644 (file)
@@ -1,78 +1 @@
 header-y += ipset/
-
-header-y += nf_conntrack_common.h
-header-y += nf_conntrack_ftp.h
-header-y += nf_conntrack_sctp.h
-header-y += nf_conntrack_tcp.h
-header-y += nf_conntrack_tuple_common.h
-header-y += nf_nat.h
-header-y += nfnetlink.h
-header-y += nfnetlink_acct.h
-header-y += nfnetlink_compat.h
-header-y += nfnetlink_conntrack.h
-header-y += nfnetlink_cthelper.h
-header-y += nfnetlink_cttimeout.h
-header-y += nfnetlink_log.h
-header-y += nfnetlink_queue.h
-header-y += x_tables.h
-header-y += xt_AUDIT.h
-header-y += xt_CHECKSUM.h
-header-y += xt_CLASSIFY.h
-header-y += xt_CONNMARK.h
-header-y += xt_CONNSECMARK.h
-header-y += xt_CT.h
-header-y += xt_DSCP.h
-header-y += xt_IDLETIMER.h
-header-y += xt_LED.h
-header-y += xt_LOG.h
-header-y += xt_MARK.h
-header-y += xt_nfacct.h
-header-y += xt_NFLOG.h
-header-y += xt_NFQUEUE.h
-header-y += xt_RATEEST.h
-header-y += xt_SECMARK.h
-header-y += xt_TCPMSS.h
-header-y += xt_TCPOPTSTRIP.h
-header-y += xt_TEE.h
-header-y += xt_TPROXY.h
-header-y += xt_addrtype.h
-header-y += xt_cluster.h
-header-y += xt_comment.h
-header-y += xt_connbytes.h
-header-y += xt_connlimit.h
-header-y += xt_connmark.h
-header-y += xt_conntrack.h
-header-y += xt_cpu.h
-header-y += xt_dccp.h
-header-y += xt_devgroup.h
-header-y += xt_dscp.h
-header-y += xt_ecn.h
-header-y += xt_esp.h
-header-y += xt_hashlimit.h
-header-y += xt_helper.h
-header-y += xt_iprange.h
-header-y += xt_ipvs.h
-header-y += xt_length.h
-header-y += xt_limit.h
-header-y += xt_mac.h
-header-y += xt_mark.h
-header-y += xt_multiport.h
-header-y += xt_osf.h
-header-y += xt_owner.h
-header-y += xt_physdev.h
-header-y += xt_pkttype.h
-header-y += xt_policy.h
-header-y += xt_quota.h
-header-y += xt_rateest.h
-header-y += xt_realm.h
-header-y += xt_recent.h
-header-y += xt_set.h
-header-y += xt_sctp.h
-header-y += xt_socket.h
-header-y += xt_state.h
-header-y += xt_statistic.h
-header-y += xt_string.h
-header-y += xt_tcpmss.h
-header-y += xt_tcpudp.h
-header-y += xt_time.h
-header-y += xt_u32.h
index 601fe71d34d55b46a7976c77cd208d765d7f870f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,4 +0,0 @@
-header-y += ip_set.h
-header-y += ip_set_bitmap.h
-header-y += ip_set_hash.h
-header-y += ip_set_list.h
index 528697b3c1524d1e7e071986231e2d14979018c2..7958e84a65afa22a8d6f406da674b2843e93b041 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef _IP_SET_H
-#define _IP_SET_H
-
 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
  *                         Patrick Schaaf <bof@bof.de>
  *                         Martin Josefsson <gandalf@wlug.westbo.se>
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#ifndef _IP_SET_H
+#define _IP_SET_H
 
-#include <linux/types.h>
-
-/* The protocol version */
-#define IPSET_PROTOCOL         6
-
-/* The max length of strings including NUL: set and type identifiers */
-#define IPSET_MAXNAMELEN       32
-
-/* Message types and commands */
-enum ipset_cmd {
-       IPSET_CMD_NONE,
-       IPSET_CMD_PROTOCOL,     /* 1: Return protocol version */
-       IPSET_CMD_CREATE,       /* 2: Create a new (empty) set */
-       IPSET_CMD_DESTROY,      /* 3: Destroy a (empty) set */
-       IPSET_CMD_FLUSH,        /* 4: Remove all elements from a set */
-       IPSET_CMD_RENAME,       /* 5: Rename a set */
-       IPSET_CMD_SWAP,         /* 6: Swap two sets */
-       IPSET_CMD_LIST,         /* 7: List sets */
-       IPSET_CMD_SAVE,         /* 8: Save sets */
-       IPSET_CMD_ADD,          /* 9: Add an element to a set */
-       IPSET_CMD_DEL,          /* 10: Delete an element from a set */
-       IPSET_CMD_TEST,         /* 11: Test an element in a set */
-       IPSET_CMD_HEADER,       /* 12: Get set header data only */
-       IPSET_CMD_TYPE,         /* 13: Get set type */
-       IPSET_MSG_MAX,          /* Netlink message commands */
-
-       /* Commands in userspace: */
-       IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */
-       IPSET_CMD_HELP,         /* 15: Get help */
-       IPSET_CMD_VERSION,      /* 16: Get program version */
-       IPSET_CMD_QUIT,         /* 17: Quit from interactive mode */
-
-       IPSET_CMD_MAX,
-
-       IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */
-};
-
-/* Attributes at command level */
-enum {
-       IPSET_ATTR_UNSPEC,
-       IPSET_ATTR_PROTOCOL,    /* 1: Protocol version */
-       IPSET_ATTR_SETNAME,     /* 2: Name of the set */
-       IPSET_ATTR_TYPENAME,    /* 3: Typename */
-       IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */
-       IPSET_ATTR_REVISION,    /* 4: Settype revision */
-       IPSET_ATTR_FAMILY,      /* 5: Settype family */
-       IPSET_ATTR_FLAGS,       /* 6: Flags at command level */
-       IPSET_ATTR_DATA,        /* 7: Nested attributes */
-       IPSET_ATTR_ADT,         /* 8: Multiple data containers */
-       IPSET_ATTR_LINENO,      /* 9: Restore lineno */
-       IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */
-       IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
-       __IPSET_ATTR_CMD_MAX,
-};
-#define IPSET_ATTR_CMD_MAX     (__IPSET_ATTR_CMD_MAX - 1)
-
-/* CADT specific attributes */
-enum {
-       IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,
-       IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,
-       IPSET_ATTR_IP_TO,       /* 2 */
-       IPSET_ATTR_CIDR,        /* 3 */
-       IPSET_ATTR_PORT,        /* 4 */
-       IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,
-       IPSET_ATTR_PORT_TO,     /* 5 */
-       IPSET_ATTR_TIMEOUT,     /* 6 */
-       IPSET_ATTR_PROTO,       /* 7 */
-       IPSET_ATTR_CADT_FLAGS,  /* 8 */
-       IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO,     /* 9 */
-       /* Reserve empty slots */
-       IPSET_ATTR_CADT_MAX = 16,
-       /* Create-only specific attributes */
-       IPSET_ATTR_GC,
-       IPSET_ATTR_HASHSIZE,
-       IPSET_ATTR_MAXELEM,
-       IPSET_ATTR_NETMASK,
-       IPSET_ATTR_PROBES,
-       IPSET_ATTR_RESIZE,
-       IPSET_ATTR_SIZE,
-       /* Kernel-only */
-       IPSET_ATTR_ELEMENTS,
-       IPSET_ATTR_REFERENCES,
-       IPSET_ATTR_MEMSIZE,
-
-       __IPSET_ATTR_CREATE_MAX,
-};
-#define IPSET_ATTR_CREATE_MAX  (__IPSET_ATTR_CREATE_MAX - 1)
-
-/* ADT specific attributes */
-enum {
-       IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + 1,
-       IPSET_ATTR_NAME,
-       IPSET_ATTR_NAMEREF,
-       IPSET_ATTR_IP2,
-       IPSET_ATTR_CIDR2,
-       IPSET_ATTR_IP2_TO,
-       IPSET_ATTR_IFACE,
-       __IPSET_ATTR_ADT_MAX,
-};
-#define IPSET_ATTR_ADT_MAX     (__IPSET_ATTR_ADT_MAX - 1)
-
-/* IP specific attributes */
-enum {
-       IPSET_ATTR_IPADDR_IPV4 = IPSET_ATTR_UNSPEC + 1,
-       IPSET_ATTR_IPADDR_IPV6,
-       __IPSET_ATTR_IPADDR_MAX,
-};
-#define IPSET_ATTR_IPADDR_MAX  (__IPSET_ATTR_IPADDR_MAX - 1)
-
-/* Error codes */
-enum ipset_errno {
-       IPSET_ERR_PRIVATE = 4096,
-       IPSET_ERR_PROTOCOL,
-       IPSET_ERR_FIND_TYPE,
-       IPSET_ERR_MAX_SETS,
-       IPSET_ERR_BUSY,
-       IPSET_ERR_EXIST_SETNAME2,
-       IPSET_ERR_TYPE_MISMATCH,
-       IPSET_ERR_EXIST,
-       IPSET_ERR_INVALID_CIDR,
-       IPSET_ERR_INVALID_NETMASK,
-       IPSET_ERR_INVALID_FAMILY,
-       IPSET_ERR_TIMEOUT,
-       IPSET_ERR_REFERENCED,
-       IPSET_ERR_IPADDR_IPV4,
-       IPSET_ERR_IPADDR_IPV6,
-
-       /* Type specific error codes */
-       IPSET_ERR_TYPE_SPECIFIC = 4352,
-};
-
-/* Flags at command level */
-enum ipset_cmd_flags {
-       IPSET_FLAG_BIT_EXIST    = 0,
-       IPSET_FLAG_EXIST        = (1 << IPSET_FLAG_BIT_EXIST),
-       IPSET_FLAG_BIT_LIST_SETNAME = 1,
-       IPSET_FLAG_LIST_SETNAME = (1 << IPSET_FLAG_BIT_LIST_SETNAME),
-       IPSET_FLAG_BIT_LIST_HEADER = 2,
-       IPSET_FLAG_LIST_HEADER  = (1 << IPSET_FLAG_BIT_LIST_HEADER),
-       IPSET_FLAG_CMD_MAX = 15,        /* Lower half */
-};
-
-/* Flags at CADT attribute level */
-enum ipset_cadt_flags {
-       IPSET_FLAG_BIT_BEFORE   = 0,
-       IPSET_FLAG_BEFORE       = (1 << IPSET_FLAG_BIT_BEFORE),
-       IPSET_FLAG_BIT_PHYSDEV  = 1,
-       IPSET_FLAG_PHYSDEV      = (1 << IPSET_FLAG_BIT_PHYSDEV),
-       IPSET_FLAG_BIT_NOMATCH  = 2,
-       IPSET_FLAG_NOMATCH      = (1 << IPSET_FLAG_BIT_NOMATCH),
-       IPSET_FLAG_CADT_MAX     = 15,   /* Upper half */
-};
-
-/* Commands with settype-specific attributes */
-enum ipset_adt {
-       IPSET_ADD,
-       IPSET_DEL,
-       IPSET_TEST,
-       IPSET_ADT_MAX,
-       IPSET_CREATE = IPSET_ADT_MAX,
-       IPSET_CADT_MAX,
-};
-
-/* Sets are identified by an index in kernel space. Tweak with ip_set_id_t
- * and IPSET_INVALID_ID if you want to increase the max number of sets.
- */
-typedef __u16 ip_set_id_t;
-
-#define IPSET_INVALID_ID               65535
-
-enum ip_set_dim {
-       IPSET_DIM_ZERO = 0,
-       IPSET_DIM_ONE,
-       IPSET_DIM_TWO,
-       IPSET_DIM_THREE,
-       /* Max dimension in elements.
-        * If changed, new revision of iptables match/target is required.
-        */
-       IPSET_DIM_MAX = 6,
-       IPSET_BIT_RETURN_NOMATCH = 7,
-};
-
-/* Option flags for kernel operations */
-enum ip_set_kopt {
-       IPSET_INV_MATCH = (1 << IPSET_DIM_ZERO),
-       IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE),
-       IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO),
-       IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE),
-       IPSET_RETURN_NOMATCH = (1 << IPSET_BIT_RETURN_NOMATCH),
-};
-
-#ifdef __KERNEL__
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <linux/netlink.h>
@@ -211,6 +18,7 @@ enum ip_set_kopt {
 #include <linux/stringify.h>
 #include <linux/vmalloc.h>
 #include <net/netlink.h>
+#include <uapi/linux/netfilter/ipset/ip_set.h>
 
 #define _IP_SET_MODULE_DESC(a, b, c)           \
        MODULE_DESCRIPTION(a " type of IP sets, revisions " b "-" c)
@@ -476,31 +284,4 @@ bitmap_bytes(u32 a, u32 b)
        return 4 * ((((b - a + 8) / 8) + 3) / 4);
 }
 
-#endif /* __KERNEL__ */
-
-/* Interface to iptables/ip6tables */
-
-#define SO_IP_SET              83
-
-union ip_set_name_index {
-       char name[IPSET_MAXNAMELEN];
-       ip_set_id_t index;
-};
-
-#define IP_SET_OP_GET_BYNAME   0x00000006      /* Get set index by name */
-struct ip_set_req_get_set {
-       unsigned int op;
-       unsigned int version;
-       union ip_set_name_index set;
-};
-
-#define IP_SET_OP_GET_BYINDEX  0x00000007      /* Get set name by index */
-/* Uses ip_set_req_get_set */
-
-#define IP_SET_OP_VERSION      0x00000100      /* Ask kernel version */
-struct ip_set_req_version {
-       unsigned int op;
-       unsigned int version;
-};
-
 #endif /*_IP_SET_H */
index 61a9e8746c8399dcbd5c8948e39d0aa712db121c..1a30646d5be853f74463f3d6f9f1ee4408ed785a 100644 (file)
@@ -1,15 +1,8 @@
 #ifndef __IP_SET_BITMAP_H
 #define __IP_SET_BITMAP_H
 
-/* Bitmap type specific error codes */
-enum {
-       /* The element is out of the range of the set */
-       IPSET_ERR_BITMAP_RANGE = IPSET_ERR_TYPE_SPECIFIC,
-       /* The range exceeds the size limit of the set type */
-       IPSET_ERR_BITMAP_RANGE_SIZE,
-};
+#include <uapi/linux/netfilter/ipset/ip_set_bitmap.h>
 
-#ifdef __KERNEL__
 #define IPSET_BITMAP_MAX_RANGE 0x0000FFFF
 
 /* Common functions */
@@ -26,6 +19,4 @@ range_to_mask(u32 from, u32 to, u8 *bits)
        return mask;
 }
 
-#endif /* __KERNEL__ */
-
 #endif /* __IP_SET_BITMAP_H */
index e2a9fae767f631ac9fbc406a5237bbf099ca6ef7..f98ddfb094cb320fc9059a78347df396140d1bb4 100644 (file)
@@ -1,23 +1,8 @@
 #ifndef __IP_SET_HASH_H
 #define __IP_SET_HASH_H
 
-/* Hash type specific error codes */
-enum {
-       /* Hash is full */
-       IPSET_ERR_HASH_FULL = IPSET_ERR_TYPE_SPECIFIC,
-       /* Null-valued element */
-       IPSET_ERR_HASH_ELEM,
-       /* Invalid protocol */
-       IPSET_ERR_INVALID_PROTO,
-       /* Protocol missing but must be specified */
-       IPSET_ERR_MISSING_PROTO,
-       /* Range not supported */
-       IPSET_ERR_HASH_RANGE_UNSUPPORTED,
-       /* Invalid range */
-       IPSET_ERR_HASH_RANGE,
-};
+#include <uapi/linux/netfilter/ipset/ip_set_hash.h>
 
-#ifdef __KERNEL__
 
 #define IPSET_DEFAULT_HASHSIZE         1024
 #define IPSET_MIMINAL_HASHSIZE         64
@@ -25,6 +10,4 @@ enum {
 #define IPSET_DEFAULT_PROBES           4
 #define IPSET_DEFAULT_RESIZE           100
 
-#endif /* __KERNEL__ */
-
 #endif /* __IP_SET_HASH_H */
index 40a63f30261319158c3e15737052867cacc6a37e..68c2aea897f593664dd9d0ab7131b1defd0a9265 100644 (file)
@@ -1,27 +1,10 @@
 #ifndef __IP_SET_LIST_H
 #define __IP_SET_LIST_H
 
-/* List type specific error codes */
-enum {
-       /* Set name to be added/deleted/tested does not exist. */
-       IPSET_ERR_NAME = IPSET_ERR_TYPE_SPECIFIC,
-       /* list:set type is not permitted to add */
-       IPSET_ERR_LOOP,
-       /* Missing reference set */
-       IPSET_ERR_BEFORE,
-       /* Reference set does not exist */
-       IPSET_ERR_NAMEREF,
-       /* Set is full */
-       IPSET_ERR_LIST_FULL,
-       /* Reference set is not added to the set */
-       IPSET_ERR_REF_EXIST,
-};
+#include <uapi/linux/netfilter/ipset/ip_set_list.h>
 
-#ifdef __KERNEL__
 
 #define IP_SET_LIST_DEFAULT_SIZE       8
 #define IP_SET_LIST_MIN_SIZE           4
 
-#endif /* __KERNEL__ */
-
 #endif /* __IP_SET_LIST_H */
index d146872a0b91fa2d586991f32452d285b253df15..127d0b90604fa08486a88437fbd9a8e09b315148 100644 (file)
@@ -1,119 +1,8 @@
 #ifndef _NF_CONNTRACK_COMMON_H
 #define _NF_CONNTRACK_COMMON_H
-/* Connection state tracking for netfilter.  This is separated from,
-   but required by, the NAT layer; it can also be used by an iptables
-   extension. */
-enum ip_conntrack_info {
-       /* Part of an established connection (either direction). */
-       IP_CT_ESTABLISHED,
 
-       /* Like NEW, but related to an existing connection, or ICMP error
-          (in either direction). */
-       IP_CT_RELATED,
+#include <uapi/linux/netfilter/nf_conntrack_common.h>
 
-       /* Started a new connection to track (only
-           IP_CT_DIR_ORIGINAL); may be a retransmission. */
-       IP_CT_NEW,
-
-       /* >= this indicates reply direction */
-       IP_CT_IS_REPLY,
-
-       IP_CT_ESTABLISHED_REPLY = IP_CT_ESTABLISHED + IP_CT_IS_REPLY,
-       IP_CT_RELATED_REPLY = IP_CT_RELATED + IP_CT_IS_REPLY,
-       IP_CT_NEW_REPLY = IP_CT_NEW + IP_CT_IS_REPLY,   
-       /* Number of distinct IP_CT types (no NEW in reply dirn). */
-       IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1
-};
-
-/* Bitset representing status of connection. */
-enum ip_conntrack_status {
-       /* It's an expected connection: bit 0 set.  This bit never changed */
-       IPS_EXPECTED_BIT = 0,
-       IPS_EXPECTED = (1 << IPS_EXPECTED_BIT),
-
-       /* We've seen packets both ways: bit 1 set.  Can be set, not unset. */
-       IPS_SEEN_REPLY_BIT = 1,
-       IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT),
-
-       /* Conntrack should never be early-expired. */
-       IPS_ASSURED_BIT = 2,
-       IPS_ASSURED = (1 << IPS_ASSURED_BIT),
-
-       /* Connection is confirmed: originating packet has left box */
-       IPS_CONFIRMED_BIT = 3,
-       IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
-
-       /* Connection needs src nat in orig dir.  This bit never changed. */
-       IPS_SRC_NAT_BIT = 4,
-       IPS_SRC_NAT = (1 << IPS_SRC_NAT_BIT),
-
-       /* Connection needs dst nat in orig dir.  This bit never changed. */
-       IPS_DST_NAT_BIT = 5,
-       IPS_DST_NAT = (1 << IPS_DST_NAT_BIT),
-
-       /* Both together. */
-       IPS_NAT_MASK = (IPS_DST_NAT | IPS_SRC_NAT),
-
-       /* Connection needs TCP sequence adjusted. */
-       IPS_SEQ_ADJUST_BIT = 6,
-       IPS_SEQ_ADJUST = (1 << IPS_SEQ_ADJUST_BIT),
-
-       /* NAT initialization bits. */
-       IPS_SRC_NAT_DONE_BIT = 7,
-       IPS_SRC_NAT_DONE = (1 << IPS_SRC_NAT_DONE_BIT),
-
-       IPS_DST_NAT_DONE_BIT = 8,
-       IPS_DST_NAT_DONE = (1 << IPS_DST_NAT_DONE_BIT),
-
-       /* Both together */
-       IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE),
-
-       /* Connection is dying (removed from lists), can not be unset. */
-       IPS_DYING_BIT = 9,
-       IPS_DYING = (1 << IPS_DYING_BIT),
-
-       /* Connection has fixed timeout. */
-       IPS_FIXED_TIMEOUT_BIT = 10,
-       IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
-
-       /* Conntrack is a template */
-       IPS_TEMPLATE_BIT = 11,
-       IPS_TEMPLATE = (1 << IPS_TEMPLATE_BIT),
-
-       /* Conntrack is a fake untracked entry */
-       IPS_UNTRACKED_BIT = 12,
-       IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT),
-
-       /* Conntrack got a helper explicitly attached via CT target. */
-       IPS_HELPER_BIT = 13,
-       IPS_HELPER = (1 << IPS_HELPER_BIT),
-};
-
-/* Connection tracking event types */
-enum ip_conntrack_events {
-       IPCT_NEW,               /* new conntrack */
-       IPCT_RELATED,           /* related conntrack */
-       IPCT_DESTROY,           /* destroyed conntrack */
-       IPCT_REPLY,             /* connection has seen two-way traffic */
-       IPCT_ASSURED,           /* connection status has changed to assured */
-       IPCT_PROTOINFO,         /* protocol information has changed */
-       IPCT_HELPER,            /* new helper has been set */
-       IPCT_MARK,              /* new mark has been set */
-       IPCT_NATSEQADJ,         /* NAT is doing sequence adjustment */
-       IPCT_SECMARK,           /* new security mark has been set */
-};
-
-enum ip_conntrack_expect_events {
-       IPEXP_NEW,              /* new expectation */
-       IPEXP_DESTROY,          /* destroyed expectation */
-};
-
-/* expectation flags */
-#define NF_CT_EXPECT_PERMANENT         0x1
-#define NF_CT_EXPECT_INACTIVE          0x2
-#define NF_CT_EXPECT_USERSPACE         0x4
-
-#ifdef __KERNEL__
 struct ip_conntrack_stat {
        unsigned int searched;
        unsigned int found;
@@ -136,6 +25,4 @@ struct ip_conntrack_stat {
 /* call to create an explicit dependency on nf_conntrack. */
 extern void need_conntrack(void);
 
-#endif /* __KERNEL__ */
-
 #endif /* _NF_CONNTRACK_COMMON_H */
index 8faf3f792d13034179d64b82e9ecc57014c6c3bb..5f818b01e0356d7eac8c80762dff87a15483fad8 100644 (file)
@@ -1,20 +1,8 @@
 #ifndef _NF_CONNTRACK_FTP_H
 #define _NF_CONNTRACK_FTP_H
-/* FTP tracking. */
 
-/* This enum is exposed to userspace */
-enum nf_ct_ftp_type {
-       /* PORT command from client */
-       NF_CT_FTP_PORT,
-       /* PASV response from server */
-       NF_CT_FTP_PASV,
-       /* EPRT command from client */
-       NF_CT_FTP_EPRT,
-       /* EPSV response from server */
-       NF_CT_FTP_EPSV,
-};
+#include <uapi/linux/netfilter/nf_conntrack_ftp.h>
 
-#ifdef __KERNEL__
 
 #define FTP_PORT       21
 
@@ -42,6 +30,4 @@ extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb,
                                       unsigned int matchoff,
                                       unsigned int matchlen,
                                       struct nf_conntrack_expect *exp);
-#endif /* __KERNEL__ */
-
 #endif /* _NF_CONNTRACK_FTP_H */
index e59868ae12d42114df83e28f3712bd28de1a4564..22db9614b584ad0d5b6bc174c2eb3613a8b73dfd 100644 (file)
@@ -1,53 +1,8 @@
 #ifndef _NF_CONNTRACK_TCP_H
 #define _NF_CONNTRACK_TCP_H
-/* TCP tracking. */
 
-#include <linux/types.h>
+#include <uapi/linux/netfilter/nf_conntrack_tcp.h>
 
-/* This is exposed to userspace (ctnetlink) */
-enum tcp_conntrack {
-       TCP_CONNTRACK_NONE,
-       TCP_CONNTRACK_SYN_SENT,
-       TCP_CONNTRACK_SYN_RECV,
-       TCP_CONNTRACK_ESTABLISHED,
-       TCP_CONNTRACK_FIN_WAIT,
-       TCP_CONNTRACK_CLOSE_WAIT,
-       TCP_CONNTRACK_LAST_ACK,
-       TCP_CONNTRACK_TIME_WAIT,
-       TCP_CONNTRACK_CLOSE,
-       TCP_CONNTRACK_LISTEN,   /* obsolete */
-#define TCP_CONNTRACK_SYN_SENT2        TCP_CONNTRACK_LISTEN
-       TCP_CONNTRACK_MAX,
-       TCP_CONNTRACK_IGNORE,
-       TCP_CONNTRACK_RETRANS,
-       TCP_CONNTRACK_UNACK,
-       TCP_CONNTRACK_TIMEOUT_MAX
-};
-
-/* Window scaling is advertised by the sender */
-#define IP_CT_TCP_FLAG_WINDOW_SCALE            0x01
-
-/* SACK is permitted by the sender */
-#define IP_CT_TCP_FLAG_SACK_PERM               0x02
-
-/* This sender sent FIN first */
-#define IP_CT_TCP_FLAG_CLOSE_INIT              0x04
-
-/* Be liberal in window checking */
-#define IP_CT_TCP_FLAG_BE_LIBERAL              0x08
-
-/* Has unacknowledged data */
-#define IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED     0x10
-
-/* The field td_maxack has been set */
-#define IP_CT_TCP_FLAG_MAXACK_SET              0x20
-
-struct nf_ct_tcp_flags {
-       __u8 flags;
-       __u8 mask;
-};
-
-#ifdef __KERNEL__
 
 struct ip_ct_tcp_state {
        u_int32_t       td_end;         /* max of seq + len */
@@ -74,6 +29,4 @@ struct ip_ct_tcp {
        u_int8_t        last_flags;     /* Last flags set */
 };
 
-#endif /* __KERNEL__ */
-
 #endif /* _NF_CONNTRACK_TCP_H */
index 18341cdb2443816f5e3af91e0d42d49a57cb36ad..4966ddec039bf4db67295cba66bc767de7063d69 100644 (file)
@@ -1,63 +1,11 @@
 #ifndef _NFNETLINK_H
 #define _NFNETLINK_H
-#include <linux/types.h>
-#include <linux/netfilter/nfnetlink_compat.h>
 
-enum nfnetlink_groups {
-       NFNLGRP_NONE,
-#define NFNLGRP_NONE                   NFNLGRP_NONE
-       NFNLGRP_CONNTRACK_NEW,
-#define NFNLGRP_CONNTRACK_NEW          NFNLGRP_CONNTRACK_NEW
-       NFNLGRP_CONNTRACK_UPDATE,
-#define NFNLGRP_CONNTRACK_UPDATE       NFNLGRP_CONNTRACK_UPDATE
-       NFNLGRP_CONNTRACK_DESTROY,
-#define NFNLGRP_CONNTRACK_DESTROY      NFNLGRP_CONNTRACK_DESTROY
-       NFNLGRP_CONNTRACK_EXP_NEW,
-#define        NFNLGRP_CONNTRACK_EXP_NEW       NFNLGRP_CONNTRACK_EXP_NEW
-       NFNLGRP_CONNTRACK_EXP_UPDATE,
-#define NFNLGRP_CONNTRACK_EXP_UPDATE   NFNLGRP_CONNTRACK_EXP_UPDATE
-       NFNLGRP_CONNTRACK_EXP_DESTROY,
-#define NFNLGRP_CONNTRACK_EXP_DESTROY  NFNLGRP_CONNTRACK_EXP_DESTROY
-       __NFNLGRP_MAX,
-};
-#define NFNLGRP_MAX    (__NFNLGRP_MAX - 1)
-
-/* General form of address family dependent message.
- */
-struct nfgenmsg {
-       __u8  nfgen_family;             /* AF_xxx */
-       __u8  version;          /* nfnetlink version */
-       __be16    res_id;               /* resource id */
-};
-
-#define NFNETLINK_V0   0
-
-/* netfilter netlink message types are split in two pieces:
- * 8 bit subsystem, 8bit operation.
- */
-
-#define NFNL_SUBSYS_ID(x)      ((x & 0xff00) >> 8)
-#define NFNL_MSG_TYPE(x)       (x & 0x00ff)
-
-/* No enum here, otherwise __stringify() trick of MODULE_ALIAS_NFNL_SUBSYS()
- * won't work anymore */
-#define NFNL_SUBSYS_NONE               0
-#define NFNL_SUBSYS_CTNETLINK          1
-#define NFNL_SUBSYS_CTNETLINK_EXP      2
-#define NFNL_SUBSYS_QUEUE              3
-#define NFNL_SUBSYS_ULOG               4
-#define NFNL_SUBSYS_OSF                        5
-#define NFNL_SUBSYS_IPSET              6
-#define NFNL_SUBSYS_ACCT               7
-#define NFNL_SUBSYS_CTNETLINK_TIMEOUT  8
-#define NFNL_SUBSYS_CTHELPER           9
-#define NFNL_SUBSYS_COUNT              10
-
-#ifdef __KERNEL__
 
 #include <linux/netlink.h>
 #include <linux/capability.h>
 #include <net/netlink.h>
+#include <uapi/linux/netfilter/nfnetlink.h>
 
 struct nfnl_callback {
        int (*call)(struct sock *nl, struct sk_buff *skb, 
@@ -92,5 +40,4 @@ extern void nfnl_unlock(void);
 #define MODULE_ALIAS_NFNL_SUBSYS(subsys) \
        MODULE_ALIAS("nfnetlink-subsys-" __stringify(subsys))
 
-#endif /* __KERNEL__ */
 #endif /* _NFNETLINK_H */
index 7c4279b4ae7a9a2ccc95289e52ce65d97db30865..bb4bbc9b7a18c4834724eabe574b76670806c8c4 100644 (file)
@@ -1,29 +1,8 @@
 #ifndef _NFNL_ACCT_H_
 #define _NFNL_ACCT_H_
 
-#ifndef NFACCT_NAME_MAX
-#define NFACCT_NAME_MAX                32
-#endif
+#include <uapi/linux/netfilter/nfnetlink_acct.h>
 
-enum nfnl_acct_msg_types {
-       NFNL_MSG_ACCT_NEW,
-       NFNL_MSG_ACCT_GET,
-       NFNL_MSG_ACCT_GET_CTRZERO,
-       NFNL_MSG_ACCT_DEL,
-       NFNL_MSG_ACCT_MAX
-};
-
-enum nfnl_acct_type {
-       NFACCT_UNSPEC,
-       NFACCT_NAME,
-       NFACCT_PKTS,
-       NFACCT_BYTES,
-       NFACCT_USE,
-       __NFACCT_MAX
-};
-#define NFACCT_MAX (__NFACCT_MAX - 1)
-
-#ifdef __KERNEL__
 
 struct nf_acct;
 
@@ -31,6 +10,4 @@ extern struct nf_acct *nfnl_acct_find_get(const char *filter_name);
 extern void nfnl_acct_put(struct nf_acct *acct);
 extern void nfnl_acct_update(const struct sk_buff *skb, struct nf_acct *nfacct);
 
-#endif /* __KERNEL__ */
-
 #endif /* _NFNL_ACCT_H */
index 8d674a78674461c44422ed67bf45a59be270d198..dd49566315c616f1d4db4cba47ee1dc9ecaefa26 100644 (file)
@@ -1,191 +1,9 @@
 #ifndef _X_TABLES_H
 #define _X_TABLES_H
-#include <linux/kernel.h>
-#include <linux/types.h>
 
-#define XT_FUNCTION_MAXNAMELEN 30
-#define XT_EXTENSION_MAXNAMELEN 29
-#define XT_TABLE_MAXNAMELEN 32
-
-struct xt_entry_match {
-       union {
-               struct {
-                       __u16 match_size;
-
-                       /* Used by userspace */
-                       char name[XT_EXTENSION_MAXNAMELEN];
-                       __u8 revision;
-               } user;
-               struct {
-                       __u16 match_size;
-
-                       /* Used inside the kernel */
-                       struct xt_match *match;
-               } kernel;
-
-               /* Total length */
-               __u16 match_size;
-       } u;
-
-       unsigned char data[0];
-};
-
-struct xt_entry_target {
-       union {
-               struct {
-                       __u16 target_size;
-
-                       /* Used by userspace */
-                       char name[XT_EXTENSION_MAXNAMELEN];
-                       __u8 revision;
-               } user;
-               struct {
-                       __u16 target_size;
-
-                       /* Used inside the kernel */
-                       struct xt_target *target;
-               } kernel;
-
-               /* Total length */
-               __u16 target_size;
-       } u;
-
-       unsigned char data[0];
-};
-
-#define XT_TARGET_INIT(__name, __size)                                        \
-{                                                                             \
-       .target.u.user = {                                                     \
-               .target_size    = XT_ALIGN(__size),                            \
-               .name           = __name,                                      \
-       },                                                                     \
-}
-
-struct xt_standard_target {
-       struct xt_entry_target target;
-       int verdict;
-};
-
-struct xt_error_target {
-       struct xt_entry_target target;
-       char errorname[XT_FUNCTION_MAXNAMELEN];
-};
-
-/* The argument to IPT_SO_GET_REVISION_*.  Returns highest revision
- * kernel supports, if >= revision. */
-struct xt_get_revision {
-       char name[XT_EXTENSION_MAXNAMELEN];
-       __u8 revision;
-};
-
-/* CONTINUE verdict for targets */
-#define XT_CONTINUE 0xFFFFFFFF
-
-/* For standard target */
-#define XT_RETURN (-NF_REPEAT - 1)
-
-/* this is a dummy structure to find out the alignment requirement for a struct
- * containing all the fundamental data types that are used in ipt_entry,
- * ip6t_entry and arpt_entry.  This sucks, and it is a hack.  It will be my
- * personal pleasure to remove it -HW
- */
-struct _xt_align {
-       __u8 u8;
-       __u16 u16;
-       __u32 u32;
-       __u64 u64;
-};
-
-#define XT_ALIGN(s) __ALIGN_KERNEL((s), __alignof__(struct _xt_align))
-
-/* Standard return verdict, or do jump. */
-#define XT_STANDARD_TARGET ""
-/* Error verdict. */
-#define XT_ERROR_TARGET "ERROR"
-
-#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0)
-#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
-
-struct xt_counters {
-       __u64 pcnt, bcnt;                       /* Packet and byte counters */
-};
-
-/* The argument to IPT_SO_ADD_COUNTERS. */
-struct xt_counters_info {
-       /* Which table. */
-       char name[XT_TABLE_MAXNAMELEN];
-
-       unsigned int num_counters;
-
-       /* The counters (actually `number' of these). */
-       struct xt_counters counters[0];
-};
-
-#define XT_INV_PROTO           0x40    /* Invert the sense of PROTO. */
-
-#ifndef __KERNEL__
-/* fn returns 0 to continue iteration */
-#define XT_MATCH_ITERATE(type, e, fn, args...)                 \
-({                                                             \
-       unsigned int __i;                                       \
-       int __ret = 0;                                          \
-       struct xt_entry_match *__m;                             \
-                                                               \
-       for (__i = sizeof(type);                                \
-            __i < (e)->target_offset;                          \
-            __i += __m->u.match_size) {                        \
-               __m = (void *)e + __i;                          \
-                                                               \
-               __ret = fn(__m , ## args);                      \
-               if (__ret != 0)                                 \
-                       break;                                  \
-       }                                                       \
-       __ret;                                                  \
-})
-
-/* fn returns 0 to continue iteration */
-#define XT_ENTRY_ITERATE_CONTINUE(type, entries, size, n, fn, args...) \
-({                                                             \
-       unsigned int __i, __n;                                  \
-       int __ret = 0;                                          \
-       type *__entry;                                          \
-                                                               \
-       for (__i = 0, __n = 0; __i < (size);                    \
-            __i += __entry->next_offset, __n++) {              \
-               __entry = (void *)(entries) + __i;              \
-               if (__n < n)                                    \
-                       continue;                               \
-                                                               \
-               __ret = fn(__entry , ## args);                  \
-               if (__ret != 0)                                 \
-                       break;                                  \
-       }                                                       \
-       __ret;                                                  \
-})
-
-/* fn returns 0 to continue iteration */
-#define XT_ENTRY_ITERATE(type, entries, size, fn, args...) \
-       XT_ENTRY_ITERATE_CONTINUE(type, entries, size, 0, fn, args)
-
-#endif /* !__KERNEL__ */
-
-/* pos is normally a struct ipt_entry/ip6t_entry/etc. */
-#define xt_entry_foreach(pos, ehead, esize) \
-       for ((pos) = (typeof(pos))(ehead); \
-            (pos) < (typeof(pos))((char *)(ehead) + (esize)); \
-            (pos) = (typeof(pos))((char *)(pos) + (pos)->next_offset))
-
-/* can only be xt_entry_match, so no use of typeof here */
-#define xt_ematch_foreach(pos, entry) \
-       for ((pos) = (struct xt_entry_match *)entry->elems; \
-            (pos) < (struct xt_entry_match *)((char *)(entry) + \
-                    (entry)->target_offset); \
-            (pos) = (struct xt_entry_match *)((char *)(pos) + \
-                    (pos)->u.match_size))
-
-#ifdef __KERNEL__
 
 #include <linux/netdevice.h>
+#include <uapi/linux/netfilter/x_tables.h>
 
 /**
  * struct xt_action_param - parameters for matches/targets
@@ -617,6 +435,4 @@ extern int xt_compat_target_to_user(const struct xt_entry_target *t,
                                    void __user **dstptr, unsigned int *size);
 
 #endif /* CONFIG_COMPAT */
-#endif /* __KERNEL__ */
-
 #endif /* _X_TABLES_H */
index c42e52f39f8fa57b0bf8d541ee295fd15821e0f2..074790c0cf74e78b542e0eaaf0aaca907e6c2d54 100644 (file)
@@ -1,78 +1,9 @@
 #ifndef _XT_HASHLIMIT_H
 #define _XT_HASHLIMIT_H
 
-#include <linux/types.h>
+#include <uapi/linux/netfilter/xt_hashlimit.h>
 
-/* timings are in milliseconds. */
-#define XT_HASHLIMIT_SCALE 10000
-/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
- * seconds, or one packet every 59 hours.
- */
-
-/* packet length accounting is done in 16-byte steps */
-#define XT_HASHLIMIT_BYTE_SHIFT 4
-
-/* details of this structure hidden by the implementation */
-struct xt_hashlimit_htable;
-
-enum {
-       XT_HASHLIMIT_HASH_DIP = 1 << 0,
-       XT_HASHLIMIT_HASH_DPT = 1 << 1,
-       XT_HASHLIMIT_HASH_SIP = 1 << 2,
-       XT_HASHLIMIT_HASH_SPT = 1 << 3,
-       XT_HASHLIMIT_INVERT   = 1 << 4,
-       XT_HASHLIMIT_BYTES    = 1 << 5,
-};
-#ifdef __KERNEL__
 #define XT_HASHLIMIT_ALL (XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT | \
                          XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT | \
                          XT_HASHLIMIT_INVERT | XT_HASHLIMIT_BYTES)
-#endif
-
-struct hashlimit_cfg {
-       __u32 mode;       /* bitmask of XT_HASHLIMIT_HASH_* */
-       __u32 avg;    /* Average secs between packets * scale */
-       __u32 burst;  /* Period multiplier for upper limit. */
-
-       /* user specified */
-       __u32 size;             /* how many buckets */
-       __u32 max;              /* max number of entries */
-       __u32 gc_interval;      /* gc interval */
-       __u32 expire;   /* when do entries expire? */
-};
-
-struct xt_hashlimit_info {
-       char name [IFNAMSIZ];           /* name */
-       struct hashlimit_cfg cfg;
-
-       /* Used internally by the kernel */
-       struct xt_hashlimit_htable *hinfo;
-       union {
-               void *ptr;
-               struct xt_hashlimit_info *master;
-       } u;
-};
-
-struct hashlimit_cfg1 {
-       __u32 mode;       /* bitmask of XT_HASHLIMIT_HASH_* */
-       __u32 avg;    /* Average secs between packets * scale */
-       __u32 burst;  /* Period multiplier for upper limit. */
-
-       /* user specified */
-       __u32 size;             /* how many buckets */
-       __u32 max;              /* max number of entries */
-       __u32 gc_interval;      /* gc interval */
-       __u32 expire;   /* when do entries expire? */
-
-       __u8 srcmask, dstmask;
-};
-
-struct xt_hashlimit_mtinfo1 {
-       char name[IFNAMSIZ];
-       struct hashlimit_cfg1 cfg;
-
-       /* Used internally by the kernel */
-       struct xt_hashlimit_htable *hinfo __attribute__((aligned(8)));
-};
-
 #endif /*_XT_HASHLIMIT_H*/
index 8555e399886d09259fe8d8daa1e688a063983499..5b5e41716d693d267bdb9484f463615d833f5ec5 100644 (file)
@@ -1,26 +1,7 @@
 #ifndef _XT_PHYSDEV_H
 #define _XT_PHYSDEV_H
 
-#include <linux/types.h>
-
-#ifdef __KERNEL__
 #include <linux/if.h>
-#endif
-
-#define XT_PHYSDEV_OP_IN               0x01
-#define XT_PHYSDEV_OP_OUT              0x02
-#define XT_PHYSDEV_OP_BRIDGED          0x04
-#define XT_PHYSDEV_OP_ISIN             0x08
-#define XT_PHYSDEV_OP_ISOUT            0x10
-#define XT_PHYSDEV_OP_MASK             (0x20 - 1)
-
-struct xt_physdev_info {
-       char physindev[IFNAMSIZ];
-       char in_mask[IFNAMSIZ];
-       char physoutdev[IFNAMSIZ];
-       char out_mask[IFNAMSIZ];
-       __u8 invert;
-       __u8 bitmask;
-};
+#include <uapi/linux/netfilter/xt_physdev.h>
 
 #endif /*_XT_PHYSDEV_H*/
index b27439c71037df54ac3c7384acb6da7065c98fcf..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,2 +0,0 @@
-header-y += arp_tables.h
-header-y += arpt_mangle.h
index e08565d45178435a73fdfb58e60081effa365782..cfb7191e6efa55633dfa8eb52855e6248ccb3d4f 100644 (file)
  *     network byte order.
  *     flags are stored in host byte order (of course).
  */
-
 #ifndef _ARPTABLES_H
 #define _ARPTABLES_H
 
-#ifdef __KERNEL__
 #include <linux/if.h>
 #include <linux/in.h>
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
-#endif
-#include <linux/types.h>
-#include <linux/compiler.h>
-#include <linux/netfilter_arp.h>
-
-#include <linux/netfilter/x_tables.h>
-
-#ifndef __KERNEL__
-#define ARPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
-#define ARPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
-#define arpt_entry_target xt_entry_target
-#define arpt_standard_target xt_standard_target
-#define arpt_error_target xt_error_target
-#define ARPT_CONTINUE XT_CONTINUE
-#define ARPT_RETURN XT_RETURN
-#define arpt_counters_info xt_counters_info
-#define arpt_counters xt_counters
-#define ARPT_STANDARD_TARGET XT_STANDARD_TARGET
-#define ARPT_ERROR_TARGET XT_ERROR_TARGET
-#define ARPT_ENTRY_ITERATE(entries, size, fn, args...) \
-       XT_ENTRY_ITERATE(struct arpt_entry, entries, size, fn, ## args)
-#endif
-
-#define ARPT_DEV_ADDR_LEN_MAX 16
-
-struct arpt_devaddr_info {
-       char addr[ARPT_DEV_ADDR_LEN_MAX];
-       char mask[ARPT_DEV_ADDR_LEN_MAX];
-};
-
-/* Yes, Virginia, you have to zero the padding. */
-struct arpt_arp {
-       /* Source and target IP addr */
-       struct in_addr src, tgt;
-       /* Mask for src and target IP addr */
-       struct in_addr smsk, tmsk;
-
-       /* Device hw address length, src+target device addresses */
-       __u8 arhln, arhln_mask;
-       struct arpt_devaddr_info src_devaddr;
-       struct arpt_devaddr_info tgt_devaddr;
-
-       /* ARP operation code. */
-       __be16 arpop, arpop_mask;
-
-       /* ARP hardware address and protocol address format. */
-       __be16 arhrd, arhrd_mask;
-       __be16 arpro, arpro_mask;
-
-       /* The protocol address length is only accepted if it is 4
-        * so there is no use in offering a way to do filtering on it.
-        */
-
-       char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
-       unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
-
-       /* Flags word */
-       __u8 flags;
-       /* Inverse flags */
-       __u16 invflags;
-};
-
-/* Values for "flag" field in struct arpt_ip (general arp structure).
- * No flags defined yet.
- */
-#define ARPT_F_MASK            0x00    /* All possible flag bits mask. */
-
-/* Values for "inv" field in struct arpt_arp. */
-#define ARPT_INV_VIA_IN                0x0001  /* Invert the sense of IN IFACE. */
-#define ARPT_INV_VIA_OUT       0x0002  /* Invert the sense of OUT IFACE */
-#define ARPT_INV_SRCIP         0x0004  /* Invert the sense of SRC IP. */
-#define ARPT_INV_TGTIP         0x0008  /* Invert the sense of TGT IP. */
-#define ARPT_INV_SRCDEVADDR    0x0010  /* Invert the sense of SRC DEV ADDR. */
-#define ARPT_INV_TGTDEVADDR    0x0020  /* Invert the sense of TGT DEV ADDR. */
-#define ARPT_INV_ARPOP         0x0040  /* Invert the sense of ARP OP. */
-#define ARPT_INV_ARPHRD                0x0080  /* Invert the sense of ARP HRD. */
-#define ARPT_INV_ARPPRO                0x0100  /* Invert the sense of ARP PRO. */
-#define ARPT_INV_ARPHLN                0x0200  /* Invert the sense of ARP HLN. */
-#define ARPT_INV_MASK          0x03FF  /* All possible flag bits mask. */
-
-/* This structure defines each of the firewall rules.  Consists of 3
-   parts which are 1) general ARP header stuff 2) match specific
-   stuff 3) the target to perform if the rule matches */
-struct arpt_entry
-{
-       struct arpt_arp arp;
-
-       /* Size of arpt_entry + matches */
-       __u16 target_offset;
-       /* Size of arpt_entry + matches + target */
-       __u16 next_offset;
-
-       /* Back pointer */
-       unsigned int comefrom;
-
-       /* Packet and byte counters. */
-       struct xt_counters counters;
-
-       /* The matches (if any), then the target. */
-       unsigned char elems[0];
-};
-
-/*
- * New IP firewall options for [gs]etsockopt at the RAW IP level.
- * Unlike BSD Linux inherits IP options so you don't have to use a raw
- * socket for this. Instead we check rights in the calls.
- *
- * ATTENTION: check linux/in.h before adding new number here.
- */
-#define ARPT_BASE_CTL          96
-
-#define ARPT_SO_SET_REPLACE            (ARPT_BASE_CTL)
-#define ARPT_SO_SET_ADD_COUNTERS       (ARPT_BASE_CTL + 1)
-#define ARPT_SO_SET_MAX                        ARPT_SO_SET_ADD_COUNTERS
-
-#define ARPT_SO_GET_INFO               (ARPT_BASE_CTL)
-#define ARPT_SO_GET_ENTRIES            (ARPT_BASE_CTL + 1)
-/* #define ARPT_SO_GET_REVISION_MATCH  (APRT_BASE_CTL + 2) */
-#define ARPT_SO_GET_REVISION_TARGET    (ARPT_BASE_CTL + 3)
-#define ARPT_SO_GET_MAX                        (ARPT_SO_GET_REVISION_TARGET)
-
-/* The argument to ARPT_SO_GET_INFO */
-struct arpt_getinfo {
-       /* Which table: caller fills this in. */
-       char name[XT_TABLE_MAXNAMELEN];
-
-       /* Kernel fills these in. */
-       /* Which hook entry points are valid: bitmask */
-       unsigned int valid_hooks;
-
-       /* Hook entry points: one per netfilter hook. */
-       unsigned int hook_entry[NF_ARP_NUMHOOKS];
-
-       /* Underflow points. */
-       unsigned int underflow[NF_ARP_NUMHOOKS];
-
-       /* Number of entries */
-       unsigned int num_entries;
-
-       /* Size of entries. */
-       unsigned int size;
-};
-
-/* The argument to ARPT_SO_SET_REPLACE. */
-struct arpt_replace {
-       /* Which table. */
-       char name[XT_TABLE_MAXNAMELEN];
-
-       /* Which hook entry points are valid: bitmask.  You can't
-           change this. */
-       unsigned int valid_hooks;
-
-       /* Number of entries */
-       unsigned int num_entries;
-
-       /* Total size of new entries */
-       unsigned int size;
-
-       /* Hook entry points. */
-       unsigned int hook_entry[NF_ARP_NUMHOOKS];
-
-       /* Underflow points. */
-       unsigned int underflow[NF_ARP_NUMHOOKS];
-
-       /* Information about old entries: */
-       /* Number of counters (must be equal to current number of entries). */
-       unsigned int num_counters;
-       /* The old entries' counters. */
-       struct xt_counters __user *counters;
-
-       /* The entries (hang off end: not really an array). */
-       struct arpt_entry entries[0];
-};
-
-/* The argument to ARPT_SO_GET_ENTRIES. */
-struct arpt_get_entries {
-       /* Which table: user fills this in. */
-       char name[XT_TABLE_MAXNAMELEN];
-
-       /* User fills this in: total entry size. */
-       unsigned int size;
-
-       /* The entries. */
-       struct arpt_entry entrytable[0];
-};
-
-/* Helper functions */
-static __inline__ struct xt_entry_target *arpt_get_target(struct arpt_entry *e)
-{
-       return (void *)e + e->target_offset;
-}
-
-/*
- *     Main firewall chains definitions and global var's definitions.
- */
-#ifdef __KERNEL__
+#include <uapi/linux/netfilter_arp/arp_tables.h>
 
 /* Standard entry. */
 struct arpt_standard {
@@ -274,5 +77,4 @@ compat_arpt_get_target(struct compat_arpt_entry *e)
 }
 
 #endif /* CONFIG_COMPAT */
-#endif /*__KERNEL__*/
 #endif /* _ARPTABLES_H */
index e48f1a3f5a4affda5e9ee3f39fe6709c893dfd7c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,18 +0,0 @@
-header-y += ebt_802_3.h
-header-y += ebt_among.h
-header-y += ebt_arp.h
-header-y += ebt_arpreply.h
-header-y += ebt_ip.h
-header-y += ebt_ip6.h
-header-y += ebt_limit.h
-header-y += ebt_log.h
-header-y += ebt_mark_m.h
-header-y += ebt_mark_t.h
-header-y += ebt_nat.h
-header-y += ebt_nflog.h
-header-y += ebt_pkttype.h
-header-y += ebt_redirect.h
-header-y += ebt_stp.h
-header-y += ebt_ulog.h
-header-y += ebt_vlan.h
-header-y += ebtables.h
index be5be1577a56e28797db0817579ac22adc22e1e9..e17e8bfb4e8beba6e72ce72ec161528d5468ae32 100644 (file)
@@ -1,70 +1,11 @@
 #ifndef __LINUX_BRIDGE_EBT_802_3_H
 #define __LINUX_BRIDGE_EBT_802_3_H
 
-#include <linux/types.h>
-
-#define EBT_802_3_SAP 0x01
-#define EBT_802_3_TYPE 0x02
-
-#define EBT_802_3_MATCH "802_3"
-
-/*
- * If frame has DSAP/SSAP value 0xaa you must check the SNAP type
- * to discover what kind of packet we're carrying. 
- */
-#define CHECK_TYPE 0xaa
-
-/*
- * Control field may be one or two bytes.  If the first byte has
- * the value 0x03 then the entire length is one byte, otherwise it is two.
- * One byte controls are used in Unnumbered Information frames.
- * Two byte controls are used in Numbered Information frames.
- */
-#define IS_UI 0x03
-
-#define EBT_802_3_MASK (EBT_802_3_SAP | EBT_802_3_TYPE | EBT_802_3)
-
-/* ui has one byte ctrl, ni has two */
-struct hdr_ui {
-       __u8 dsap;
-       __u8 ssap;
-       __u8 ctrl;
-       __u8 orig[3];
-       __be16 type;
-};
-
-struct hdr_ni {
-       __u8 dsap;
-       __u8 ssap;
-       __be16 ctrl;
-       __u8  orig[3];
-       __be16 type;
-};
-
-struct ebt_802_3_hdr {
-       __u8  daddr[6];
-       __u8  saddr[6];
-       __be16 len;
-       union {
-               struct hdr_ui ui;
-               struct hdr_ni ni;
-       } llc;
-};
-
-#ifdef __KERNEL__
 #include <linux/skbuff.h>
+#include <uapi/linux/netfilter_bridge/ebt_802_3.h>
 
 static inline struct ebt_802_3_hdr *ebt_802_3_hdr(const struct sk_buff *skb)
 {
        return (struct ebt_802_3_hdr *)skb_mac_header(skb);
 }
 #endif
-
-struct ebt_802_3_info {
-       __u8  sap;
-       __be16 type;
-       __u8  bitmask;
-       __u8  invflags;
-};
-
-#endif
index 4dd5bd6994a8f7397d65f2b6426c9d27a17c1828..34e7a2b7f8677f9f923fd48a366e09e5d4d643ee 100644 (file)
  *  This code is stongly inspired on the iptables code which is
  *  Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
  */
-
 #ifndef __LINUX_BRIDGE_EFF_H
 #define __LINUX_BRIDGE_EFF_H
-#include <linux/if.h>
-#include <linux/netfilter_bridge.h>
-#include <linux/if_ether.h>
-
-#define EBT_TABLE_MAXNAMELEN 32
-#define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN
-#define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN
-
-/* verdicts >0 are "branches" */
-#define EBT_ACCEPT   -1
-#define EBT_DROP     -2
-#define EBT_CONTINUE -3
-#define EBT_RETURN   -4
-#define NUM_STANDARD_TARGETS   4
-/* ebtables target modules store the verdict inside an int. We can
- * reclaim a part of this int for backwards compatible extensions.
- * The 4 lsb are more than enough to store the verdict. */
-#define EBT_VERDICT_BITS 0x0000000F
-
-struct xt_match;
-struct xt_target;
-
-struct ebt_counter {
-       uint64_t pcnt;
-       uint64_t bcnt;
-};
 
-struct ebt_replace {
-       char name[EBT_TABLE_MAXNAMELEN];
-       unsigned int valid_hooks;
-       /* nr of rules in the table */
-       unsigned int nentries;
-       /* total size of the entries */
-       unsigned int entries_size;
-       /* start of the chains */
-       struct ebt_entries __user *hook_entry[NF_BR_NUMHOOKS];
-       /* nr of counters userspace expects back */
-       unsigned int num_counters;
-       /* where the kernel will put the old counters */
-       struct ebt_counter __user *counters;
-       char __user *entries;
-};
+#include <uapi/linux/netfilter_bridge/ebtables.h>
 
-struct ebt_replace_kernel {
-       char name[EBT_TABLE_MAXNAMELEN];
-       unsigned int valid_hooks;
-       /* nr of rules in the table */
-       unsigned int nentries;
-       /* total size of the entries */
-       unsigned int entries_size;
-       /* start of the chains */
-       struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
-       /* nr of counters userspace expects back */
-       unsigned int num_counters;
-       /* where the kernel will put the old counters */
-       struct ebt_counter *counters;
-       char *entries;
-};
-
-struct ebt_entries {
-       /* this field is always set to zero
-        * See EBT_ENTRY_OR_ENTRIES.
-        * Must be same size as ebt_entry.bitmask */
-       unsigned int distinguisher;
-       /* the chain name */
-       char name[EBT_CHAIN_MAXNAMELEN];
-       /* counter offset for this chain */
-       unsigned int counter_offset;
-       /* one standard (accept, drop, return) per hook */
-       int policy;
-       /* nr. of entries */
-       unsigned int nentries;
-       /* entry list */
-       char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
-};
-
-/* used for the bitmask of struct ebt_entry */
-
-/* This is a hack to make a difference between an ebt_entry struct and an
- * ebt_entries struct when traversing the entries from start to end.
- * Using this simplifies the code a lot, while still being able to use
- * ebt_entries.
- * Contrary, iptables doesn't use something like ebt_entries and therefore uses
- * different techniques for naming the policy and such. So, iptables doesn't
- * need a hack like this.
- */
-#define EBT_ENTRY_OR_ENTRIES 0x01
-/* these are the normal masks */
-#define EBT_NOPROTO 0x02
-#define EBT_802_3 0x04
-#define EBT_SOURCEMAC 0x08
-#define EBT_DESTMAC 0x10
-#define EBT_F_MASK (EBT_NOPROTO | EBT_802_3 | EBT_SOURCEMAC | EBT_DESTMAC \
-   | EBT_ENTRY_OR_ENTRIES)
-
-#define EBT_IPROTO 0x01
-#define EBT_IIN 0x02
-#define EBT_IOUT 0x04
-#define EBT_ISOURCE 0x8
-#define EBT_IDEST 0x10
-#define EBT_ILOGICALIN 0x20
-#define EBT_ILOGICALOUT 0x40
-#define EBT_INV_MASK (EBT_IPROTO | EBT_IIN | EBT_IOUT | EBT_ILOGICALIN \
-   | EBT_ILOGICALOUT | EBT_ISOURCE | EBT_IDEST)
-
-struct ebt_entry_match {
-       union {
-               char name[EBT_FUNCTION_MAXNAMELEN];
-               struct xt_match *match;
-       } u;
-       /* size of data */
-       unsigned int match_size;
-       unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
-};
-
-struct ebt_entry_watcher {
-       union {
-               char name[EBT_FUNCTION_MAXNAMELEN];
-               struct xt_target *watcher;
-       } u;
-       /* size of data */
-       unsigned int watcher_size;
-       unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
-};
-
-struct ebt_entry_target {
-       union {
-               char name[EBT_FUNCTION_MAXNAMELEN];
-               struct xt_target *target;
-       } u;
-       /* size of data */
-       unsigned int target_size;
-       unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
-};
-
-#define EBT_STANDARD_TARGET "standard"
-struct ebt_standard_target {
-       struct ebt_entry_target target;
-       int verdict;
-};
-
-/* one entry */
-struct ebt_entry {
-       /* this needs to be the first field */
-       unsigned int bitmask;
-       unsigned int invflags;
-       __be16 ethproto;
-       /* the physical in-dev */
-       char in[IFNAMSIZ];
-       /* the logical in-dev */
-       char logical_in[IFNAMSIZ];
-       /* the physical out-dev */
-       char out[IFNAMSIZ];
-       /* the logical out-dev */
-       char logical_out[IFNAMSIZ];
-       unsigned char sourcemac[ETH_ALEN];
-       unsigned char sourcemsk[ETH_ALEN];
-       unsigned char destmac[ETH_ALEN];
-       unsigned char destmsk[ETH_ALEN];
-       /* sizeof ebt_entry + matches */
-       unsigned int watchers_offset;
-       /* sizeof ebt_entry + matches + watchers */
-       unsigned int target_offset;
-       /* sizeof ebt_entry + matches + watchers + target */
-       unsigned int next_offset;
-       unsigned char elems[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
-};
-
-/* {g,s}etsockopt numbers */
-#define EBT_BASE_CTL            128
-
-#define EBT_SO_SET_ENTRIES      (EBT_BASE_CTL)
-#define EBT_SO_SET_COUNTERS     (EBT_SO_SET_ENTRIES+1)
-#define EBT_SO_SET_MAX          (EBT_SO_SET_COUNTERS+1)
-
-#define EBT_SO_GET_INFO         (EBT_BASE_CTL)
-#define EBT_SO_GET_ENTRIES      (EBT_SO_GET_INFO+1)
-#define EBT_SO_GET_INIT_INFO    (EBT_SO_GET_ENTRIES+1)
-#define EBT_SO_GET_INIT_ENTRIES (EBT_SO_GET_INIT_INFO+1)
-#define EBT_SO_GET_MAX          (EBT_SO_GET_INIT_ENTRIES+1)
-
-#ifdef __KERNEL__
 
 /* return values for match() functions */
 #define EBT_MATCH 0
@@ -304,77 +124,4 @@ extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff *skb,
 /* True if the target is not a standard target */
 #define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0)
 
-#endif /* __KERNEL__ */
-
-/* blatently stolen from ip_tables.h
- * fn returns 0 to continue iteration */
-#define EBT_MATCH_ITERATE(e, fn, args...)                   \
-({                                                          \
-       unsigned int __i;                                   \
-       int __ret = 0;                                      \
-       struct ebt_entry_match *__match;                    \
-                                                           \
-       for (__i = sizeof(struct ebt_entry);                \
-            __i < (e)->watchers_offset;                    \
-            __i += __match->match_size +                   \
-            sizeof(struct ebt_entry_match)) {              \
-               __match = (void *)(e) + __i;                \
-                                                           \
-               __ret = fn(__match , ## args);              \
-               if (__ret != 0)                             \
-                       break;                              \
-       }                                                   \
-       if (__ret == 0) {                                   \
-               if (__i != (e)->watchers_offset)            \
-                       __ret = -EINVAL;                    \
-       }                                                   \
-       __ret;                                              \
-})
-
-#define EBT_WATCHER_ITERATE(e, fn, args...)                 \
-({                                                          \
-       unsigned int __i;                                   \
-       int __ret = 0;                                      \
-       struct ebt_entry_watcher *__watcher;                \
-                                                           \
-       for (__i = e->watchers_offset;                      \
-            __i < (e)->target_offset;                      \
-            __i += __watcher->watcher_size +               \
-            sizeof(struct ebt_entry_watcher)) {            \
-               __watcher = (void *)(e) + __i;              \
-                                                           \
-               __ret = fn(__watcher , ## args);            \
-               if (__ret != 0)                             \
-                       break;                              \
-       }                                                   \
-       if (__ret == 0) {                                   \
-               if (__i != (e)->target_offset)              \
-                       __ret = -EINVAL;                    \
-       }                                                   \
-       __ret;                                              \
-})
-
-#define EBT_ENTRY_ITERATE(entries, size, fn, args...)       \
-({                                                          \
-       unsigned int __i;                                   \
-       int __ret = 0;                                      \
-       struct ebt_entry *__entry;                          \
-                                                           \
-       for (__i = 0; __i < (size);) {                      \
-               __entry = (void *)(entries) + __i;          \
-               __ret = fn(__entry , ## args);              \
-               if (__ret != 0)                             \
-                       break;                              \
-               if (__entry->bitmask != 0)                  \
-                       __i += __entry->next_offset;        \
-               else                                        \
-                       __i += sizeof(struct ebt_entries);  \
-       }                                                   \
-       if (__ret == 0) {                                   \
-               if (__i != (size))                          \
-                       __ret = -EINVAL;                    \
-       }                                                   \
-       __ret;                                              \
-})
-
 #endif
index 8ba0c5b72ea9f2e114399318f8a2ff2ff6078661..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,10 +0,0 @@
-header-y += ip_tables.h
-header-y += ipt_CLUSTERIP.h
-header-y += ipt_ECN.h
-header-y += ipt_LOG.h
-header-y += ipt_REJECT.h
-header-y += ipt_TTL.h
-header-y += ipt_ULOG.h
-header-y += ipt_ah.h
-header-y += ipt_ecn.h
-header-y += ipt_ttl.h
index db79231914cecae34ac895935339bcb884cdd8db..901e84db847d35e5ccbe49d2d524c921dc9bdef9 100644 (file)
  *     flags are stored in host byte order (of course).
  *     Port numbers are stored in HOST byte order.
  */
-
 #ifndef _IPTABLES_H
 #define _IPTABLES_H
 
-#ifdef __KERNEL__
 #include <linux/if.h>
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/skbuff.h>
-#endif
-#include <linux/types.h>
-#include <linux/compiler.h>
-#include <linux/netfilter_ipv4.h>
-
-#include <linux/netfilter/x_tables.h>
-
-#ifndef __KERNEL__
-#define IPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
-#define IPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
-#define ipt_match xt_match
-#define ipt_target xt_target
-#define ipt_table xt_table
-#define ipt_get_revision xt_get_revision
-#define ipt_entry_match xt_entry_match
-#define ipt_entry_target xt_entry_target
-#define ipt_standard_target xt_standard_target
-#define ipt_error_target xt_error_target
-#define ipt_counters xt_counters
-#define IPT_CONTINUE XT_CONTINUE
-#define IPT_RETURN XT_RETURN
-
-/* This group is older than old (iptables < v1.4.0-rc1~89) */
-#include <linux/netfilter/xt_tcpudp.h>
-#define ipt_udp xt_udp
-#define ipt_tcp xt_tcp
-#define IPT_TCP_INV_SRCPT      XT_TCP_INV_SRCPT
-#define IPT_TCP_INV_DSTPT      XT_TCP_INV_DSTPT
-#define IPT_TCP_INV_FLAGS      XT_TCP_INV_FLAGS
-#define IPT_TCP_INV_OPTION     XT_TCP_INV_OPTION
-#define IPT_TCP_INV_MASK       XT_TCP_INV_MASK
-#define IPT_UDP_INV_SRCPT      XT_UDP_INV_SRCPT
-#define IPT_UDP_INV_DSTPT      XT_UDP_INV_DSTPT
-#define IPT_UDP_INV_MASK       XT_UDP_INV_MASK
-
-/* The argument to IPT_SO_ADD_COUNTERS. */
-#define ipt_counters_info xt_counters_info
-/* Standard return verdict, or do jump. */
-#define IPT_STANDARD_TARGET XT_STANDARD_TARGET
-/* Error verdict. */
-#define IPT_ERROR_TARGET XT_ERROR_TARGET
-
-/* fn returns 0 to continue iteration */
-#define IPT_MATCH_ITERATE(e, fn, args...) \
-       XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args)
-
-/* fn returns 0 to continue iteration */
-#define IPT_ENTRY_ITERATE(entries, size, fn, args...) \
-       XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args)
-#endif
-
-/* Yes, Virginia, you have to zero the padding. */
-struct ipt_ip {
-       /* Source and destination IP addr */
-       struct in_addr src, dst;
-       /* Mask for src and dest IP addr */
-       struct in_addr smsk, dmsk;
-       char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
-       unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
-
-       /* Protocol, 0 = ANY */
-       __u16 proto;
-
-       /* Flags word */
-       __u8 flags;
-       /* Inverse flags */
-       __u8 invflags;
-};
-
-/* Values for "flag" field in struct ipt_ip (general ip structure). */
-#define IPT_F_FRAG             0x01    /* Set if rule is a fragment rule */
-#define IPT_F_GOTO             0x02    /* Set if jump is a goto */
-#define IPT_F_MASK             0x03    /* All possible flag bits mask. */
-
-/* Values for "inv" field in struct ipt_ip. */
-#define IPT_INV_VIA_IN         0x01    /* Invert the sense of IN IFACE. */
-#define IPT_INV_VIA_OUT                0x02    /* Invert the sense of OUT IFACE */
-#define IPT_INV_TOS            0x04    /* Invert the sense of TOS. */
-#define IPT_INV_SRCIP          0x08    /* Invert the sense of SRC IP. */
-#define IPT_INV_DSTIP          0x10    /* Invert the sense of DST OP. */
-#define IPT_INV_FRAG           0x20    /* Invert the sense of FRAG. */
-#define IPT_INV_PROTO          XT_INV_PROTO
-#define IPT_INV_MASK           0x7F    /* All possible flag bits mask. */
-
-/* This structure defines each of the firewall rules.  Consists of 3
-   parts which are 1) general IP header stuff 2) match specific
-   stuff 3) the target to perform if the rule matches */
-struct ipt_entry {
-       struct ipt_ip ip;
-
-       /* Mark with fields that we care about. */
-       unsigned int nfcache;
-
-       /* Size of ipt_entry + matches */
-       __u16 target_offset;
-       /* Size of ipt_entry + matches + target */
-       __u16 next_offset;
-
-       /* Back pointer */
-       unsigned int comefrom;
-
-       /* Packet and byte counters. */
-       struct xt_counters counters;
-
-       /* The matches (if any), then the target. */
-       unsigned char elems[0];
-};
-
-/*
- * New IP firewall options for [gs]etsockopt at the RAW IP level.
- * Unlike BSD Linux inherits IP options so you don't have to use a raw
- * socket for this. Instead we check rights in the calls.
- *
- * ATTENTION: check linux/in.h before adding new number here.
- */
-#define IPT_BASE_CTL           64
-
-#define IPT_SO_SET_REPLACE     (IPT_BASE_CTL)
-#define IPT_SO_SET_ADD_COUNTERS        (IPT_BASE_CTL + 1)
-#define IPT_SO_SET_MAX         IPT_SO_SET_ADD_COUNTERS
-
-#define IPT_SO_GET_INFO                        (IPT_BASE_CTL)
-#define IPT_SO_GET_ENTRIES             (IPT_BASE_CTL + 1)
-#define IPT_SO_GET_REVISION_MATCH      (IPT_BASE_CTL + 2)
-#define IPT_SO_GET_REVISION_TARGET     (IPT_BASE_CTL + 3)
-#define IPT_SO_GET_MAX                 IPT_SO_GET_REVISION_TARGET
-
-/* ICMP matching stuff */
-struct ipt_icmp {
-       __u8 type;                              /* type to match */
-       __u8 code[2];                           /* range of code */
-       __u8 invflags;                          /* Inverse flags */
-};
-
-/* Values for "inv" field for struct ipt_icmp. */
-#define IPT_ICMP_INV   0x01    /* Invert the sense of type/code test */
-
-/* The argument to IPT_SO_GET_INFO */
-struct ipt_getinfo {
-       /* Which table: caller fills this in. */
-       char name[XT_TABLE_MAXNAMELEN];
-
-       /* Kernel fills these in. */
-       /* Which hook entry points are valid: bitmask */
-       unsigned int valid_hooks;
-
-       /* Hook entry points: one per netfilter hook. */
-       unsigned int hook_entry[NF_INET_NUMHOOKS];
-
-       /* Underflow points. */
-       unsigned int underflow[NF_INET_NUMHOOKS];
-
-       /* Number of entries */
-       unsigned int num_entries;
-
-       /* Size of entries. */
-       unsigned int size;
-};
-
-/* The argument to IPT_SO_SET_REPLACE. */
-struct ipt_replace {
-       /* Which table. */
-       char name[XT_TABLE_MAXNAMELEN];
-
-       /* Which hook entry points are valid: bitmask.  You can't
-           change this. */
-       unsigned int valid_hooks;
-
-       /* Number of entries */
-       unsigned int num_entries;
-
-       /* Total size of new entries */
-       unsigned int size;
-
-       /* Hook entry points. */
-       unsigned int hook_entry[NF_INET_NUMHOOKS];
-
-       /* Underflow points. */
-       unsigned int underflow[NF_INET_NUMHOOKS];
-
-       /* Information about old entries: */
-       /* Number of counters (must be equal to current number of entries). */
-       unsigned int num_counters;
-       /* The old entries' counters. */
-       struct xt_counters __user *counters;
-
-       /* The entries (hang off end: not really an array). */
-       struct ipt_entry entries[0];
-};
-
-/* The argument to IPT_SO_GET_ENTRIES. */
-struct ipt_get_entries {
-       /* Which table: user fills this in. */
-       char name[XT_TABLE_MAXNAMELEN];
-
-       /* User fills this in: total entry size. */
-       unsigned int size;
-
-       /* The entries. */
-       struct ipt_entry entrytable[0];
-};
-
-/* Helper functions */
-static __inline__ struct xt_entry_target *
-ipt_get_target(struct ipt_entry *e)
-{
-       return (void *)e + e->target_offset;
-}
-
-/*
- *     Main firewall chains definitions and global var's definitions.
- */
-#ifdef __KERNEL__
 
 #include <linux/init.h>
+#include <uapi/linux/netfilter_ipv4/ip_tables.h>
+
 extern void ipt_init(void) __init;
 
 extern struct xt_table *ipt_register_table(struct net *net,
@@ -303,5 +90,4 @@ compat_ipt_get_target(struct compat_ipt_entry *e)
 }
 
 #endif /* CONFIG_COMPAT */
-#endif /*__KERNEL__*/
 #endif /* _IPTABLES_H */
index b88c0058bf73ad02a02229606cca38e6611652dc..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,12 +0,0 @@
-header-y += ip6_tables.h
-header-y += ip6t_HL.h
-header-y += ip6t_LOG.h
-header-y += ip6t_NPT.h
-header-y += ip6t_REJECT.h
-header-y += ip6t_ah.h
-header-y += ip6t_frag.h
-header-y += ip6t_hl.h
-header-y += ip6t_ipv6header.h
-header-y += ip6t_mh.h
-header-y += ip6t_opts.h
-header-y += ip6t_rt.h
index 08c2cbbaa32b094e5ba06d53c907834ef18c068a..5f84c6229dc619e65ed0ec4a9dc65187c3daccf0 100644 (file)
  *     flags are stored in host byte order (of course).
  *     Port numbers are stored in HOST byte order.
  */
-
 #ifndef _IP6_TABLES_H
 #define _IP6_TABLES_H
 
-#ifdef __KERNEL__
 #include <linux/if.h>
 #include <linux/in6.h>
 #include <linux/ipv6.h>
 #include <linux/skbuff.h>
-#endif
-#include <linux/types.h>
-#include <linux/compiler.h>
-#include <linux/netfilter_ipv6.h>
-
-#include <linux/netfilter/x_tables.h>
-
-#ifndef __KERNEL__
-#define IP6T_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
-#define IP6T_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
-#define ip6t_match xt_match
-#define ip6t_target xt_target
-#define ip6t_table xt_table
-#define ip6t_get_revision xt_get_revision
-#define ip6t_entry_match xt_entry_match
-#define ip6t_entry_target xt_entry_target
-#define ip6t_standard_target xt_standard_target
-#define ip6t_error_target xt_error_target
-#define ip6t_counters xt_counters
-#define IP6T_CONTINUE XT_CONTINUE
-#define IP6T_RETURN XT_RETURN
-
-/* Pre-iptables-1.4.0 */
-#include <linux/netfilter/xt_tcpudp.h>
-#define ip6t_tcp xt_tcp
-#define ip6t_udp xt_udp
-#define IP6T_TCP_INV_SRCPT     XT_TCP_INV_SRCPT
-#define IP6T_TCP_INV_DSTPT     XT_TCP_INV_DSTPT
-#define IP6T_TCP_INV_FLAGS     XT_TCP_INV_FLAGS
-#define IP6T_TCP_INV_OPTION    XT_TCP_INV_OPTION
-#define IP6T_TCP_INV_MASK      XT_TCP_INV_MASK
-#define IP6T_UDP_INV_SRCPT     XT_UDP_INV_SRCPT
-#define IP6T_UDP_INV_DSTPT     XT_UDP_INV_DSTPT
-#define IP6T_UDP_INV_MASK      XT_UDP_INV_MASK
-
-#define ip6t_counters_info xt_counters_info
-#define IP6T_STANDARD_TARGET XT_STANDARD_TARGET
-#define IP6T_ERROR_TARGET XT_ERROR_TARGET
-#define IP6T_MATCH_ITERATE(e, fn, args...) \
-       XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args)
-#define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \
-       XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args)
-#endif
-
-/* Yes, Virginia, you have to zero the padding. */
-struct ip6t_ip6 {
-       /* Source and destination IP6 addr */
-       struct in6_addr src, dst;               
-       /* Mask for src and dest IP6 addr */
-       struct in6_addr smsk, dmsk;
-       char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
-       unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
-
-       /* Upper protocol number
-        * - The allowed value is 0 (any) or protocol number of last parsable
-        *   header, which is 50 (ESP), 59 (No Next Header), 135 (MH), or
-        *   the non IPv6 extension headers.
-        * - The protocol numbers of IPv6 extension headers except of ESP and
-        *   MH do not match any packets.
-        * - You also need to set IP6T_FLAGS_PROTO to "flags" to check protocol.
-        */
-       __u16 proto;
-       /* TOS to match iff flags & IP6T_F_TOS */
-       __u8 tos;
-
-       /* Flags word */
-       __u8 flags;
-       /* Inverse flags */
-       __u8 invflags;
-};
-
-/* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */
-#define IP6T_F_PROTO           0x01    /* Set if rule cares about upper 
-                                          protocols */
-#define IP6T_F_TOS             0x02    /* Match the TOS. */
-#define IP6T_F_GOTO            0x04    /* Set if jump is a goto */
-#define IP6T_F_MASK            0x07    /* All possible flag bits mask. */
-
-/* Values for "inv" field in struct ip6t_ip6. */
-#define IP6T_INV_VIA_IN                0x01    /* Invert the sense of IN IFACE. */
-#define IP6T_INV_VIA_OUT               0x02    /* Invert the sense of OUT IFACE */
-#define IP6T_INV_TOS           0x04    /* Invert the sense of TOS. */
-#define IP6T_INV_SRCIP         0x08    /* Invert the sense of SRC IP. */
-#define IP6T_INV_DSTIP         0x10    /* Invert the sense of DST OP. */
-#define IP6T_INV_FRAG          0x20    /* Invert the sense of FRAG. */
-#define IP6T_INV_PROTO         XT_INV_PROTO
-#define IP6T_INV_MASK          0x7F    /* All possible flag bits mask. */
-
-/* This structure defines each of the firewall rules.  Consists of 3
-   parts which are 1) general IP header stuff 2) match specific
-   stuff 3) the target to perform if the rule matches */
-struct ip6t_entry {
-       struct ip6t_ip6 ipv6;
-
-       /* Mark with fields that we care about. */
-       unsigned int nfcache;
-
-       /* Size of ipt_entry + matches */
-       __u16 target_offset;
-       /* Size of ipt_entry + matches + target */
-       __u16 next_offset;
-
-       /* Back pointer */
-       unsigned int comefrom;
-
-       /* Packet and byte counters. */
-       struct xt_counters counters;
-
-       /* The matches (if any), then the target. */
-       unsigned char elems[0];
-};
-
-/* Standard entry */
-struct ip6t_standard {
-       struct ip6t_entry entry;
-       struct xt_standard_target target;
-};
-
-struct ip6t_error {
-       struct ip6t_entry entry;
-       struct xt_error_target target;
-};
-
-#define IP6T_ENTRY_INIT(__size)                                                       \
-{                                                                             \
-       .target_offset  = sizeof(struct ip6t_entry),                           \
-       .next_offset    = (__size),                                            \
-}
-
-#define IP6T_STANDARD_INIT(__verdict)                                         \
-{                                                                             \
-       .entry          = IP6T_ENTRY_INIT(sizeof(struct ip6t_standard)),       \
-       .target         = XT_TARGET_INIT(XT_STANDARD_TARGET,                   \
-                                        sizeof(struct xt_standard_target)),   \
-       .target.verdict = -(__verdict) - 1,                                    \
-}
-
-#define IP6T_ERROR_INIT                                                               \
-{                                                                             \
-       .entry          = IP6T_ENTRY_INIT(sizeof(struct ip6t_error)),          \
-       .target         = XT_TARGET_INIT(XT_ERROR_TARGET,                      \
-                                        sizeof(struct xt_error_target)),      \
-       .target.errorname = "ERROR",                                           \
-}
-
-/*
- * New IP firewall options for [gs]etsockopt at the RAW IP level.
- * Unlike BSD Linux inherits IP options so you don't have to use
- * a raw socket for this. Instead we check rights in the calls.
- *
- * ATTENTION: check linux/in6.h before adding new number here.
- */
-#define IP6T_BASE_CTL                  64
-
-#define IP6T_SO_SET_REPLACE            (IP6T_BASE_CTL)
-#define IP6T_SO_SET_ADD_COUNTERS       (IP6T_BASE_CTL + 1)
-#define IP6T_SO_SET_MAX                        IP6T_SO_SET_ADD_COUNTERS
-
-#define IP6T_SO_GET_INFO               (IP6T_BASE_CTL)
-#define IP6T_SO_GET_ENTRIES            (IP6T_BASE_CTL + 1)
-#define IP6T_SO_GET_REVISION_MATCH     (IP6T_BASE_CTL + 4)
-#define IP6T_SO_GET_REVISION_TARGET    (IP6T_BASE_CTL + 5)
-#define IP6T_SO_GET_MAX                        IP6T_SO_GET_REVISION_TARGET
-
-/* ICMP matching stuff */
-struct ip6t_icmp {
-       __u8 type;                              /* type to match */
-       __u8 code[2];                           /* range of code */
-       __u8 invflags;                          /* Inverse flags */
-};
-
-/* Values for "inv" field for struct ipt_icmp. */
-#define IP6T_ICMP_INV  0x01    /* Invert the sense of type/code test */
-
-/* The argument to IP6T_SO_GET_INFO */
-struct ip6t_getinfo {
-       /* Which table: caller fills this in. */
-       char name[XT_TABLE_MAXNAMELEN];
-
-       /* Kernel fills these in. */
-       /* Which hook entry points are valid: bitmask */
-       unsigned int valid_hooks;
-
-       /* Hook entry points: one per netfilter hook. */
-       unsigned int hook_entry[NF_INET_NUMHOOKS];
-
-       /* Underflow points. */
-       unsigned int underflow[NF_INET_NUMHOOKS];
-
-       /* Number of entries */
-       unsigned int num_entries;
-
-       /* Size of entries. */
-       unsigned int size;
-};
-
-/* The argument to IP6T_SO_SET_REPLACE. */
-struct ip6t_replace {
-       /* Which table. */
-       char name[XT_TABLE_MAXNAMELEN];
-
-       /* Which hook entry points are valid: bitmask.  You can't
-           change this. */
-       unsigned int valid_hooks;
-
-       /* Number of entries */
-       unsigned int num_entries;
-
-       /* Total size of new entries */
-       unsigned int size;
-
-       /* Hook entry points. */
-       unsigned int hook_entry[NF_INET_NUMHOOKS];
-
-       /* Underflow points. */
-       unsigned int underflow[NF_INET_NUMHOOKS];
-
-       /* Information about old entries: */
-       /* Number of counters (must be equal to current number of entries). */
-       unsigned int num_counters;
-       /* The old entries' counters. */
-       struct xt_counters __user *counters;
-
-       /* The entries (hang off end: not really an array). */
-       struct ip6t_entry entries[0];
-};
-
-/* The argument to IP6T_SO_GET_ENTRIES. */
-struct ip6t_get_entries {
-       /* Which table: user fills this in. */
-       char name[XT_TABLE_MAXNAMELEN];
-
-       /* User fills this in: total entry size. */
-       unsigned int size;
-
-       /* The entries. */
-       struct ip6t_entry entrytable[0];
-};
-
-/* Helper functions */
-static __inline__ struct xt_entry_target *
-ip6t_get_target(struct ip6t_entry *e)
-{
-       return (void *)e + e->target_offset;
-}
-
-/*
- *     Main firewall chains definitions and global var's definitions.
- */
-
-#ifdef __KERNEL__
 
 #include <linux/init.h>
+#include <uapi/linux/netfilter_ipv6/ip6_tables.h>
+
 extern void ip6t_init(void) __init;
 
 extern void *ip6t_alloc_initial_table(const struct xt_table *);
@@ -327,5 +76,4 @@ compat_ip6t_get_target(struct compat_ip6t_entry *e)
 }
 
 #endif /* CONFIG_COMPAT */
-#endif /*__KERNEL__*/
 #endif /* _IP6_TABLES_H */
index f80c56ac4d82a822efe44f0dbbd87cfba819dd92..6d3af05c107cf50e1dfe962a610b16bd43d7b6ab 100644 (file)
@@ -245,6 +245,8 @@ struct netlink_callback {
                                        struct netlink_callback *cb);
        int                     (*done)(struct netlink_callback *cb);
        void                    *data;
+       /* the module that dump function belong to */
+       struct module           *module;
        u16                     family;
        u16                     min_dump_alloc;
        unsigned int            prev_seq, seq;
@@ -262,14 +264,24 @@ __nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, int type, int len, int fla
 
 struct netlink_dump_control {
        int (*dump)(struct sk_buff *skb, struct netlink_callback *);
-       int (*done)(struct netlink_callback*);
+       int (*done)(struct netlink_callback *);
        void *data;
+       struct module *module;
        u16 min_dump_alloc;
 };
 
-extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
-                             const struct nlmsghdr *nlh,
-                             struct netlink_dump_control *control);
+extern int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+                               const struct nlmsghdr *nlh,
+                               struct netlink_dump_control *control);
+static inline int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+                                    const struct nlmsghdr *nlh,
+                                    struct netlink_dump_control *control)
+{
+       if (!control->module)
+               control->module = THIS_MODULE;
+
+       return __netlink_dump_start(ssk, skb, nlh, control);
+}
 
 #endif /* __KERNEL__ */
 
index 4b03f56e280eb9e59f236806ce24ce36e435c9c7..334a2f5f6bf167857cb621f4d71b7ea62f3481a7 100644 (file)
@@ -81,12 +81,16 @@ struct nfs_access_entry {
        int                     mask;
 };
 
+struct nfs_lockowner {
+       fl_owner_t l_owner;
+       pid_t l_pid;
+};
+
 struct nfs_lock_context {
        atomic_t count;
        struct list_head list;
        struct nfs_open_context *open_context;
-       fl_owner_t lockowner;
-       pid_t pid;
+       struct nfs_lockowner lockowner;
 };
 
 struct nfs4_state;
@@ -99,6 +103,7 @@ struct nfs_open_context {
 
        unsigned long flags;
 #define NFS_CONTEXT_ERROR_WRITE                (0)
+#define NFS_CONTEXT_RESEND_WRITES      (1)
        int error;
 
        struct list_head list;
@@ -355,6 +360,8 @@ extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
 extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
 extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr);
 extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *);
+extern void nfs_access_set_mask(struct nfs_access_entry *, u32);
 extern int nfs_permission(struct inode *, int);
 extern int nfs_open(struct inode *, struct file *);
 extern int nfs_release(struct inode *, struct file *);
index 310c63c8ab2cd374ff4d78c526359241cb4758cc..a9e76ee1adcae3c28c4823ae5cf7eb472bd05a03 100644 (file)
@@ -39,6 +39,7 @@ struct nfs_client {
        unsigned long           cl_flags;       /* behavior switches */
 #define NFS_CS_NORESVPORT      0               /* - use ephemeral src port */
 #define NFS_CS_DISCRTRY                1               /* - disconnect on RPC retry */
+#define NFS_CS_MIGRATION       2               /* - transparent state migr */
        struct sockaddr_storage cl_addr;        /* server identifier */
        size_t                  cl_addrlen;
        char *                  cl_hostname;    /* hostname of server */
@@ -81,6 +82,7 @@ struct nfs_client {
        /* The flags used for obtaining the clientid during EXCHANGE_ID */
        u32                     cl_exchange_flags;
        struct nfs4_session     *cl_session;    /* shared session */
+       bool                    cl_preserve_clid;
        struct nfs41_server_owner *cl_serverowner;
        struct nfs41_server_scope *cl_serverscope;
        struct nfs41_impl_id    *cl_implid;
@@ -125,6 +127,7 @@ struct nfs_server {
        unsigned int            namelen;
        unsigned int            options;        /* extra options enabled by mount */
 #define NFS_OPTION_FSCACHE     0x00000001      /* - local caching enabled */
+#define NFS_OPTION_MIGRATION   0x00000002      /* - NFSv4 migration enabled */
 
        struct nfs_fsid         fsid;
        __u64                   maxfilesize;    /* maximum file size */
index be9cf3c7e79ec0afcc0e024f6b95da5ab2bbd97e..a73ea89789d1b3375846b96656873c790d87d5a1 100644 (file)
@@ -251,7 +251,6 @@ struct nfs4_layoutget_res {
 struct nfs4_layoutget {
        struct nfs4_layoutget_args args;
        struct nfs4_layoutget_res res;
-       struct pnfs_layout_segment **lsegpp;
        gfp_t gfp_flags;
 };
 
@@ -335,6 +334,7 @@ struct nfs_openargs {
        struct nfs_seqid *      seqid;
        int                     open_flags;
        fmode_t                 fmode;
+       u32                     access;
        __u64                   clientid;
        struct stateowner_id    id;
        union {
@@ -369,6 +369,9 @@ struct nfs_openres {
        struct nfs4_string      *owner;
        struct nfs4_string      *group_owner;
        struct nfs4_sequence_res        seq_res;
+       __u32                   access_request;
+       __u32                   access_supported;
+       __u32                   access_result;
 };
 
 /*
index 5b7d84ac954a2c7a5e0b7f19f3529bb01e1a981f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,5 +0,0 @@
-header-y += cld.h
-header-y += debug.h
-header-y += export.h
-header-y += nfsfh.h
-header-y += stats.h
index ee4aa91788e7fbd9233286afd70f0a03de9aabe5..19ef8375b577225ec6799df32327ce0a0754df0c 100644 (file)
@@ -5,44 +5,15 @@
  *
  * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
  */
-
 #ifndef LINUX_NFSD_DEBUG_H
 #define LINUX_NFSD_DEBUG_H
 
-#include <linux/sunrpc/debug.h>
+#include <uapi/linux/nfsd/debug.h>
 
-/*
- * Enable debugging for nfsd.
- * Requires RPC_DEBUG.
- */
-#ifdef RPC_DEBUG
-# define NFSD_DEBUG            1
-#endif
-
-/*
- * knfsd debug flags
- */
-#define NFSDDBG_SOCK           0x0001
-#define NFSDDBG_FH             0x0002
-#define NFSDDBG_EXPORT         0x0004
-#define NFSDDBG_SVC            0x0008
-#define NFSDDBG_PROC           0x0010
-#define NFSDDBG_FILEOP         0x0020
-#define NFSDDBG_AUTH           0x0040
-#define NFSDDBG_REPCACHE       0x0080
-#define NFSDDBG_XDR            0x0100
-#define NFSDDBG_LOCKD          0x0200
-#define NFSDDBG_ALL            0x7FFF
-#define NFSDDBG_NOCHANGE       0xFFFF
-
-
-#ifdef __KERNEL__
 # undef ifdebug
 # ifdef NFSD_DEBUG
 #  define ifdebug(flag)                if (nfsd_debug & NFSDDBG_##flag)
 # else
 #  define ifdebug(flag)                if (0)
 # endif
-#endif /* __KERNEL__ */
-
 #endif /* LINUX_NFSD_DEBUG_H */
index e33f747b173c500d02639dfd5257de093a79fff0..24c139288db4a1b97022780fedcd1d8313903424 100644 (file)
@@ -6,58 +6,11 @@
  *
  * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
  */
-
 #ifndef NFSD_EXPORT_H
 #define NFSD_EXPORT_H
 
-# include <linux/types.h>
-#ifdef __KERNEL__
 # include <linux/nfsd/nfsfh.h>
-#endif
-
-/*
- * Important limits for the exports stuff.
- */
-#define NFSCLNT_IDMAX          1024
-#define NFSCLNT_ADDRMAX                16
-#define NFSCLNT_KEYMAX         32
-
-/*
- * Export flags.
- */
-#define NFSEXP_READONLY                0x0001
-#define NFSEXP_INSECURE_PORT   0x0002
-#define NFSEXP_ROOTSQUASH      0x0004
-#define NFSEXP_ALLSQUASH       0x0008
-#define NFSEXP_ASYNC           0x0010
-#define NFSEXP_GATHERED_WRITES 0x0020
-/* 40 80 100 currently unused */
-#define NFSEXP_NOHIDE          0x0200
-#define NFSEXP_NOSUBTREECHECK  0x0400
-#define        NFSEXP_NOAUTHNLM        0x0800          /* Don't authenticate NLM requests - just trust */
-#define NFSEXP_MSNFS           0x1000  /* do silly things that MS clients expect; no longer supported */
-#define NFSEXP_FSID            0x2000
-#define        NFSEXP_CROSSMOUNT       0x4000
-#define        NFSEXP_NOACL            0x8000  /* reserved for possible ACL related use */
-/*
- * The NFSEXP_V4ROOT flag causes the kernel to give access only to NFSv4
- * clients, and only to the single directory that is the root of the
- * export; further lookup and readdir operations are treated as if every
- * subdirectory was a mountpoint, and ignored if they are not themselves
- * exported.  This is used by nfsd and mountd to construct the NFSv4
- * pseudofilesystem, which provides access only to paths leading to each
- * exported filesystem.
- */
-#define        NFSEXP_V4ROOT           0x10000
-/* All flags that we claim to support.  (Note we don't support NOACL.) */
-#define NFSEXP_ALLFLAGS                0x17E3F
-
-/* The flags that may vary depending on security flavor: */
-#define NFSEXP_SECINFO_FLAGS   (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
-                                       | NFSEXP_ALLSQUASH \
-                                       | NFSEXP_INSECURE_PORT)
-
-#ifdef __KERNEL__
+#include <uapi/linux/nfsd/export.h>
 
 /*
  * FS Locations
@@ -154,7 +107,4 @@ static inline void exp_get(struct svc_export *exp)
 }
 struct svc_export * rqst_exp_find(struct svc_rqst *, int, u32 *);
 
-#endif /* __KERNEL__ */
-
 #endif /* NFSD_EXPORT_H */
-
index fa63048fecff82e8e5849c1487d583c49194313c..a93593f1fa4ea7d38668bf4367bd1bec0ecc1faa 100644 (file)
  *
  * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
  */
-
 #ifndef _LINUX_NFSD_FH_H
 #define _LINUX_NFSD_FH_H
 
-#include <linux/types.h>
-#include <linux/nfs.h>
-#include <linux/nfs2.h>
-#include <linux/nfs3.h>
-#include <linux/nfs4.h>
-#ifdef __KERNEL__
 # include <linux/sunrpc/svc.h>
-#endif
-
-/*
- * This is the old "dentry style" Linux NFSv2 file handle.
- *
- * The xino and xdev fields are currently used to transport the
- * ino/dev of the exported inode.
- */
-struct nfs_fhbase_old {
-       __u32           fb_dcookie;     /* dentry cookie - always 0xfeebbaca */
-       __u32           fb_ino;         /* our inode number */
-       __u32           fb_dirino;      /* dir inode number, 0 for directories */
-       __u32           fb_dev;         /* our device */
-       __u32           fb_xdev;
-       __u32           fb_xino;
-       __u32           fb_generation;
-};
-
-/*
- * This is the new flexible, extensible style NFSv2/v3 file handle.
- * by Neil Brown <neilb@cse.unsw.edu.au> - March 2000
- *
- * The file handle starts with a sequence of four-byte words.
- * The first word contains a version number (1) and three descriptor bytes
- * that tell how the remaining 3 variable length fields should be handled.
- * These three bytes are auth_type, fsid_type and fileid_type.
- *
- * All four-byte values are in host-byte-order.
- *
- * The auth_type field specifies how the filehandle can be authenticated
- * This might allow a file to be confirmed to be in a writable part of a
- * filetree without checking the path from it up to the root.
- * Current values:
- *     0  - No authentication.  fb_auth is 0 bytes long
- * Possible future values:
- *     1  - 4 bytes taken from MD5 hash of the remainer of the file handle
- *          prefixed by a secret and with the important export flags.
- *
- * The fsid_type identifies how the filesystem (or export point) is
- *    encoded.
- *  Current values:
- *     0  - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number
- *        NOTE: we cannot use the kdev_t device id value, because kdev_t.h
- *              says we mustn't.  We must break it up and reassemble.
- *     1  - 4 byte user specified identifier
- *     2  - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED
- *     3  - 4 byte device id, encoded for user-space, 4 byte inode number
- *     4  - 4 byte inode number and 4 byte uuid
- *     5  - 8 byte uuid
- *     6  - 16 byte uuid
- *     7  - 8 byte inode number and 16 byte uuid
- *
- * The fileid_type identified how the file within the filesystem is encoded.
- * This is (will be) passed to, and set by, the underlying filesystem if it supports
- * filehandle operations.  The filesystem must not use the value '0' or '0xff' and may
- * only use the values 1 and 2 as defined below:
- *  Current values:
- *    0   - The root, or export point, of the filesystem.  fb_fileid is 0 bytes.
- *    1   - 32bit inode number, 32 bit generation number.
- *    2   - 32bit inode number, 32 bit generation number, 32 bit parent directory inode number.
- *
- */
-struct nfs_fhbase_new {
-       __u8            fb_version;     /* == 1, even => nfs_fhbase_old */
-       __u8            fb_auth_type;
-       __u8            fb_fsid_type;
-       __u8            fb_fileid_type;
-       __u32           fb_auth[1];
-/*     __u32           fb_fsid[0]; floating */
-/*     __u32           fb_fileid[0]; floating */
-};
-
-struct knfsd_fh {
-       unsigned int    fh_size;        /* significant for NFSv3.
-                                        * Points to the current size while building
-                                        * a new file handle
-                                        */
-       union {
-               struct nfs_fhbase_old   fh_old;
-               __u32                   fh_pad[NFS4_FHSIZE/4];
-               struct nfs_fhbase_new   fh_new;
-       } fh_base;
-};
-
-#define ofh_dcookie            fh_base.fh_old.fb_dcookie
-#define ofh_ino                        fh_base.fh_old.fb_ino
-#define ofh_dirino             fh_base.fh_old.fb_dirino
-#define ofh_dev                        fh_base.fh_old.fb_dev
-#define ofh_xdev               fh_base.fh_old.fb_xdev
-#define ofh_xino               fh_base.fh_old.fb_xino
-#define ofh_generation         fh_base.fh_old.fb_generation
-
-#define        fh_version              fh_base.fh_new.fb_version
-#define        fh_fsid_type            fh_base.fh_new.fb_fsid_type
-#define        fh_auth_type            fh_base.fh_new.fb_auth_type
-#define        fh_fileid_type          fh_base.fh_new.fb_fileid_type
-#define        fh_auth                 fh_base.fh_new.fb_auth
-#define        fh_fsid                 fh_base.fh_new.fb_auth
-
-#ifdef __KERNEL__
+#include <uapi/linux/nfsd/nfsfh.h>
 
 static inline __u32 ino_t_to_u32(ino_t ino)
 {
@@ -166,7 +60,4 @@ typedef struct svc_fh {
 
 } svc_fh;
 
-#endif /* __KERNEL__ */
-
-
 #endif /* _LINUX_NFSD_FH_H */
index 2693ef647df6657ae20ca917f3862921e7e53874..e75b2544ff12f31973d76c50d976ff7ed25db87f 100644 (file)
@@ -5,16 +5,11 @@
  *
  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  */
-
 #ifndef LINUX_NFSD_STATS_H
 #define LINUX_NFSD_STATS_H
 
-#include <linux/nfs4.h>
-
-/* thread usage wraps very million seconds (approx one fortnight) */
-#define        NFSD_USAGE_WRAP (HZ*1000000)
+#include <uapi/linux/nfsd/stats.h>
 
-#ifdef __KERNEL__
 
 struct nfsd_stats {
        unsigned int    rchits;         /* repcache hits */
@@ -47,5 +42,4 @@ extern struct svc_stat                nfsd_svcstats;
 void   nfsd_stat_init(void);
 void   nfsd_stat_shutdown(void);
 
-#endif /* __KERNEL__ */
 #endif /* LINUX_NFSD_STATS_H */
index 6ef49b803efb1fee5fdb9bdc02d6b34a4d445a89..8163107b94b4ebacd0c0080e168b6920b068b469 100644 (file)
@@ -26,32 +26,32 @@ extern struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
 extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np);
 
 #else /* CONFIG_OF */
-int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
+static inline int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 {
        return -ENOSYS;
 }
 
-struct phy_device *of_phy_find_device(struct device_node *phy_np)
+static inline struct phy_device *of_phy_find_device(struct device_node *phy_np)
 {
        return NULL;
 }
 
-struct phy_device *of_phy_connect(struct net_device *dev,
-                                        struct device_node *phy_np,
-                                        void (*hndlr)(struct net_device *),
-                                        u32 flags, phy_interface_t iface)
+static inline struct phy_device *of_phy_connect(struct net_device *dev,
+                                               struct device_node *phy_np,
+                                               void (*hndlr)(struct net_device *),
+                                               u32 flags, phy_interface_t iface)
 {
        return NULL;
 }
 
-struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
-                                        void (*hndlr)(struct net_device *),
-                                        phy_interface_t iface)
+static inline struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
+                                                          void (*hndlr)(struct net_device *),
+                                                          phy_interface_t iface)
 {
        return NULL;
 }
 
-struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np)
+static inline struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np)
 {
        return NULL;
 }
index eed27f4f4c3efd1785a3e777636f52bd5642aa7e..be655e4a2a75b23e056c1631e5219fd52dd6c6f8 100644 (file)
@@ -71,13 +71,13 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,
 #ifdef CONFIG_COMPACTION
 #define get_pageblock_skip(page) \
                        get_pageblock_flags_group(page, PB_migrate_skip,     \
-                                                       PB_migrate_skip + 1)
+                                                       PB_migrate_skip)
 #define clear_pageblock_skip(page) \
                        set_pageblock_flags_group(page, 0, PB_migrate_skip,  \
-                                                       PB_migrate_skip + 1)
+                                                       PB_migrate_skip)
 #define set_pageblock_skip(page) \
                        set_pageblock_flags_group(page, 1, PB_migrate_skip,  \
-                                                       PB_migrate_skip + 1)
+                                                       PB_migrate_skip)
 #endif /* CONFIG_COMPACTION */
 
 #define get_pageblock_flags(page) \
diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h
new file mode 100644 (file)
index 0000000..cf80f7e
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef _LINUX_PERCPU_RWSEM_H
+#define _LINUX_PERCPU_RWSEM_H
+
+#include <linux/mutex.h>
+#include <linux/percpu.h>
+#include <linux/rcupdate.h>
+#include <linux/delay.h>
+
+struct percpu_rw_semaphore {
+       unsigned __percpu *counters;
+       bool locked;
+       struct mutex mtx;
+};
+
+static inline void percpu_down_read(struct percpu_rw_semaphore *p)
+{
+       rcu_read_lock();
+       if (unlikely(p->locked)) {
+               rcu_read_unlock();
+               mutex_lock(&p->mtx);
+               this_cpu_inc(*p->counters);
+               mutex_unlock(&p->mtx);
+               return;
+       }
+       this_cpu_inc(*p->counters);
+       rcu_read_unlock();
+}
+
+static inline void percpu_up_read(struct percpu_rw_semaphore *p)
+{
+       /*
+        * On X86, write operation in this_cpu_dec serves as a memory unlock
+        * barrier (i.e. memory accesses may be moved before the write, but
+        * no memory accesses are moved past the write).
+        * On other architectures this may not be the case, so we need smp_mb()
+        * there.
+        */
+#if defined(CONFIG_X86) && (!defined(CONFIG_X86_PPRO_FENCE) && !defined(CONFIG_X86_OOSTORE))
+       barrier();
+#else
+       smp_mb();
+#endif
+       this_cpu_dec(*p->counters);
+}
+
+static inline unsigned __percpu_count(unsigned __percpu *counters)
+{
+       unsigned total = 0;
+       int cpu;
+
+       for_each_possible_cpu(cpu)
+               total += ACCESS_ONCE(*per_cpu_ptr(counters, cpu));
+
+       return total;
+}
+
+static inline void percpu_down_write(struct percpu_rw_semaphore *p)
+{
+       mutex_lock(&p->mtx);
+       p->locked = true;
+       synchronize_rcu();
+       while (__percpu_count(p->counters))
+               msleep(1);
+       smp_rmb(); /* paired with smp_mb() in percpu_sem_up_read() */
+}
+
+static inline void percpu_up_write(struct percpu_rw_semaphore *p)
+{
+       p->locked = false;
+       mutex_unlock(&p->mtx);
+}
+
+static inline int percpu_init_rwsem(struct percpu_rw_semaphore *p)
+{
+       p->counters = alloc_percpu(unsigned);
+       if (unlikely(!p->counters))
+               return -ENOMEM;
+       p->locked = false;
+       mutex_init(&p->mtx);
+       return 0;
+}
+
+static inline void percpu_free_rwsem(struct percpu_rw_semaphore *p)
+{
+       free_percpu(p->counters);
+       p->counters = NULL; /* catch use after free bugs */
+}
+
+#endif
index 599afc4bb67e88c592e19f77a56800458ffa252d..b4166cdfa7a2cd991019a1fe764323b22ecefa2a 100644 (file)
@@ -1110,7 +1110,7 @@ struct perf_cpu_context {
        int                             exclusive;
        struct list_head                rotation_list;
        int                             jiffies_interval;
-       struct pmu                      *active_pmu;
+       struct pmu                      *unique_pmu;
        struct perf_cgroup              *cgrp;
 };
 
index c2303c3e4803577d4d0b2fb7533e4ddb1638a0e7..3a8be9cdc95c1424434e1532d981ca4787c39dc6 100644 (file)
@@ -28,7 +28,7 @@ enum i2c_freq_mode {
  * @sm:                speed mode
  */
 struct nmk_i2c_controller {
-       unsigned long   clk_freq;
+       u32             clk_freq;
        unsigned short  slsu;
        unsigned char   tft;
        unsigned char   rft;
diff --git a/include/linux/platform_data/leds-lm3556.h b/include/linux/platform_data/leds-lm3556.h
deleted file mode 100644 (file)
index 4b4e7d6..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Simple driver for Texas Instruments LM3556 LED Flash driver chip (Rev0x03)
- * Copyright (C) 2012 Texas Instruments
- *
- * 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 __LINUX_LM3556_H
-#define __LINUX_LM3556_H
-
-#define LM3556_NAME "leds-lm3556"
-
-enum lm3556_pin_polarity {
-       PIN_LOW_ACTIVE = 0,
-       PIN_HIGH_ACTIVE,
-};
-
-enum lm3556_pin_enable {
-       PIN_DISABLED = 0,
-       PIN_ENABLED,
-};
-
-enum lm3556_strobe_usuage {
-       STROBE_EDGE_DETECT = 0,
-       STROBE_LEVEL_DETECT,
-};
-
-enum lm3556_indic_mode {
-       INDIC_MODE_INTERNAL = 0,
-       INDIC_MODE_EXTERNAL,
-};
-
-struct lm3556_platform_data {
-       enum lm3556_pin_enable torch_pin_en;
-       enum lm3556_pin_polarity torch_pin_polarity;
-
-       enum lm3556_strobe_usuage strobe_usuage;
-       enum lm3556_pin_enable strobe_pin_en;
-       enum lm3556_pin_polarity strobe_pin_polarity;
-
-       enum lm3556_pin_enable tx_pin_en;
-       enum lm3556_pin_polarity tx_pin_polarity;
-
-       enum lm3556_indic_mode indicator_mode;
-};
-
-#endif /* __LINUX_LM3556_H */
diff --git a/include/linux/platform_data/leds-lm355x.h b/include/linux/platform_data/leds-lm355x.h
new file mode 100644 (file)
index 0000000..b88724b
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Simple driver for Texas Instruments LM355x LED driver chip
+ *
+ * Author: G.Shark Jeong <gshark.jeong@gmail.com>
+ *         Daniel Jeong <daniel.jeong@ti.com>
+ */
+
+#define LM355x_NAME "leds-lm355x"
+#define LM3554_NAME "leds-lm3554"
+#define LM3556_NAME "leds-lm3556"
+
+/* lm3554 : strobe def. on */
+enum lm355x_strobe {
+       LM355x_PIN_STROBE_DISABLE = 0x00,
+       LM355x_PIN_STROBE_ENABLE = 0x01,
+};
+
+enum lm355x_torch {
+       LM355x_PIN_TORCH_DISABLE = 0,
+       LM3554_PIN_TORCH_ENABLE = 0x80,
+       LM3556_PIN_TORCH_ENABLE = 0x10,
+};
+
+enum lm355x_tx2 {
+       LM355x_PIN_TX_DISABLE = 0,
+       LM3554_PIN_TX_ENABLE = 0x20,
+       LM3556_PIN_TX_ENABLE = 0x40,
+};
+
+enum lm355x_ntc {
+       LM355x_PIN_NTC_DISABLE = 0,
+       LM3554_PIN_NTC_ENABLE = 0x08,
+       LM3556_PIN_NTC_ENABLE = 0x80,
+};
+
+enum lm355x_pmode {
+       LM355x_PMODE_DISABLE = 0,
+       LM355x_PMODE_ENABLE = 0x04,
+};
+
+/*
+ * struct lm3554_platform_data
+ * @pin_strobe: strobe input
+ * @pin_torch : input pin
+ *              lm3554-tx1/torch/gpio1
+ *              lm3556-torch
+ * @pin_tx2   : input pin
+ *              lm3554-envm/tx2/gpio2
+ *              lm3556-tx pin
+ * @ntc_pin  : output pin
+ *              lm3554-ledi/ntc
+ *              lm3556-temp pin
+ * @pass_mode : pass mode
+ */
+struct lm355x_platform_data {
+       enum lm355x_strobe pin_strobe;
+       enum lm355x_torch pin_tx1;
+       enum lm355x_tx2 pin_tx2;
+       enum lm355x_ntc ntc_pin;
+
+       enum lm355x_pmode pass_mode;
+};
diff --git a/include/linux/platform_data/leds-lm3642.h b/include/linux/platform_data/leds-lm3642.h
new file mode 100644 (file)
index 0000000..72d6ee6
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+* Copyright (C) 2012 Texas Instruments
+*
+* License Terms: GNU General Public License v2
+*
+* Simple driver for Texas Instruments LM3642 LED driver chip
+*
+* Author: G.Shark Jeong <gshark.jeong@gmail.com>
+*         Daniel Jeong <daniel.jeong@ti.com>
+*/
+
+#ifndef __LINUX_LM3642_H
+#define __LINUX_LM3642_H
+
+#define LM3642_NAME "leds-lm3642"
+
+enum lm3642_torch_pin_enable {
+       LM3642_TORCH_PIN_DISABLE = 0x00,
+       LM3642_TORCH_PIN_ENABLE = 0x10,
+};
+
+enum lm3642_strobe_pin_enable {
+       LM3642_STROBE_PIN_DISABLE = 0x00,
+       LM3642_STROBE_PIN_ENABLE = 0x20,
+};
+
+enum lm3642_tx_pin_enable {
+       LM3642_TX_PIN_DISABLE = 0x00,
+       LM3642_TX_PIN_ENABLE = 0x40,
+};
+
+struct lm3642_platform_data {
+       enum lm3642_torch_pin_enable torch_pin;
+       enum lm3642_strobe_pin_enable strobe_pin;
+       enum lm3642_tx_pin_enable tx_pin;
+};
+
+#endif /* __LINUX_LM3642_H */
diff --git a/include/linux/platform_data/leds-pca9633.h b/include/linux/platform_data/leds-pca9633.h
new file mode 100644 (file)
index 0000000..c5bf29b
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * PCA9633 LED chip driver.
+ *
+ * Copyright 2012 bct electronic GmbH
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __LINUX_PCA9633_H
+#define __LINUX_PCA9633_H
+#include <linux/leds.h>
+
+enum pca9633_outdrv {
+       PCA9633_OPEN_DRAIN,
+       PCA9633_TOTEM_POLE, /* aka push-pull */
+};
+
+struct pca9633_platform_data {
+       struct led_platform_data leds;
+       enum pca9633_outdrv outdrv;
+};
+
+#endif /* __LINUX_PCA9633_H*/
index c45b1e8d4c2ec73ff0fe608ac2b96ba9d0d34607..bf34e17cee7f6eb9c9068d811c37dae3b8c10fe0 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
+ * Copyright (C) 2010 - 2012 Samsung Electronics Co., Ltd.
  *
- * S5P series MIPI CSI slave device support
+ * Samsung S5P/Exynos SoC series MIPI CSIS device support
  *
  * 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
 #ifndef __PLAT_SAMSUNG_MIPI_CSIS_H_
 #define __PLAT_SAMSUNG_MIPI_CSIS_H_ __FILE__
 
-struct platform_device;
-
 /**
  * struct s5p_platform_mipi_csis - platform data for S5P MIPI-CSIS driver
- * @clk_rate: bus clock frequency
- * @lanes: number of data lanes used
- * @alignment: data alignment in bits
- * @hs_settle: HS-RX settle time
- * @fixed_phy_vdd: false to enable external D-PHY regulator management in the
- *                driver or true in case this regulator has no enable function
- * @phy_enable: pointer to a callback controlling D-PHY enable/reset
+ * @clk_rate:    bus clock frequency
+ * @wclk_source: CSI wrapper clock selection: 0 - bus clock, 1 - ext. SCLK_CAM
+ * @lanes:       number of data lanes used
+ * @hs_settle:   HS-RX settle time
  */
 struct s5p_platform_mipi_csis {
        unsigned long clk_rate;
+       u8 wclk_source;
        u8 lanes;
-       u8 alignment;
        u8 hs_settle;
-       bool fixed_phy_vdd;
-       int (*phy_enable)(struct platform_device *pdev, bool on);
 };
 
 /**
  * s5p_csis_phy_enable - global MIPI-CSI receiver D-PHY control
- * @pdev: MIPI-CSIS platform device
- * @on: true to enable D-PHY and deassert its reset
- *     false to disable D-PHY
+ * @id:     MIPI-CSIS harware instance index (0...1)
+ * @on:     true to enable D-PHY and deassert its reset
+ *          false to disable D-PHY
+ * @return: 0 on success, or negative error code on failure
  */
-int s5p_csis_phy_enable(struct platform_device *pdev, bool on);
+int s5p_csis_phy_enable(int id, bool on);
 
 #endif /* __PLAT_SAMSUNG_MIPI_CSIS_H_ */
diff --git a/include/linux/platform_data/mmp_dma.h b/include/linux/platform_data/mmp_dma.h
new file mode 100644 (file)
index 0000000..2a330ec
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  MMP Platform DMA Management
+ *
+ *  Copyright (c) 2011 Marvell Semiconductors Inc.
+ *
+ *  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 MMP_DMA_H
+#define MMP_DMA_H
+
+struct mmp_dma_platdata {
+       int dma_channels;
+};
+
+#endif /* MMP_DMA_H */
index 51ad0995abac73eb741b0e793f91cd2cd2f06f36..59acd987ed340e18b69a55fd15f0872dca94b055 100644 (file)
@@ -49,6 +49,7 @@ struct sdhci_pxa_platdata {
        bool            ext_cd_gpio_invert;
        unsigned int    max_speed;
        unsigned int    host_caps;
+       unsigned int    host_caps2;
        unsigned int    quirks;
        unsigned int    pm_caps;
 };
index 3db698aee34cd9437f8f42823f17825796597f09..1d24ffad59c53c27a66bf7b4cced639f0a5f000a 100644 (file)
@@ -401,6 +401,10 @@ static inline void user_single_step_siginfo(struct task_struct *tsk,
 #define arch_ptrace_stop(code, info)           do { } while (0)
 #endif
 
+#ifndef current_pt_regs
+#define current_pt_regs() task_pt_regs(current)
+#endif
+
 extern int task_current_syscall(struct task_struct *target, long *callno,
                                unsigned long args[6], unsigned int maxargs,
                                unsigned long *sp, unsigned long *pc);
index 21d076c5089e9646418113fb9d27d30e4ba109f7..112b31436848d449bdd471374faa4135d910d043 100644 (file)
@@ -1,11 +1,13 @@
 #ifndef __LINUX_PWM_H
 #define __LINUX_PWM_H
 
+#include <linux/err.h>
 #include <linux/of.h>
 
 struct pwm_device;
 struct seq_file;
 
+#if IS_ENABLED(CONFIG_PWM) || IS_ENABLED(CONFIG_HAVE_PWM)
 /*
  * pwm_request - request a PWM device
  */
@@ -30,10 +32,47 @@ int pwm_enable(struct pwm_device *pwm);
  * pwm_disable - stop a PWM output toggling
  */
 void pwm_disable(struct pwm_device *pwm);
+#else
+static inline struct pwm_device *pwm_request(int pwm_id, const char *label)
+{
+       return ERR_PTR(-ENODEV);
+}
+
+static inline void pwm_free(struct pwm_device *pwm)
+{
+}
+
+static inline int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+       return -EINVAL;
+}
+
+static inline int pwm_enable(struct pwm_device *pwm)
+{
+       return -EINVAL;
+}
+
+static inline void pwm_disable(struct pwm_device *pwm)
+{
+}
+#endif
 
-#ifdef CONFIG_PWM
 struct pwm_chip;
 
+/**
+ * enum pwm_polarity - polarity of a PWM signal
+ * @PWM_POLARITY_NORMAL: a high signal for the duration of the duty-
+ * cycle, followed by a low signal for the remainder of the pulse
+ * period
+ * @PWM_POLARITY_INVERSED: a low signal for the duration of the duty-
+ * cycle, followed by a high signal for the remainder of the pulse
+ * period
+ */
+enum pwm_polarity {
+       PWM_POLARITY_NORMAL,
+       PWM_POLARITY_INVERSED,
+};
+
 enum {
        PWMF_REQUESTED = 1 << 0,
        PWMF_ENABLED = 1 << 1,
@@ -61,11 +100,17 @@ static inline unsigned int pwm_get_period(struct pwm_device *pwm)
        return pwm ? pwm->period : 0;
 }
 
+/*
+ * pwm_set_polarity - configure the polarity of a PWM signal
+ */
+int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity);
+
 /**
  * struct pwm_ops - PWM controller operations
  * @request: optional hook for requesting a PWM
  * @free: optional hook for freeing a PWM
  * @config: configure duty cycles and period length for this PWM
+ * @set_polarity: configure the polarity of this PWM
  * @enable: enable PWM output toggling
  * @disable: disable PWM output toggling
  * @dbg_show: optional routine to show contents in debugfs
@@ -79,6 +124,9 @@ struct pwm_ops {
        int                     (*config)(struct pwm_chip *chip,
                                          struct pwm_device *pwm,
                                          int duty_ns, int period_ns);
+       int                     (*set_polarity)(struct pwm_chip *chip,
+                                         struct pwm_device *pwm,
+                                         enum pwm_polarity polarity);
        int                     (*enable)(struct pwm_chip *chip,
                                          struct pwm_device *pwm);
        void                    (*disable)(struct pwm_chip *chip,
@@ -113,6 +161,7 @@ struct pwm_chip {
        unsigned int            of_pwm_n_cells;
 };
 
+#if IS_ENABLED(CONFIG_PWM)
 int pwm_set_chip_data(struct pwm_device *pwm, void *data);
 void *pwm_get_chip_data(struct pwm_device *pwm);
 
@@ -125,6 +174,57 @@ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
 struct pwm_device *pwm_get(struct device *dev, const char *consumer);
 void pwm_put(struct pwm_device *pwm);
 
+struct pwm_device *devm_pwm_get(struct device *dev, const char *consumer);
+void devm_pwm_put(struct device *dev, struct pwm_device *pwm);
+#else
+static inline int pwm_set_chip_data(struct pwm_device *pwm, void *data)
+{
+       return -EINVAL;
+}
+
+static inline void *pwm_get_chip_data(struct pwm_device *pwm)
+{
+       return NULL;
+}
+
+static inline int pwmchip_add(struct pwm_chip *chip)
+{
+       return -EINVAL;
+}
+
+static inline int pwmchip_remove(struct pwm_chip *chip)
+{
+       return -EINVAL;
+}
+
+static inline struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
+                                                      unsigned int index,
+                                                      const char *label)
+{
+       return ERR_PTR(-ENODEV);
+}
+
+static inline struct pwm_device *pwm_get(struct device *dev,
+                                        const char *consumer)
+{
+       return ERR_PTR(-ENODEV);
+}
+
+static inline void pwm_put(struct pwm_device *pwm)
+{
+}
+
+static inline struct pwm_device *devm_pwm_get(struct device *dev,
+                                             const char *consumer)
+{
+       return ERR_PTR(-ENODEV);
+}
+
+static inline void devm_pwm_put(struct device *dev, struct pwm_device *pwm)
+{
+}
+#endif
+
 struct pwm_lookup {
        struct list_head list;
        const char *provider;
@@ -141,8 +241,12 @@ struct pwm_lookup {
                .con_id = _con_id,                      \
        }
 
+#if IS_ENABLED(CONFIG_PWM)
 void pwm_add_table(struct pwm_lookup *table, size_t num);
-
+#else
+static inline void pwm_add_table(struct pwm_lookup *table, size_t num)
+{
+}
 #endif
 
 #endif /* __LINUX_PWM_H */
index d2dff22cf681bf6a0eee8789a5448cb5a17459e5..4187da51100631f157d508a1c121609a89204872 100644 (file)
@@ -63,7 +63,7 @@
  *
  *     0       RapidIO inbound doorbells
  *     1       RapidIO inbound mailboxes
- *     1       RapidIO outbound mailboxes
+ *     2       RapidIO outbound mailboxes
  */
 #define RIO_DOORBELL_RESOURCE  0
 #define RIO_INB_MBOX_RESOURCE  1
@@ -266,7 +266,6 @@ struct rio_mport {
 
 struct rio_id_table {
        u16 start;      /* logical minimal id */
-       u16 next;       /* hint for find */
        u32 max;        /* max number of IDs in table */
        spinlock_t lock;
        unsigned long *table;
index 7b600da9a635027393368715a43e0a2a44827db0..4bd6c06eb28edb13cc8a47698fd2b1df94d72f65 100644 (file)
@@ -201,6 +201,7 @@ static inline void *sg_virt(struct scatterlist *sg)
        return page_address(sg_page(sg)) + sg->offset;
 }
 
+int sg_nents(struct scatterlist *sg);
 struct scatterlist *sg_next(struct scatterlist *);
 struct scatterlist *sg_last(struct scatterlist *s, unsigned int);
 void sg_init_table(struct scatterlist *, unsigned int);
index c2070e92a9d6ef0acfb962b49f68167785093add..a83ca5816ecbc1e2f41a958c3f6830a50f8931b9 100644 (file)
@@ -2332,6 +2332,9 @@ extern int do_execve(const char *,
                     const char __user * const __user *, struct pt_regs *);
 extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *);
 struct task_struct *fork_idle(int);
+#ifdef CONFIG_GENERIC_KERNEL_THREAD
+extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+#endif
 
 extern void set_task_comm(struct task_struct *tsk, char *from);
 extern char *get_task_comm(char *to, struct task_struct *tsk);
index 5b50c4e1a7c25eeada9bb6756e2ebee3ad8b7473..05e88bdcf7d95cbe493bfa8ed890010bd0094890 100644 (file)
@@ -1411,8 +1411,8 @@ struct security_operations {
        int (*sb_kern_mount) (struct super_block *sb, int flags, void *data);
        int (*sb_show_options) (struct seq_file *m, struct super_block *sb);
        int (*sb_statfs) (struct dentry *dentry);
-       int (*sb_mount) (char *dev_name, struct path *path,
-                        char *type, unsigned long flags, void *data);
+       int (*sb_mount) (const char *dev_name, struct path *path,
+                        const char *type, unsigned long flags, void *data);
        int (*sb_umount) (struct vfsmount *mnt, int flags);
        int (*sb_pivotroot) (struct path *old_path,
                             struct path *new_path);
@@ -1694,8 +1694,8 @@ int security_sb_remount(struct super_block *sb, void *data);
 int security_sb_kern_mount(struct super_block *sb, int flags, void *data);
 int security_sb_show_options(struct seq_file *m, struct super_block *sb);
 int security_sb_statfs(struct dentry *dentry);
-int security_sb_mount(char *dev_name, struct path *path,
-                     char *type, unsigned long flags, void *data);
+int security_sb_mount(const char *dev_name, struct path *path,
+                     const char *type, unsigned long flags, void *data);
 int security_sb_umount(struct vfsmount *mnt, int flags);
 int security_sb_pivotroot(struct path *old_path, struct path *new_path);
 int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts);
@@ -1964,8 +1964,8 @@ static inline int security_sb_statfs(struct dentry *dentry)
        return 0;
 }
 
-static inline int security_sb_mount(char *dev_name, struct path *path,
-                                   char *type, unsigned long flags,
+static inline int security_sb_mount(const char *dev_name, struct path *path,
+                                   const char *type, unsigned long flags,
                                    void *data)
 {
        return 0;
index b33a3a1f205e45c747c9125a5b5920365ca2f8be..6a2c34e6d962658d0a1532959a06b5ddebe65087 100644 (file)
@@ -589,9 +589,6 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
        return __alloc_skb(size, priority, SKB_ALLOC_FCLONE, NUMA_NO_NODE);
 }
 
-extern void skb_recycle(struct sk_buff *skb);
-extern bool skb_recycle_check(struct sk_buff *skb, int skb_size);
-
 extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
 extern int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask);
 extern struct sk_buff *skb_clone(struct sk_buff *skb,
@@ -2645,27 +2642,6 @@ static inline void skb_checksum_none_assert(const struct sk_buff *skb)
 
 bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off);
 
-static inline bool skb_is_recycleable(const struct sk_buff *skb, int skb_size)
-{
-       if (irqs_disabled())
-               return false;
-
-       if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY)
-               return false;
-
-       if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE)
-               return false;
-
-       skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD);
-       if (skb_end_offset(skb) < skb_size)
-               return false;
-
-       if (skb_shared(skb) || skb_cloned(skb))
-               return false;
-
-       return true;
-}
-
 /**
  * skb_head_is_locked - Determine if the skb->head is locked down
  * @skb: skb to check
index 98df21164a863e9b131a15a263ff4ceb6754360f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1 +0,0 @@
-header-y += debug.h
index 523547ecfee2812c0f8d7fa069f7c8ac3f66ab2d..34206b84d8dac9208401c48e92713c1d8ca11a1f 100644 (file)
@@ -130,6 +130,8 @@ struct rpc_clnt     *rpc_bind_new_program(struct rpc_clnt *,
                                const struct rpc_program *, u32);
 void rpc_task_reset_client(struct rpc_task *task, struct rpc_clnt *clnt);
 struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
+struct rpc_clnt *rpc_clone_client_set_auth(struct rpc_clnt *,
+                               rpc_authflavor_t);
 void           rpc_shutdown_client(struct rpc_clnt *);
 void           rpc_release_client(struct rpc_clnt *);
 void           rpc_task_release_client(struct rpc_task *);
index a76cc20d98ce21531a6fcbd70e861bbfc5055c12..9385bd74c8604fb467979c16c164cdcd4723ec83 100644 (file)
@@ -5,28 +5,11 @@
  *
  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
  */
-
 #ifndef _LINUX_SUNRPC_DEBUG_H_
 #define _LINUX_SUNRPC_DEBUG_H_
 
-/*
- * RPC debug facilities
- */
-#define RPCDBG_XPRT            0x0001
-#define RPCDBG_CALL            0x0002
-#define RPCDBG_DEBUG           0x0004
-#define RPCDBG_NFS             0x0008
-#define RPCDBG_AUTH            0x0010
-#define RPCDBG_BIND            0x0020
-#define RPCDBG_SCHED           0x0040
-#define RPCDBG_TRANS           0x0080
-#define RPCDBG_SVCXPRT         0x0100
-#define RPCDBG_SVCDSP          0x0200
-#define RPCDBG_MISC            0x0400
-#define RPCDBG_CACHE           0x0800
-#define RPCDBG_ALL             0x7fff
+#include <uapi/linux/sunrpc/debug.h>
 
-#ifdef __KERNEL__
 
 /*
  * Enable RPC debugging/profiling.
@@ -87,24 +70,4 @@ void         rpc_register_sysctl(void);
 void           rpc_unregister_sysctl(void);
 #endif
 
-#endif /* __KERNEL__ */
-
-/*
- * Declarations for the sysctl debug interface, which allows to read or
- * change the debug flags for rpc, nfs, nfsd, and lockd. Since the sunrpc
- * module currently registers its sysctl table dynamically, the sysctl path
- * for module FOO is <CTL_SUNRPC, CTL_FOODEBUG>.
- */
-
-enum {
-       CTL_RPCDEBUG = 1,
-       CTL_NFSDEBUG,
-       CTL_NFSDDEBUG,
-       CTL_NLMDEBUG,
-       CTL_SLOTTABLE_UDP,
-       CTL_SLOTTABLE_TCP,
-       CTL_MIN_RESVPORT,
-       CTL_MAX_RESVPORT,
-};
-
 #endif /* _LINUX_SUNRPC_DEBUG_H_ */
index b3f64b12f1415f7e14d1f49cdeca4ccf7de20f0f..b05963f09ebf7b499902973a2707fad9aaa471e0 100644 (file)
@@ -114,7 +114,6 @@ void        svc_xprt_init(struct net *, struct svc_xprt_class *, struct svc_xprt *,
 int    svc_create_xprt(struct svc_serv *, const char *, struct net *,
                        const int, const unsigned short, int);
 void   svc_xprt_enqueue(struct svc_xprt *xprt);
-void   svc_xprt_received(struct svc_xprt *);
 void   svc_xprt_put(struct svc_xprt *xprt);
 void   svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt);
 void   svc_close_xprt(struct svc_xprt *xprt);
@@ -124,6 +123,7 @@ struct      svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name,
                        struct net *net, const sa_family_t af,
                        const unsigned short port);
 int    svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen);
+void   svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *xprt);
 
 static inline void svc_xprt_get(struct svc_xprt *xprt)
 {
@@ -166,8 +166,7 @@ static inline size_t svc_addr_len(const struct sockaddr *sa)
        case AF_INET6:
                return sizeof(struct sockaddr_in6);
        }
-
-       return 0;
+       BUG();
 }
 
 static inline unsigned short svc_xprt_local_port(const struct svc_xprt *xprt)
index cb4ac69e1f3356aeb96cdeed3ca83e106b45ba25..92ad02f0dcc0ea9409a09c1b3637e1f5c1869bc1 100644 (file)
@@ -39,9 +39,6 @@ int           svc_recv(struct svc_rqst *, long);
 int            svc_send(struct svc_rqst *);
 void           svc_drop(struct svc_rqst *);
 void           svc_sock_update_bufs(struct svc_serv *serv);
-int            svc_sock_names(struct svc_serv *serv, char *buf,
-                                       const size_t buflen,
-                                       const char *toclose);
 int            svc_addsock(struct svc_serv *serv, const int fd,
                                        char *name_return, const size_t len);
 void           svc_init_xprt_sock(void);
index bf8c49ff7530c7ee8b85d4a8b3ccef5de86ff308..951cb9b7d02b9167982135a6245972c18605f1a0 100644 (file)
@@ -173,8 +173,7 @@ struct rpc_xprt {
        unsigned int            min_reqs;       /* min number of slots */
        atomic_t                num_reqs;       /* total slots */
        unsigned long           state;          /* transport state */
-       unsigned char           shutdown   : 1, /* being shut down */
-                               resvport   : 1; /* use a reserved port */
+       unsigned char           resvport   : 1; /* use a reserved port */
        unsigned int            swapper;        /* we're swapping over this
                                                   transport */
        unsigned int            bind_index;     /* bind function index */
index 19439c75c5b255751e2467b5405861763f131fd5..727f0cd739213cc70054d3412b181527f504d2f2 100644 (file)
@@ -827,7 +827,15 @@ asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags,
                                  const char  __user *pathname);
 asmlinkage long sys_syncfs(int fd);
 
+#ifndef CONFIG_GENERIC_KERNEL_EXECVE
 int kernel_execve(const char *filename, const char *const argv[], const char *const envp[]);
+#else
+#define kernel_execve(filename, argv, envp) \
+       do_execve(filename, \
+               (const char __user *const __user *)argv, \
+               (const char __user *const __user *)envp, \
+               current_pt_regs())
+#endif
 
 
 asmlinkage long sys_perf_event_open(
index 67b501c302b20fa3cddfd605c1e45172f02c5500..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,7 +0,0 @@
-header-y += tc_gact.h
-header-y += tc_ipt.h
-header-y += tc_mirred.h
-header-y += tc_pedit.h
-header-y += tc_nat.h
-header-y += tc_skbedit.h
-header-y += tc_csum.h
index 4a58a1c32a0004c7b774f161636e3b98bc6d7a66..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,4 +0,0 @@
-header-y += tc_em_cmp.h
-header-y += tc_em_meta.h
-header-y += tc_em_nbyte.h
-header-y += tc_em_text.h
diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h
new file mode 100644 (file)
index 0000000..e1d558e
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * You SHOULD NOT be including this unless you're vsyscall
+ * handling code or timekeeping internal code!
+ */
+
+#ifndef _LINUX_TIMEKEEPER_INTERNAL_H
+#define _LINUX_TIMEKEEPER_INTERNAL_H
+
+#include <linux/clocksource.h>
+#include <linux/jiffies.h>
+#include <linux/time.h>
+
+/* Structure holding internal timekeeping values. */
+struct timekeeper {
+       /* Current clocksource used for timekeeping. */
+       struct clocksource      *clock;
+       /* NTP adjusted clock multiplier */
+       u32                     mult;
+       /* The shift value of the current clocksource. */
+       u32                     shift;
+       /* Number of clock cycles in one NTP interval. */
+       cycle_t                 cycle_interval;
+       /* Number of clock shifted nano seconds in one NTP interval. */
+       u64                     xtime_interval;
+       /* shifted nano seconds left over when rounding cycle_interval */
+       s64                     xtime_remainder;
+       /* Raw nano seconds accumulated per NTP interval. */
+       u32                     raw_interval;
+
+       /* Current CLOCK_REALTIME time in seconds */
+       u64                     xtime_sec;
+       /* Clock shifted nano seconds */
+       u64                     xtime_nsec;
+
+       /* Difference between accumulated time and NTP time in ntp
+        * shifted nano seconds. */
+       s64                     ntp_error;
+       /* Shift conversion between clock shifted nano seconds and
+        * ntp shifted nano seconds. */
+       u32                     ntp_error_shift;
+
+       /*
+        * wall_to_monotonic is what we need to add to xtime (or xtime corrected
+        * for sub jiffie times) to get to monotonic time.  Monotonic is pegged
+        * at zero at system boot time, so wall_to_monotonic will be negative,
+        * however, we will ALWAYS keep the tv_nsec part positive so we can use
+        * the usual normalization.
+        *
+        * wall_to_monotonic is moved after resume from suspend for the
+        * monotonic time not to jump. We need to add total_sleep_time to
+        * wall_to_monotonic to get the real boot based time offset.
+        *
+        * - wall_to_monotonic is no longer the boot time, getboottime must be
+        * used instead.
+        */
+       struct timespec         wall_to_monotonic;
+       /* Offset clock monotonic -> clock realtime */
+       ktime_t                 offs_real;
+       /* time spent in suspend */
+       struct timespec         total_sleep_time;
+       /* Offset clock monotonic -> clock boottime */
+       ktime_t                 offs_boot;
+       /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */
+       struct timespec         raw_time;
+       /* Seqlock for all timekeeper values */
+       seqlock_t               lock;
+};
+
+static inline struct timespec tk_xtime(struct timekeeper *tk)
+{
+       struct timespec ts;
+
+       ts.tv_sec = tk->xtime_sec;
+       ts.tv_nsec = (long)(tk->xtime_nsec >> tk->shift);
+       return ts;
+}
+
+
+#ifdef CONFIG_GENERIC_TIME_VSYSCALL
+
+extern void update_vsyscall(struct timekeeper *tk);
+extern void update_vsyscall_tz(void);
+
+#elif defined(CONFIG_GENERIC_TIME_VSYSCALL_OLD)
+
+extern void update_vsyscall_old(struct timespec *ts, struct timespec *wtm,
+                               struct clocksource *c, u32 mult);
+extern void update_vsyscall_tz(void);
+
+static inline void update_vsyscall(struct timekeeper *tk)
+{
+       struct timespec xt;
+
+       xt = tk_xtime(tk);
+       update_vsyscall_old(&xt, &tk->wall_to_monotonic, tk->clock, tk->mult);
+}
+
+#else
+
+static inline void update_vsyscall(struct timekeeper *tk)
+{
+}
+static inline void update_vsyscall_tz(void)
+{
+}
+#endif
+
+#endif /* _LINUX_TIMEKEEPER_INTERNAL_H */
index f87cf622317f5bc96f454b418ce1f36d3ade80b8..ddbbb7de894b4039d70003197737d5591649ad15 100644 (file)
@@ -68,6 +68,7 @@ struct usbnet {
 #              define EVENT_RX_PAUSED  5
 #              define EVENT_DEV_ASLEEP 6
 #              define EVENT_DEV_OPEN   7
+#              define EVENT_DEVICE_REPORT_IDLE 8
 };
 
 static inline struct usb_driver *driver_of(struct usb_interface *intf)
@@ -160,6 +161,7 @@ extern int usbnet_probe(struct usb_interface *, const struct usb_device_id *);
 extern int usbnet_suspend(struct usb_interface *, pm_message_t);
 extern int usbnet_resume(struct usb_interface *);
 extern void usbnet_disconnect(struct usb_interface *);
+extern void usbnet_device_suggests_idle(struct usbnet *dev);
 
 
 /* Drivers that reuse some of the standard USB CDC infrastructure
index 421d24c7f686ad407129bdd20fd6c7245cf3bbe6..f56c945cecd4ecb008eb713e1989b5af920dad3e 100644 (file)
@@ -349,6 +349,7 @@ enum v4l2_mpeg_video_multi_slice_mode {
 #define V4L2_CID_MPEG_VIDEO_VBV_SIZE                   (V4L2_CID_MPEG_BASE+222)
 #define V4L2_CID_MPEG_VIDEO_DEC_PTS                    (V4L2_CID_MPEG_BASE+223)
 #define V4L2_CID_MPEG_VIDEO_DEC_FRAME                  (V4L2_CID_MPEG_BASE+224)
+#define V4L2_CID_MPEG_VIDEO_VBV_DELAY                  (V4L2_CID_MPEG_BASE+225)
 
 #define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP            (V4L2_CID_MPEG_BASE+300)
 #define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP            (V4L2_CID_MPEG_BASE+301)
@@ -439,6 +440,46 @@ enum v4l2_mpeg_video_h264_vui_sar_idc {
        V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1            = 16,
        V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED       = 17,
 };
+#define V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING             (V4L2_CID_MPEG_BASE+368)
+#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0                (V4L2_CID_MPEG_BASE+369)
+#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE       (V4L2_CID_MPEG_BASE+370)
+enum v4l2_mpeg_video_h264_sei_fp_arrangement_type {
+       V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_CHECKERBOARD       = 0,
+       V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_COLUMN             = 1,
+       V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_ROW                = 2,
+       V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE       = 3,
+       V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TOP_BOTTOM         = 4,
+       V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TEMPORAL           = 5,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_FMO                   (V4L2_CID_MPEG_BASE+371)
+#define V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE          (V4L2_CID_MPEG_BASE+372)
+enum v4l2_mpeg_video_h264_fmo_map_type {
+       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES            = 0,
+       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES              = 1,
+       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_FOREGROUND_WITH_LEFT_OVER     = 2,
+       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_BOX_OUT                       = 3,
+       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN                   = 4,
+       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN                     = 5,
+       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_EXPLICIT                      = 6,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP       (V4L2_CID_MPEG_BASE+373)
+#define V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION  (V4L2_CID_MPEG_BASE+374)
+enum v4l2_mpeg_video_h264_fmo_change_dir {
+       V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT       = 0,
+       V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_LEFT        = 1,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE       (V4L2_CID_MPEG_BASE+375)
+#define V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH                (V4L2_CID_MPEG_BASE+376)
+#define V4L2_CID_MPEG_VIDEO_H264_ASO                   (V4L2_CID_MPEG_BASE+377)
+#define V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER       (V4L2_CID_MPEG_BASE+378)
+#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING           (V4L2_CID_MPEG_BASE+379)
+#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE      (V4L2_CID_MPEG_BASE+380)
+enum v4l2_mpeg_video_h264_hierarchical_coding_type {
+       V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B      = 0,
+       V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P      = 1,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER     (V4L2_CID_MPEG_BASE+381)
+#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP  (V4L2_CID_MPEG_BASE+382)
 #define V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP   (V4L2_CID_MPEG_BASE+400)
 #define V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP   (V4L2_CID_MPEG_BASE+401)
 #define V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP   (V4L2_CID_MPEG_BASE+402)
@@ -757,5 +798,6 @@ enum v4l2_jpeg_chroma_subsampling {
 
 #define V4L2_CID_LINK_FREQ                     (V4L2_CID_IMAGE_PROC_CLASS_BASE + 1)
 #define V4L2_CID_PIXEL_RATE                    (V4L2_CID_IMAGE_PROC_CLASS_BASE + 2)
+#define V4L2_CID_TEST_PATTERN                  (V4L2_CID_IMAGE_PROC_CLASS_BASE + 3)
 
 #endif
index 5ea7f753a3488757ab7f2a06132fd7a8b2ce46e8..7d64e0e1a18b2543b7bc35ad20e202e6b1282d60 100644 (file)
@@ -92,6 +92,11 @@ enum v4l2_mbus_pixelcode {
 
        /* JPEG compressed formats - next is 0x4002 */
        V4L2_MBUS_FMT_JPEG_1X8 = 0x4001,
+
+       /* Vendor specific formats - next is 0x5002 */
+
+       /* S5C73M3 sensor specific interleaved UYVY and JPEG */
+       V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8 = 0x5001,
 };
 
 /**
index 61395ef85a003a55ff8ce390bf52b582e4454db3..873adbe82988a8415cd25da1b4d7951873e22762 100644 (file)
@@ -366,7 +366,9 @@ struct v4l2_pix_format {
 
 /* two non contiguous planes - one Y, one Cr + Cb interleaved  */
 #define V4L2_PIX_FMT_NV12M   v4l2_fourcc('N', 'M', '1', '2') /* 12  Y/CbCr 4:2:0  */
+#define V4L2_PIX_FMT_NV21M   v4l2_fourcc('N', 'M', '2', '1') /* 21  Y/CrCb 4:2:0  */
 #define V4L2_PIX_FMT_NV12MT  v4l2_fourcc('T', 'M', '1', '2') /* 12  Y/CbCr 4:2:0 64x32 macroblocks */
+#define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') /* 12  Y/CbCr 4:2:0 16x16 macroblocks */
 
 /* three non contiguous planes - Y, Cb, Cr */
 #define V4L2_PIX_FMT_YUV420M v4l2_fourcc('Y', 'M', '1', '2') /* 12  YUV420 planar */
@@ -403,6 +405,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_MPEG     v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4 Multiplexed */
 #define V4L2_PIX_FMT_H264     v4l2_fourcc('H', '2', '6', '4') /* H264 with start codes */
 #define V4L2_PIX_FMT_H264_NO_SC v4l2_fourcc('A', 'V', 'C', '1') /* H264 without start codes */
+#define V4L2_PIX_FMT_H264_MVC v4l2_fourcc('M', '2', '6', '4') /* H264 MVC */
 #define V4L2_PIX_FMT_H263     v4l2_fourcc('H', '2', '6', '3') /* H263          */
 #define V4L2_PIX_FMT_MPEG1    v4l2_fourcc('M', 'P', 'G', '1') /* MPEG-1 ES     */
 #define V4L2_PIX_FMT_MPEG2    v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES     */
@@ -410,6 +413,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_XVID     v4l2_fourcc('X', 'V', 'I', 'D') /* Xvid           */
 #define V4L2_PIX_FMT_VC1_ANNEX_G v4l2_fourcc('V', 'C', '1', 'G') /* SMPTE 421M Annex G compliant stream */
 #define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */
+#define V4L2_PIX_FMT_VP8      v4l2_fourcc('V', 'P', '8', '0') /* VP8 */
 
 /*  Vendor-specific formats   */
 #define V4L2_PIX_FMT_CPIA1    v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
@@ -437,6 +441,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_KONICA420  v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */
 #define V4L2_PIX_FMT_JPGL      v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */
 #define V4L2_PIX_FMT_SE401      v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */
+#define V4L2_PIX_FMT_S5C_UYVY_JPG v4l2_fourcc('S', '5', 'C', 'I') /* S5C73M3 interleaved UYVY/JPEG */
 
 /*
  *     F O R M A T   E N U M E R A T I O N
index dc8d305b0e0501d05c92a8dacc527c0a31ff671f..d6b4440387b70a336d9da8af35e1224a20af04ba 100644 (file)
@@ -72,6 +72,7 @@ struct virtio_scsi_config {
 /* Feature Bits */
 #define VIRTIO_SCSI_F_INOUT                    0
 #define VIRTIO_SCSI_F_HOTPLUG                  1
+#define VIRTIO_SCSI_F_CHANGE                   2
 
 /* Response codes */
 #define VIRTIO_SCSI_S_OK                       0
@@ -108,6 +109,7 @@ struct virtio_scsi_config {
 #define VIRTIO_SCSI_T_NO_EVENT                 0
 #define VIRTIO_SCSI_T_TRANSPORT_RESET          1
 #define VIRTIO_SCSI_T_ASYNC_NOTIFY             2
+#define VIRTIO_SCSI_T_PARAM_CHANGE             3
 
 /* Reasons of transport reset event */
 #define VIRTIO_SCSI_EVT_RESET_HARD             0
index 3cb4f269bb095bce2af8d5da38f8c6b813934bea..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1 +0,0 @@
-header-y += i2400m.h
index 8bc1b3c0e6790501d1853e59841867f5709afed4..a7ca4884c46cc8a386a42a7d9f9eaae6c35dc8ba 100644 (file)
@@ -35,7 +35,7 @@ struct osd_config_info {
 struct vpbe_output {
        struct v4l2_output output;
        /*
-        * If output capabilities include dv_preset, list supported presets
+        * If output capabilities include dv_timings, list supported timings
         * below
         */
        char *subdev_name;
@@ -120,16 +120,16 @@ struct vpbe_device_ops {
        unsigned int (*get_output)(struct vpbe_device *vpbe_dev);
 
        /* Set DV preset at current output */
-       int (*s_dv_preset)(struct vpbe_device *vpbe_dev,
-                          struct v4l2_dv_preset *dv_preset);
+       int (*s_dv_timings)(struct vpbe_device *vpbe_dev,
+                          struct v4l2_dv_timings *dv_timings);
 
        /* Get DV presets supported at the output */
-       int (*g_dv_preset)(struct vpbe_device *vpbe_dev,
-                          struct v4l2_dv_preset *dv_preset);
+       int (*g_dv_timings)(struct vpbe_device *vpbe_dev,
+                          struct v4l2_dv_timings *dv_timings);
 
        /* Enumerate the DV Presets supported at the output */
-       int (*enum_dv_presets)(struct vpbe_device *vpbe_dev,
-                              struct v4l2_dv_enum_preset *preset_info);
+       int (*enum_dv_timings)(struct vpbe_device *vpbe_dev,
+                              struct v4l2_enum_dv_timings *timings_info);
 
        /* Set std at the output */
        int (*s_std)(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id);
index 727f55170e41cc7dd74accb196b4a75776ed0ce2..9b85396514be33390705fdc34c4bad826fd609e1 100644 (file)
@@ -32,11 +32,6 @@ enum vpbe_enc_timings_type {
        VPBE_ENC_TIMINGS_INVALID = 0x8,
 };
 
-union vpbe_timings {
-       v4l2_std_id std_id;
-       unsigned int dv_preset;
-};
-
 /*
  * struct vpbe_enc_mode_info
  * @name: ptr to name string of the standard, "NTSC", "PAL" etc
@@ -73,7 +68,8 @@ union vpbe_timings {
 struct vpbe_enc_mode_info {
        unsigned char *name;
        enum vpbe_enc_timings_type timings_type;
-       union vpbe_timings timings;
+       v4l2_std_id std_id;
+       struct v4l2_dv_timings dv_timings;
        unsigned int interlaced;
        unsigned int xres;
        unsigned int yres;
index 6b57334f402996341e584fcc0177054140663ba5..cc78c2eb16da25a689ece25ad1dfc931c6dcf211 100644 (file)
@@ -32,7 +32,7 @@ struct venc_platform_data {
        int (*setup_pinmux)(enum v4l2_mbus_pixelcode if_type,
                            int field);
        int (*setup_clock)(enum vpbe_enc_timings_type type,
-                          unsigned int mode);
+                          unsigned int pixclock);
        int (*setup_if_config)(enum v4l2_mbus_pixelcode pixcode);
        /* Number of LCD outputs supported */
        int num_lcd_outputs;
index d8f6ab1943e4e492679b1b4ae58ac1244496cc72..3882e0675ccfd45e718dbd8dc38bedd51af02120 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/i2c.h>
 
 #define VPIF_CAPTURE_MAX_CHANNELS      2
+#define VPIF_DISPLAY_MAX_CHANNELS      2
 
 enum vpif_if_type {
        VPIF_IF_BT656,
@@ -37,29 +38,38 @@ struct vpif_interface {
 struct vpif_subdev_info {
        const char *name;
        struct i2c_board_info board_info;
-       u32 input;
-       u32 output;
-       unsigned can_route:1;
-       struct vpif_interface vpif_if;
+};
+
+struct vpif_output {
+       struct v4l2_output output;
+       const char *subdev_name;
+       u32 input_route;
+       u32 output_route;
+};
+
+struct vpif_display_chan_config {
+       const struct vpif_output *outputs;
+       int output_count;
+       bool clip_en;
 };
 
 struct vpif_display_config {
        int (*set_clock)(int, int);
        struct vpif_subdev_info *subdevinfo;
        int subdev_count;
-       const char **output;
-       int output_count;
+       struct vpif_display_chan_config chan_config[VPIF_DISPLAY_MAX_CHANNELS];
        const char *card_name;
-       bool ch2_clip_en;
-       bool ch3_clip_en;
 };
 
 struct vpif_input {
        struct v4l2_input input;
        const char *subdev_name;
+       u32 input_route;
+       u32 output_route;
 };
 
 struct vpif_capture_chan_config {
+       struct vpif_interface vpif_if;
        const struct vpif_input *inputs;
        int input_count;
 };
index 09421a611d73df78ed1d3d6af80571e0511956ce..eaea62a382f886a414b803d4f86119117a46f262 100644 (file)
@@ -30,7 +30,6 @@ struct i2c_board_info;
  * @board_info: pointer to I2C subdevice's board info
  * @clk_frequency: frequency of the clock the host interface provides to sensor
  * @bus_type: determines bus type, MIPI, ITU-R BT.601 etc.
- * @csi_data_align: MIPI-CSI interface data alignment in bits
  * @i2c_bus_num: i2c control bus id the sensor is attached to
  * @mux_id: FIMC camera interface multiplexer index (separate for MIPI and ITU)
  * @clk_id: index of the SoC peripheral clock for sensors
@@ -40,7 +39,6 @@ struct s5p_fimc_isp_info {
        struct i2c_board_info *board_info;
        unsigned long clk_frequency;
        enum cam_bus_type bus_type;
-       u16 csi_data_align;
        u16 i2c_bus_num;
        u16 mux_id;
        u16 flags;
index 801adb466bd25cdde14eac5e7314ed4061f52707..96509119f28f42daa6ce3794cea050f4d8768603 100644 (file)
@@ -351,6 +351,29 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
                        const struct v4l2_ctrl_ops *ops,
                        u32 id, s32 max, s32 mask, s32 def);
 
+/** v4l2_ctrl_new_std_menu_items() - Create a new standard V4L2 menu control
+  * with driver specific menu.
+  * @hdl:      The control handler.
+  * @ops:      The control ops.
+  * @id:       The control ID.
+  * @max:      The control's maximum value.
+  * @mask:     The control's skip mask for menu controls. This makes it
+  *            easy to skip menu items that are not valid. If bit X is set,
+  *            then menu item X is skipped. Of course, this only works for
+  *            menus with <= 32 menu items. There are no menus that come
+  *            close to that number, so this is OK. Should we ever need more,
+  *            then this will have to be extended to a u64 or a bit array.
+  * @def:      The control's default value.
+  * @qmenu:    The new menu.
+  *
+  * Same as v4l2_ctrl_new_std_menu(), but @qmenu will be the driver specific
+  * menu of this control.
+  *
+  */
+struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
+                       const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
+                       s32 mask, s32 def, const char * const *qmenu);
+
 /** v4l2_ctrl_new_int_menu() - Create a new standard V4L2 integer menu control.
   * @hdl:      The control handler.
   * @ops:      The control ops.
index 2ecd7377153bb9bf7dbf5f5706466c6bf42bfdbf..b137a5e1151a5be0ad55c036f721ff6cb4bbe4e4 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef _V4L2_SUBDEV_H
 #define _V4L2_SUBDEV_H
 
+#include <linux/types.h>
 #include <linux/v4l2-subdev.h>
 #include <media/media-entity.h>
 #include <media/v4l2-common.h>
@@ -45,6 +46,7 @@ struct v4l2_fh;
 struct v4l2_subdev;
 struct v4l2_subdev_fh;
 struct tuner_setup;
+struct v4l2_mbus_frame_desc;
 
 /* decode_vbi_line */
 struct v4l2_decode_vbi_line {
@@ -226,6 +228,36 @@ struct v4l2_subdev_audio_ops {
        int (*s_stream)(struct v4l2_subdev *sd, int enable);
 };
 
+/* Indicates the @length field specifies maximum data length. */
+#define V4L2_MBUS_FRAME_DESC_FL_LEN_MAX                (1U << 0)
+/* Indicates user defined data format, i.e. non standard frame format. */
+#define V4L2_MBUS_FRAME_DESC_FL_BLOB           (1U << 1)
+
+/**
+ * struct v4l2_mbus_frame_desc_entry - media bus frame description structure
+ * @flags: V4L2_MBUS_FRAME_DESC_FL_* flags
+ * @pixelcode: media bus pixel code, valid if FRAME_DESC_FL_BLOB is not set
+ * @length: number of octets per frame, valid for compressed or unspecified
+ *          formats
+ */
+struct v4l2_mbus_frame_desc_entry {
+       u16 flags;
+       u32 pixelcode;
+       u32 length;
+};
+
+#define V4L2_FRAME_DESC_ENTRY_MAX      4
+
+/**
+ * struct v4l2_mbus_frame_desc - media bus data frame description
+ * @entry: frame descriptors array
+ * @num_entries: number of entries in @entry array
+ */
+struct v4l2_mbus_frame_desc {
+       struct v4l2_mbus_frame_desc_entry entry[V4L2_FRAME_DESC_ENTRY_MAX];
+       unsigned short num_entries;
+};
+
 /*
    s_std_output: set v4l2_std_id for video OUTPUT devices. This is ignored by
        video input devices.
@@ -274,6 +306,10 @@ struct v4l2_subdev_audio_ops {
    s_mbus_config: set a certain mediabus configuration. This operation is added
        for compatibility with soc-camera drivers and should not be used by new
        software.
+
+   s_rx_buffer: set a host allocated memory buffer for the subdev. The subdev
+       can adjust @size to a lower value and must not write more data to the
+       buffer starting at @data than the original value of @size.
  */
 struct v4l2_subdev_video_ops {
        int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
@@ -327,6 +363,8 @@ struct v4l2_subdev_video_ops {
                             struct v4l2_mbus_config *cfg);
        int (*s_mbus_config)(struct v4l2_subdev *sd,
                             const struct v4l2_mbus_config *cfg);
+       int (*s_rx_buffer)(struct v4l2_subdev *sd, void *buf,
+                          unsigned int *size);
 };
 
 /*
@@ -455,6 +493,12 @@ struct v4l2_subdev_ir_ops {
                                struct v4l2_subdev_ir_parameters *params);
 };
 
+/**
+ * struct v4l2_subdev_pad_ops - v4l2-subdev pad level operations
+ * @get_frame_desc: get the current low level media bus frame parameters.
+ * @get_frame_desc: set the low level media bus frame parameters, @fd array
+ *                  may be adjusted by the subdev driver to device capabilities.
+ */
 struct v4l2_subdev_pad_ops {
        int (*enum_mbus_code)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
                              struct v4l2_subdev_mbus_code_enum *code);
@@ -483,6 +527,10 @@ struct v4l2_subdev_pad_ops {
                             struct v4l2_subdev_format *source_fmt,
                             struct v4l2_subdev_format *sink_fmt);
 #endif /* CONFIG_MEDIA_CONTROLLER */
+       int (*get_frame_desc)(struct v4l2_subdev *sd, unsigned int pad,
+                             struct v4l2_mbus_frame_desc *fd);
+       int (*set_frame_desc)(struct v4l2_subdev *sd, unsigned int pad,
+                             struct v4l2_mbus_frame_desc *fd);
 };
 
 struct v4l2_subdev_ops {
index 192f8fb7d5463318c5b8d5e78c8d60738983d26c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,5 +0,0 @@
-header-y += inftl-user.h
-header-y += mtd-abi.h
-header-y += mtd-user.h
-header-y += nftl-user.h
-header-y += ubi-user.h
index e1dd5082ec7e43605e66ae0c48789ed1b4e68e35..628e11b98c580d7f66ace375f5a4e0598d03b471 100644 (file)
@@ -21,6 +21,7 @@ struct flowi_common {
        __u8    flowic_flags;
 #define FLOWI_FLAG_ANYSRC              0x01
 #define FLOWI_FLAG_CAN_SLEEP           0x02
+#define FLOWI_FLAG_KNOWN_NH            0x04
        __u32   flowic_secid;
 };
 
index da22243d27600cd66b5fb70da61f5cadc05d5468..bc40b633a5c4dc0e763c5c8c4ff123135160dc04 100644 (file)
@@ -48,7 +48,8 @@ struct rtable {
        int                     rt_genid;
        unsigned int            rt_flags;
        __u16                   rt_type;
-       __u16                   rt_is_input;
+       __u8                    rt_is_input;
+       __u8                    rt_uses_gateway;
 
        int                     rt_iif;
 
index 3c5363ab867b263e24d1c94da2714be532236795..bd3d8b24b42024f848ffd0c55f2dc58dc6de1b28 100644 (file)
@@ -39,6 +39,7 @@ struct rdma_cm_id_stats {
 
 struct ibnl_client_cbs {
        int (*dump)(struct sk_buff *skb, struct netlink_callback *nlcb);
+       struct module *module;
 };
 
 int ibnl_init(void);
index 0d7d67e96d438dc1dd247691544fc8b0de50b416..9c8702942b611f981615c8a780cea0ffc5e5ce50 100644 (file)
@@ -127,6 +127,9 @@ struct fcp_txrdy {
  *
  * All response frames will always contain the fcp_resp template.  Some
  * will also include the fcp_resp_len template.
+ *
+ * From Table 23, the FCP_RSP_INFO can either be 4 bytes or 8 bytes, both
+ * are valid length.
  */
 struct fcp_resp {
        __u8            _fr_resvd[8];   /* reserved */
@@ -156,6 +159,9 @@ struct fcp_resp_rsp_info {
     __u8      _fr_resvd2[4];      /* reserved */
 };
 
+#define FCP_RESP_RSP_INFO_LEN4    4 /* without reserved field */
+#define FCP_RESP_RSP_INFO_LEN8    8 /* with reserved field */
+
 struct fcp_resp_with_ext {
        struct fcp_resp resp;
        struct fcp_resp_ext ext;
index 22b07cc99808562c86a3de2728ec0557291e56dc..8742d853a3b892b3caa54608d73c67f08dd544bd 100644 (file)
@@ -327,7 +327,6 @@ struct fcoe_percpu_s {
  * @lport:                    The associated local port
  * @fcoe_pending_queue:               The pending Rx queue of skbs
  * @fcoe_pending_queue_active: Indicates if the pending queue is active
- * @priority:                 Packet priority (DCB)
  * @max_queue_depth:          Max queue depth of pending queue
  * @min_queue_depth:          Min queue depth of pending queue
  * @timer:                    The queue timer
@@ -343,7 +342,6 @@ struct fcoe_port {
        struct fc_lport       *lport;
        struct sk_buff_head   fcoe_pending_queue;
        u8                    fcoe_pending_queue_active;
-       u8                    priority;
        u32                   max_queue_depth;
        u32                   min_queue_depth;
        struct timer_list     timer;
index ac06cc595890ef87a8e01632f5872ab11e4057f2..de5f5d8f1f8a9b84e6b7306b51ac02e75821533f 100644 (file)
@@ -132,18 +132,10 @@ struct scsi_cmnd {
        unsigned char tag;      /* SCSI-II queued command tag */
 };
 
+/* make sure not to use it with REQ_TYPE_BLOCK_PC commands */
 static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd)
 {
-       struct scsi_driver **sdp;
-
-       if (!cmd->request->rq_disk)
-               return NULL;
-
-       sdp = (struct scsi_driver **)cmd->request->rq_disk->private_data;
-       if (!sdp)
-               return NULL;
-
-       return *sdp;
+       return *(struct scsi_driver **)cmd->request->rq_disk->private_data;
 }
 
 extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t);
index 941c84bf1065f406cfbc3eeb5f4b09e4fdcd58ec..2acd54018b64dd60a271ebd618fc02a0634e1b85 100644 (file)
@@ -13,9 +13,6 @@ struct se_subsystem_api {
 
        u8 transport_type;
 
-       unsigned int fua_write_emulated : 1;
-       unsigned int write_cache_emulated : 1;
-
        int (*attach_hba)(struct se_hba *, u32);
        void (*detach_hba)(struct se_hba *);
        int (*pmode_enable_hba)(struct se_hba *, unsigned long);
index 69fb3cfd02d7f2acc0d656b458287d4d89666f82..81ddb4ae6c3fe69743a5dda9710264ae68b4f566 100644 (file)
@@ -62,8 +62,6 @@ struct target_core_fabric_ops {
        int (*queue_data_in)(struct se_cmd *);
        int (*queue_status)(struct se_cmd *);
        int (*queue_tm_rsp)(struct se_cmd *);
-       u16 (*set_fabric_sense_len)(struct se_cmd *, u32);
-       u16 (*get_fabric_sense_len)(void);
        /*
         * fabric module calls for target_core_fabric_configfs.c
         */
@@ -102,6 +100,9 @@ void        transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *,
                struct se_session *, u32, int, int, unsigned char *);
 int    transport_lookup_cmd_lun(struct se_cmd *, u32);
 int    target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *);
+int    target_submit_cmd_map_sgls(struct se_cmd *, struct se_session *,
+               unsigned char *, unsigned char *, u32, u32, int, int, int,
+               struct scatterlist *, u32, struct scatterlist *, u32);
 int    target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *,
                unsigned char *, u32, u32, int, int, int);
 int    target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
index 91b91e8056737878e71897b9e9e96d000b722d52..54fab041b22ab7a5102879a1b82ac5b4f97966df 100644 (file)
@@ -445,6 +445,7 @@ TRACE_EVENT(btrfs_delayed_tree_ref,
                __field(        u64,  ref_root          )
                __field(        int,  level             )
                __field(        int,  type              )
+               __field(        u64,  seq               )
        ),
 
        TP_fast_assign(
@@ -455,17 +456,19 @@ TRACE_EVENT(btrfs_delayed_tree_ref,
                __entry->ref_root       = full_ref->root;
                __entry->level          = full_ref->level;
                __entry->type           = ref->type;
+               __entry->seq            = ref->seq;
        ),
 
        TP_printk("bytenr = %llu, num_bytes = %llu, action = %s, "
                  "parent = %llu(%s), ref_root = %llu(%s), level = %d, "
-                 "type = %s",
+                 "type = %s, seq = %llu",
                  (unsigned long long)__entry->bytenr,
                  (unsigned long long)__entry->num_bytes,
                  show_ref_action(__entry->action),
                  show_root_type(__entry->parent),
                  show_root_type(__entry->ref_root),
-                 __entry->level, show_ref_type(__entry->type))
+                 __entry->level, show_ref_type(__entry->type),
+                 (unsigned long long)__entry->seq)
 );
 
 TRACE_EVENT(btrfs_delayed_data_ref,
@@ -485,6 +488,7 @@ TRACE_EVENT(btrfs_delayed_data_ref,
                __field(        u64,  owner             )
                __field(        u64,  offset            )
                __field(        int,  type              )
+               __field(        u64,  seq               )
        ),
 
        TP_fast_assign(
@@ -496,11 +500,12 @@ TRACE_EVENT(btrfs_delayed_data_ref,
                __entry->owner          = full_ref->objectid;
                __entry->offset         = full_ref->offset;
                __entry->type           = ref->type;
+               __entry->seq            = ref->seq;
        ),
 
        TP_printk("bytenr = %llu, num_bytes = %llu, action = %s, "
                  "parent = %llu(%s), ref_root = %llu(%s), owner = %llu, "
-                 "offset = %llu, type = %s",
+                 "offset = %llu, type = %s, seq = %llu",
                  (unsigned long long)__entry->bytenr,
                  (unsigned long long)__entry->num_bytes,
                  show_ref_action(__entry->action),
@@ -508,7 +513,8 @@ TRACE_EVENT(btrfs_delayed_data_ref,
                  show_root_type(__entry->ref_root),
                  (unsigned long long)__entry->owner,
                  (unsigned long long)__entry->offset,
-                 show_ref_type(__entry->type))
+                 show_ref_type(__entry->type),
+                 (unsigned long long)__entry->seq)
 );
 
 TRACE_EVENT(btrfs_delayed_ref_head,
index aafaa5aa54d46bb9a93a8137a22344408298223f..43396612d3a322dae3cb99f00719bfb15001c476 100644 (file)
@@ -1 +1,3 @@
 # UAPI Header export list
+header-y += caif_socket.h
+header-y += if_caif.h
index aafaa5aa54d46bb9a93a8137a22344408298223f..21c91bf25a298c9090d103e1fe41406e72a7ae20 100644 (file)
@@ -1 +1,6 @@
 # UAPI Header export list
+header-y += bcm.h
+header-y += error.h
+header-y += gw.h
+header-y += netlink.h
+header-y += raw.h
index aafaa5aa54d46bb9a93a8137a22344408298223f..89e52850bf29c400d72541991b4877a9d499581d 100644 (file)
@@ -1 +1,2 @@
 # UAPI Header export list
+header-y += capicmd.h
index aafaa5aa54d46bb9a93a8137a22344408298223f..8c1d2cb75e330ae605277aa70ec44415a53f3428 100644 (file)
@@ -1 +1,2 @@
 # UAPI Header export list
+header-y += ioctl.h
index 4afbace8e86900976956ec4035416cd41bebcccb..08f555fef13fee2946951983ae7cf2e210aa05cc 100644 (file)
@@ -1,2 +1,78 @@
 # UAPI Header export list
 header-y += ipset/
+header-y += nf_conntrack_common.h
+header-y += nf_conntrack_ftp.h
+header-y += nf_conntrack_sctp.h
+header-y += nf_conntrack_tcp.h
+header-y += nf_conntrack_tuple_common.h
+header-y += nf_nat.h
+header-y += nfnetlink.h
+header-y += nfnetlink_acct.h
+header-y += nfnetlink_compat.h
+header-y += nfnetlink_conntrack.h
+header-y += nfnetlink_cthelper.h
+header-y += nfnetlink_cttimeout.h
+header-y += nfnetlink_log.h
+header-y += nfnetlink_queue.h
+header-y += x_tables.h
+header-y += xt_AUDIT.h
+header-y += xt_CHECKSUM.h
+header-y += xt_CLASSIFY.h
+header-y += xt_CONNMARK.h
+header-y += xt_CONNSECMARK.h
+header-y += xt_CT.h
+header-y += xt_DSCP.h
+header-y += xt_IDLETIMER.h
+header-y += xt_LED.h
+header-y += xt_LOG.h
+header-y += xt_MARK.h
+header-y += xt_NFLOG.h
+header-y += xt_NFQUEUE.h
+header-y += xt_RATEEST.h
+header-y += xt_SECMARK.h
+header-y += xt_TCPMSS.h
+header-y += xt_TCPOPTSTRIP.h
+header-y += xt_TEE.h
+header-y += xt_TPROXY.h
+header-y += xt_addrtype.h
+header-y += xt_cluster.h
+header-y += xt_comment.h
+header-y += xt_connbytes.h
+header-y += xt_connlimit.h
+header-y += xt_connmark.h
+header-y += xt_conntrack.h
+header-y += xt_cpu.h
+header-y += xt_dccp.h
+header-y += xt_devgroup.h
+header-y += xt_dscp.h
+header-y += xt_ecn.h
+header-y += xt_esp.h
+header-y += xt_hashlimit.h
+header-y += xt_helper.h
+header-y += xt_iprange.h
+header-y += xt_ipvs.h
+header-y += xt_length.h
+header-y += xt_limit.h
+header-y += xt_mac.h
+header-y += xt_mark.h
+header-y += xt_multiport.h
+header-y += xt_nfacct.h
+header-y += xt_osf.h
+header-y += xt_owner.h
+header-y += xt_physdev.h
+header-y += xt_pkttype.h
+header-y += xt_policy.h
+header-y += xt_quota.h
+header-y += xt_rateest.h
+header-y += xt_realm.h
+header-y += xt_recent.h
+header-y += xt_sctp.h
+header-y += xt_set.h
+header-y += xt_socket.h
+header-y += xt_state.h
+header-y += xt_statistic.h
+header-y += xt_string.h
+header-y += xt_tcpmss.h
+header-y += xt_tcpudp.h
+header-y += xt_time.h
+header-y += xt_u32.h
index aafaa5aa54d46bb9a93a8137a22344408298223f..d2680423d9abbe0a3e4bd755f0c27e4eb66dacad 100644 (file)
@@ -1 +1,5 @@
 # UAPI Header export list
+header-y += ip_set.h
+header-y += ip_set_bitmap.h
+header-y += ip_set_hash.h
+header-y += ip_set_list.h
diff --git a/include/uapi/linux/netfilter/ipset/ip_set.h b/include/uapi/linux/netfilter/ipset/ip_set.h
new file mode 100644 (file)
index 0000000..fbee428
--- /dev/null
@@ -0,0 +1,231 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ *                         Patrick Schaaf <bof@bof.de>
+ *                         Martin Josefsson <gandalf@wlug.westbo.se>
+ * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * 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 _UAPI_IP_SET_H
+#define _UAPI_IP_SET_H
+
+
+#include <linux/types.h>
+
+/* The protocol version */
+#define IPSET_PROTOCOL         6
+
+/* The max length of strings including NUL: set and type identifiers */
+#define IPSET_MAXNAMELEN       32
+
+/* Message types and commands */
+enum ipset_cmd {
+       IPSET_CMD_NONE,
+       IPSET_CMD_PROTOCOL,     /* 1: Return protocol version */
+       IPSET_CMD_CREATE,       /* 2: Create a new (empty) set */
+       IPSET_CMD_DESTROY,      /* 3: Destroy a (empty) set */
+       IPSET_CMD_FLUSH,        /* 4: Remove all elements from a set */
+       IPSET_CMD_RENAME,       /* 5: Rename a set */
+       IPSET_CMD_SWAP,         /* 6: Swap two sets */
+       IPSET_CMD_LIST,         /* 7: List sets */
+       IPSET_CMD_SAVE,         /* 8: Save sets */
+       IPSET_CMD_ADD,          /* 9: Add an element to a set */
+       IPSET_CMD_DEL,          /* 10: Delete an element from a set */
+       IPSET_CMD_TEST,         /* 11: Test an element in a set */
+       IPSET_CMD_HEADER,       /* 12: Get set header data only */
+       IPSET_CMD_TYPE,         /* 13: Get set type */
+       IPSET_MSG_MAX,          /* Netlink message commands */
+
+       /* Commands in userspace: */
+       IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */
+       IPSET_CMD_HELP,         /* 15: Get help */
+       IPSET_CMD_VERSION,      /* 16: Get program version */
+       IPSET_CMD_QUIT,         /* 17: Quit from interactive mode */
+
+       IPSET_CMD_MAX,
+
+       IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */
+};
+
+/* Attributes at command level */
+enum {
+       IPSET_ATTR_UNSPEC,
+       IPSET_ATTR_PROTOCOL,    /* 1: Protocol version */
+       IPSET_ATTR_SETNAME,     /* 2: Name of the set */
+       IPSET_ATTR_TYPENAME,    /* 3: Typename */
+       IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */
+       IPSET_ATTR_REVISION,    /* 4: Settype revision */
+       IPSET_ATTR_FAMILY,      /* 5: Settype family */
+       IPSET_ATTR_FLAGS,       /* 6: Flags at command level */
+       IPSET_ATTR_DATA,        /* 7: Nested attributes */
+       IPSET_ATTR_ADT,         /* 8: Multiple data containers */
+       IPSET_ATTR_LINENO,      /* 9: Restore lineno */
+       IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */
+       IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
+       __IPSET_ATTR_CMD_MAX,
+};
+#define IPSET_ATTR_CMD_MAX     (__IPSET_ATTR_CMD_MAX - 1)
+
+/* CADT specific attributes */
+enum {
+       IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,
+       IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,
+       IPSET_ATTR_IP_TO,       /* 2 */
+       IPSET_ATTR_CIDR,        /* 3 */
+       IPSET_ATTR_PORT,        /* 4 */
+       IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,
+       IPSET_ATTR_PORT_TO,     /* 5 */
+       IPSET_ATTR_TIMEOUT,     /* 6 */
+       IPSET_ATTR_PROTO,       /* 7 */
+       IPSET_ATTR_CADT_FLAGS,  /* 8 */
+       IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO,     /* 9 */
+       /* Reserve empty slots */
+       IPSET_ATTR_CADT_MAX = 16,
+       /* Create-only specific attributes */
+       IPSET_ATTR_GC,
+       IPSET_ATTR_HASHSIZE,
+       IPSET_ATTR_MAXELEM,
+       IPSET_ATTR_NETMASK,
+       IPSET_ATTR_PROBES,
+       IPSET_ATTR_RESIZE,
+       IPSET_ATTR_SIZE,
+       /* Kernel-only */
+       IPSET_ATTR_ELEMENTS,
+       IPSET_ATTR_REFERENCES,
+       IPSET_ATTR_MEMSIZE,
+
+       __IPSET_ATTR_CREATE_MAX,
+};
+#define IPSET_ATTR_CREATE_MAX  (__IPSET_ATTR_CREATE_MAX - 1)
+
+/* ADT specific attributes */
+enum {
+       IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + 1,
+       IPSET_ATTR_NAME,
+       IPSET_ATTR_NAMEREF,
+       IPSET_ATTR_IP2,
+       IPSET_ATTR_CIDR2,
+       IPSET_ATTR_IP2_TO,
+       IPSET_ATTR_IFACE,
+       __IPSET_ATTR_ADT_MAX,
+};
+#define IPSET_ATTR_ADT_MAX     (__IPSET_ATTR_ADT_MAX - 1)
+
+/* IP specific attributes */
+enum {
+       IPSET_ATTR_IPADDR_IPV4 = IPSET_ATTR_UNSPEC + 1,
+       IPSET_ATTR_IPADDR_IPV6,
+       __IPSET_ATTR_IPADDR_MAX,
+};
+#define IPSET_ATTR_IPADDR_MAX  (__IPSET_ATTR_IPADDR_MAX - 1)
+
+/* Error codes */
+enum ipset_errno {
+       IPSET_ERR_PRIVATE = 4096,
+       IPSET_ERR_PROTOCOL,
+       IPSET_ERR_FIND_TYPE,
+       IPSET_ERR_MAX_SETS,
+       IPSET_ERR_BUSY,
+       IPSET_ERR_EXIST_SETNAME2,
+       IPSET_ERR_TYPE_MISMATCH,
+       IPSET_ERR_EXIST,
+       IPSET_ERR_INVALID_CIDR,
+       IPSET_ERR_INVALID_NETMASK,
+       IPSET_ERR_INVALID_FAMILY,
+       IPSET_ERR_TIMEOUT,
+       IPSET_ERR_REFERENCED,
+       IPSET_ERR_IPADDR_IPV4,
+       IPSET_ERR_IPADDR_IPV6,
+
+       /* Type specific error codes */
+       IPSET_ERR_TYPE_SPECIFIC = 4352,
+};
+
+/* Flags at command level */
+enum ipset_cmd_flags {
+       IPSET_FLAG_BIT_EXIST    = 0,
+       IPSET_FLAG_EXIST        = (1 << IPSET_FLAG_BIT_EXIST),
+       IPSET_FLAG_BIT_LIST_SETNAME = 1,
+       IPSET_FLAG_LIST_SETNAME = (1 << IPSET_FLAG_BIT_LIST_SETNAME),
+       IPSET_FLAG_BIT_LIST_HEADER = 2,
+       IPSET_FLAG_LIST_HEADER  = (1 << IPSET_FLAG_BIT_LIST_HEADER),
+       IPSET_FLAG_CMD_MAX = 15,        /* Lower half */
+};
+
+/* Flags at CADT attribute level */
+enum ipset_cadt_flags {
+       IPSET_FLAG_BIT_BEFORE   = 0,
+       IPSET_FLAG_BEFORE       = (1 << IPSET_FLAG_BIT_BEFORE),
+       IPSET_FLAG_BIT_PHYSDEV  = 1,
+       IPSET_FLAG_PHYSDEV      = (1 << IPSET_FLAG_BIT_PHYSDEV),
+       IPSET_FLAG_BIT_NOMATCH  = 2,
+       IPSET_FLAG_NOMATCH      = (1 << IPSET_FLAG_BIT_NOMATCH),
+       IPSET_FLAG_CADT_MAX     = 15,   /* Upper half */
+};
+
+/* Commands with settype-specific attributes */
+enum ipset_adt {
+       IPSET_ADD,
+       IPSET_DEL,
+       IPSET_TEST,
+       IPSET_ADT_MAX,
+       IPSET_CREATE = IPSET_ADT_MAX,
+       IPSET_CADT_MAX,
+};
+
+/* Sets are identified by an index in kernel space. Tweak with ip_set_id_t
+ * and IPSET_INVALID_ID if you want to increase the max number of sets.
+ */
+typedef __u16 ip_set_id_t;
+
+#define IPSET_INVALID_ID               65535
+
+enum ip_set_dim {
+       IPSET_DIM_ZERO = 0,
+       IPSET_DIM_ONE,
+       IPSET_DIM_TWO,
+       IPSET_DIM_THREE,
+       /* Max dimension in elements.
+        * If changed, new revision of iptables match/target is required.
+        */
+       IPSET_DIM_MAX = 6,
+       IPSET_BIT_RETURN_NOMATCH = 7,
+};
+
+/* Option flags for kernel operations */
+enum ip_set_kopt {
+       IPSET_INV_MATCH = (1 << IPSET_DIM_ZERO),
+       IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE),
+       IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO),
+       IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE),
+       IPSET_RETURN_NOMATCH = (1 << IPSET_BIT_RETURN_NOMATCH),
+};
+
+
+/* Interface to iptables/ip6tables */
+
+#define SO_IP_SET              83
+
+union ip_set_name_index {
+       char name[IPSET_MAXNAMELEN];
+       ip_set_id_t index;
+};
+
+#define IP_SET_OP_GET_BYNAME   0x00000006      /* Get set index by name */
+struct ip_set_req_get_set {
+       unsigned int op;
+       unsigned int version;
+       union ip_set_name_index set;
+};
+
+#define IP_SET_OP_GET_BYINDEX  0x00000007      /* Get set name by index */
+/* Uses ip_set_req_get_set */
+
+#define IP_SET_OP_VERSION      0x00000100      /* Ask kernel version */
+struct ip_set_req_version {
+       unsigned int op;
+       unsigned int version;
+};
+
+#endif /* _UAPI_IP_SET_H */
diff --git a/include/uapi/linux/netfilter/ipset/ip_set_bitmap.h b/include/uapi/linux/netfilter/ipset/ip_set_bitmap.h
new file mode 100644 (file)
index 0000000..6a2c038
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _UAPI__IP_SET_BITMAP_H
+#define _UAPI__IP_SET_BITMAP_H
+
+/* Bitmap type specific error codes */
+enum {
+       /* The element is out of the range of the set */
+       IPSET_ERR_BITMAP_RANGE = IPSET_ERR_TYPE_SPECIFIC,
+       /* The range exceeds the size limit of the set type */
+       IPSET_ERR_BITMAP_RANGE_SIZE,
+};
+
+
+#endif /* _UAPI__IP_SET_BITMAP_H */
diff --git a/include/uapi/linux/netfilter/ipset/ip_set_hash.h b/include/uapi/linux/netfilter/ipset/ip_set_hash.h
new file mode 100644 (file)
index 0000000..352eecc
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef _UAPI__IP_SET_HASH_H
+#define _UAPI__IP_SET_HASH_H
+
+/* Hash type specific error codes */
+enum {
+       /* Hash is full */
+       IPSET_ERR_HASH_FULL = IPSET_ERR_TYPE_SPECIFIC,
+       /* Null-valued element */
+       IPSET_ERR_HASH_ELEM,
+       /* Invalid protocol */
+       IPSET_ERR_INVALID_PROTO,
+       /* Protocol missing but must be specified */
+       IPSET_ERR_MISSING_PROTO,
+       /* Range not supported */
+       IPSET_ERR_HASH_RANGE_UNSUPPORTED,
+       /* Invalid range */
+       IPSET_ERR_HASH_RANGE,
+};
+
+
+#endif /* _UAPI__IP_SET_HASH_H */
diff --git a/include/uapi/linux/netfilter/ipset/ip_set_list.h b/include/uapi/linux/netfilter/ipset/ip_set_list.h
new file mode 100644 (file)
index 0000000..a44efaa
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef _UAPI__IP_SET_LIST_H
+#define _UAPI__IP_SET_LIST_H
+
+/* List type specific error codes */
+enum {
+       /* Set name to be added/deleted/tested does not exist. */
+       IPSET_ERR_NAME = IPSET_ERR_TYPE_SPECIFIC,
+       /* list:set type is not permitted to add */
+       IPSET_ERR_LOOP,
+       /* Missing reference set */
+       IPSET_ERR_BEFORE,
+       /* Reference set does not exist */
+       IPSET_ERR_NAMEREF,
+       /* Set is full */
+       IPSET_ERR_LIST_FULL,
+       /* Reference set is not added to the set */
+       IPSET_ERR_REF_EXIST,
+};
+
+
+#endif /* _UAPI__IP_SET_LIST_H */
diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h
new file mode 100644 (file)
index 0000000..1644cdd
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef _UAPI_NF_CONNTRACK_COMMON_H
+#define _UAPI_NF_CONNTRACK_COMMON_H
+/* Connection state tracking for netfilter.  This is separated from,
+   but required by, the NAT layer; it can also be used by an iptables
+   extension. */
+enum ip_conntrack_info {
+       /* Part of an established connection (either direction). */
+       IP_CT_ESTABLISHED,
+
+       /* Like NEW, but related to an existing connection, or ICMP error
+          (in either direction). */
+       IP_CT_RELATED,
+
+       /* Started a new connection to track (only
+           IP_CT_DIR_ORIGINAL); may be a retransmission. */
+       IP_CT_NEW,
+
+       /* >= this indicates reply direction */
+       IP_CT_IS_REPLY,
+
+       IP_CT_ESTABLISHED_REPLY = IP_CT_ESTABLISHED + IP_CT_IS_REPLY,
+       IP_CT_RELATED_REPLY = IP_CT_RELATED + IP_CT_IS_REPLY,
+       IP_CT_NEW_REPLY = IP_CT_NEW + IP_CT_IS_REPLY,   
+       /* Number of distinct IP_CT types (no NEW in reply dirn). */
+       IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1
+};
+
+/* Bitset representing status of connection. */
+enum ip_conntrack_status {
+       /* It's an expected connection: bit 0 set.  This bit never changed */
+       IPS_EXPECTED_BIT = 0,
+       IPS_EXPECTED = (1 << IPS_EXPECTED_BIT),
+
+       /* We've seen packets both ways: bit 1 set.  Can be set, not unset. */
+       IPS_SEEN_REPLY_BIT = 1,
+       IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT),
+
+       /* Conntrack should never be early-expired. */
+       IPS_ASSURED_BIT = 2,
+       IPS_ASSURED = (1 << IPS_ASSURED_BIT),
+
+       /* Connection is confirmed: originating packet has left box */
+       IPS_CONFIRMED_BIT = 3,
+       IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
+
+       /* Connection needs src nat in orig dir.  This bit never changed. */
+       IPS_SRC_NAT_BIT = 4,
+       IPS_SRC_NAT = (1 << IPS_SRC_NAT_BIT),
+
+       /* Connection needs dst nat in orig dir.  This bit never changed. */
+       IPS_DST_NAT_BIT = 5,
+       IPS_DST_NAT = (1 << IPS_DST_NAT_BIT),
+
+       /* Both together. */
+       IPS_NAT_MASK = (IPS_DST_NAT | IPS_SRC_NAT),
+
+       /* Connection needs TCP sequence adjusted. */
+       IPS_SEQ_ADJUST_BIT = 6,
+       IPS_SEQ_ADJUST = (1 << IPS_SEQ_ADJUST_BIT),
+
+       /* NAT initialization bits. */
+       IPS_SRC_NAT_DONE_BIT = 7,
+       IPS_SRC_NAT_DONE = (1 << IPS_SRC_NAT_DONE_BIT),
+
+       IPS_DST_NAT_DONE_BIT = 8,
+       IPS_DST_NAT_DONE = (1 << IPS_DST_NAT_DONE_BIT),
+
+       /* Both together */
+       IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE),
+
+       /* Connection is dying (removed from lists), can not be unset. */
+       IPS_DYING_BIT = 9,
+       IPS_DYING = (1 << IPS_DYING_BIT),
+
+       /* Connection has fixed timeout. */
+       IPS_FIXED_TIMEOUT_BIT = 10,
+       IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
+
+       /* Conntrack is a template */
+       IPS_TEMPLATE_BIT = 11,
+       IPS_TEMPLATE = (1 << IPS_TEMPLATE_BIT),
+
+       /* Conntrack is a fake untracked entry */
+       IPS_UNTRACKED_BIT = 12,
+       IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT),
+
+       /* Conntrack got a helper explicitly attached via CT target. */
+       IPS_HELPER_BIT = 13,
+       IPS_HELPER = (1 << IPS_HELPER_BIT),
+};
+
+/* Connection tracking event types */
+enum ip_conntrack_events {
+       IPCT_NEW,               /* new conntrack */
+       IPCT_RELATED,           /* related conntrack */
+       IPCT_DESTROY,           /* destroyed conntrack */
+       IPCT_REPLY,             /* connection has seen two-way traffic */
+       IPCT_ASSURED,           /* connection status has changed to assured */
+       IPCT_PROTOINFO,         /* protocol information has changed */
+       IPCT_HELPER,            /* new helper has been set */
+       IPCT_MARK,              /* new mark has been set */
+       IPCT_NATSEQADJ,         /* NAT is doing sequence adjustment */
+       IPCT_SECMARK,           /* new security mark has been set */
+};
+
+enum ip_conntrack_expect_events {
+       IPEXP_NEW,              /* new expectation */
+       IPEXP_DESTROY,          /* destroyed expectation */
+};
+
+/* expectation flags */
+#define NF_CT_EXPECT_PERMANENT         0x1
+#define NF_CT_EXPECT_INACTIVE          0x2
+#define NF_CT_EXPECT_USERSPACE         0x4
+
+
+#endif /* _UAPI_NF_CONNTRACK_COMMON_H */
diff --git a/include/uapi/linux/netfilter/nf_conntrack_ftp.h b/include/uapi/linux/netfilter/nf_conntrack_ftp.h
new file mode 100644 (file)
index 0000000..1030315
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _UAPI_NF_CONNTRACK_FTP_H
+#define _UAPI_NF_CONNTRACK_FTP_H
+/* FTP tracking. */
+
+/* This enum is exposed to userspace */
+enum nf_ct_ftp_type {
+       /* PORT command from client */
+       NF_CT_FTP_PORT,
+       /* PASV response from server */
+       NF_CT_FTP_PASV,
+       /* EPRT command from client */
+       NF_CT_FTP_EPRT,
+       /* EPSV response from server */
+       NF_CT_FTP_EPSV,
+};
+
+
+#endif /* _UAPI_NF_CONNTRACK_FTP_H */
diff --git a/include/uapi/linux/netfilter/nf_conntrack_tcp.h b/include/uapi/linux/netfilter/nf_conntrack_tcp.h
new file mode 100644 (file)
index 0000000..9993a42
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef _UAPI_NF_CONNTRACK_TCP_H
+#define _UAPI_NF_CONNTRACK_TCP_H
+/* TCP tracking. */
+
+#include <linux/types.h>
+
+/* This is exposed to userspace (ctnetlink) */
+enum tcp_conntrack {
+       TCP_CONNTRACK_NONE,
+       TCP_CONNTRACK_SYN_SENT,
+       TCP_CONNTRACK_SYN_RECV,
+       TCP_CONNTRACK_ESTABLISHED,
+       TCP_CONNTRACK_FIN_WAIT,
+       TCP_CONNTRACK_CLOSE_WAIT,
+       TCP_CONNTRACK_LAST_ACK,
+       TCP_CONNTRACK_TIME_WAIT,
+       TCP_CONNTRACK_CLOSE,
+       TCP_CONNTRACK_LISTEN,   /* obsolete */
+#define TCP_CONNTRACK_SYN_SENT2        TCP_CONNTRACK_LISTEN
+       TCP_CONNTRACK_MAX,
+       TCP_CONNTRACK_IGNORE,
+       TCP_CONNTRACK_RETRANS,
+       TCP_CONNTRACK_UNACK,
+       TCP_CONNTRACK_TIMEOUT_MAX
+};
+
+/* Window scaling is advertised by the sender */
+#define IP_CT_TCP_FLAG_WINDOW_SCALE            0x01
+
+/* SACK is permitted by the sender */
+#define IP_CT_TCP_FLAG_SACK_PERM               0x02
+
+/* This sender sent FIN first */
+#define IP_CT_TCP_FLAG_CLOSE_INIT              0x04
+
+/* Be liberal in window checking */
+#define IP_CT_TCP_FLAG_BE_LIBERAL              0x08
+
+/* Has unacknowledged data */
+#define IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED     0x10
+
+/* The field td_maxack has been set */
+#define IP_CT_TCP_FLAG_MAXACK_SET              0x20
+
+struct nf_ct_tcp_flags {
+       __u8 flags;
+       __u8 mask;
+};
+
+
+#endif /* _UAPI_NF_CONNTRACK_TCP_H */
diff --git a/include/uapi/linux/netfilter/nfnetlink.h b/include/uapi/linux/netfilter/nfnetlink.h
new file mode 100644 (file)
index 0000000..4a4efaf
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef _UAPI_NFNETLINK_H
+#define _UAPI_NFNETLINK_H
+#include <linux/types.h>
+#include <linux/netfilter/nfnetlink_compat.h>
+
+enum nfnetlink_groups {
+       NFNLGRP_NONE,
+#define NFNLGRP_NONE                   NFNLGRP_NONE
+       NFNLGRP_CONNTRACK_NEW,
+#define NFNLGRP_CONNTRACK_NEW          NFNLGRP_CONNTRACK_NEW
+       NFNLGRP_CONNTRACK_UPDATE,
+#define NFNLGRP_CONNTRACK_UPDATE       NFNLGRP_CONNTRACK_UPDATE
+       NFNLGRP_CONNTRACK_DESTROY,
+#define NFNLGRP_CONNTRACK_DESTROY      NFNLGRP_CONNTRACK_DESTROY
+       NFNLGRP_CONNTRACK_EXP_NEW,
+#define        NFNLGRP_CONNTRACK_EXP_NEW       NFNLGRP_CONNTRACK_EXP_NEW
+       NFNLGRP_CONNTRACK_EXP_UPDATE,
+#define NFNLGRP_CONNTRACK_EXP_UPDATE   NFNLGRP_CONNTRACK_EXP_UPDATE
+       NFNLGRP_CONNTRACK_EXP_DESTROY,
+#define NFNLGRP_CONNTRACK_EXP_DESTROY  NFNLGRP_CONNTRACK_EXP_DESTROY
+       __NFNLGRP_MAX,
+};
+#define NFNLGRP_MAX    (__NFNLGRP_MAX - 1)
+
+/* General form of address family dependent message.
+ */
+struct nfgenmsg {
+       __u8  nfgen_family;             /* AF_xxx */
+       __u8  version;          /* nfnetlink version */
+       __be16    res_id;               /* resource id */
+};
+
+#define NFNETLINK_V0   0
+
+/* netfilter netlink message types are split in two pieces:
+ * 8 bit subsystem, 8bit operation.
+ */
+
+#define NFNL_SUBSYS_ID(x)      ((x & 0xff00) >> 8)
+#define NFNL_MSG_TYPE(x)       (x & 0x00ff)
+
+/* No enum here, otherwise __stringify() trick of MODULE_ALIAS_NFNL_SUBSYS()
+ * won't work anymore */
+#define NFNL_SUBSYS_NONE               0
+#define NFNL_SUBSYS_CTNETLINK          1
+#define NFNL_SUBSYS_CTNETLINK_EXP      2
+#define NFNL_SUBSYS_QUEUE              3
+#define NFNL_SUBSYS_ULOG               4
+#define NFNL_SUBSYS_OSF                        5
+#define NFNL_SUBSYS_IPSET              6
+#define NFNL_SUBSYS_ACCT               7
+#define NFNL_SUBSYS_CTNETLINK_TIMEOUT  8
+#define NFNL_SUBSYS_CTHELPER           9
+#define NFNL_SUBSYS_COUNT              10
+
+#endif /* _UAPI_NFNETLINK_H */
diff --git a/include/uapi/linux/netfilter/nfnetlink_acct.h b/include/uapi/linux/netfilter/nfnetlink_acct.h
new file mode 100644 (file)
index 0000000..c7b6269
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _UAPI_NFNL_ACCT_H_
+#define _UAPI_NFNL_ACCT_H_
+
+#ifndef NFACCT_NAME_MAX
+#define NFACCT_NAME_MAX                32
+#endif
+
+enum nfnl_acct_msg_types {
+       NFNL_MSG_ACCT_NEW,
+       NFNL_MSG_ACCT_GET,
+       NFNL_MSG_ACCT_GET_CTRZERO,
+       NFNL_MSG_ACCT_DEL,
+       NFNL_MSG_ACCT_MAX
+};
+
+enum nfnl_acct_type {
+       NFACCT_UNSPEC,
+       NFACCT_NAME,
+       NFACCT_PKTS,
+       NFACCT_BYTES,
+       NFACCT_USE,
+       __NFACCT_MAX
+};
+#define NFACCT_MAX (__NFACCT_MAX - 1)
+
+
+#endif /* _UAPI_NFNL_ACCT_H_ */
diff --git a/include/uapi/linux/netfilter/x_tables.h b/include/uapi/linux/netfilter/x_tables.h
new file mode 100644 (file)
index 0000000..c36969b
--- /dev/null
@@ -0,0 +1,187 @@
+#ifndef _UAPI_X_TABLES_H
+#define _UAPI_X_TABLES_H
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#define XT_FUNCTION_MAXNAMELEN 30
+#define XT_EXTENSION_MAXNAMELEN 29
+#define XT_TABLE_MAXNAMELEN 32
+
+struct xt_entry_match {
+       union {
+               struct {
+                       __u16 match_size;
+
+                       /* Used by userspace */
+                       char name[XT_EXTENSION_MAXNAMELEN];
+                       __u8 revision;
+               } user;
+               struct {
+                       __u16 match_size;
+
+                       /* Used inside the kernel */
+                       struct xt_match *match;
+               } kernel;
+
+               /* Total length */
+               __u16 match_size;
+       } u;
+
+       unsigned char data[0];
+};
+
+struct xt_entry_target {
+       union {
+               struct {
+                       __u16 target_size;
+
+                       /* Used by userspace */
+                       char name[XT_EXTENSION_MAXNAMELEN];
+                       __u8 revision;
+               } user;
+               struct {
+                       __u16 target_size;
+
+                       /* Used inside the kernel */
+                       struct xt_target *target;
+               } kernel;
+
+               /* Total length */
+               __u16 target_size;
+       } u;
+
+       unsigned char data[0];
+};
+
+#define XT_TARGET_INIT(__name, __size)                                        \
+{                                                                             \
+       .target.u.user = {                                                     \
+               .target_size    = XT_ALIGN(__size),                            \
+               .name           = __name,                                      \
+       },                                                                     \
+}
+
+struct xt_standard_target {
+       struct xt_entry_target target;
+       int verdict;
+};
+
+struct xt_error_target {
+       struct xt_entry_target target;
+       char errorname[XT_FUNCTION_MAXNAMELEN];
+};
+
+/* The argument to IPT_SO_GET_REVISION_*.  Returns highest revision
+ * kernel supports, if >= revision. */
+struct xt_get_revision {
+       char name[XT_EXTENSION_MAXNAMELEN];
+       __u8 revision;
+};
+
+/* CONTINUE verdict for targets */
+#define XT_CONTINUE 0xFFFFFFFF
+
+/* For standard target */
+#define XT_RETURN (-NF_REPEAT - 1)
+
+/* this is a dummy structure to find out the alignment requirement for a struct
+ * containing all the fundamental data types that are used in ipt_entry,
+ * ip6t_entry and arpt_entry.  This sucks, and it is a hack.  It will be my
+ * personal pleasure to remove it -HW
+ */
+struct _xt_align {
+       __u8 u8;
+       __u16 u16;
+       __u32 u32;
+       __u64 u64;
+};
+
+#define XT_ALIGN(s) __ALIGN_KERNEL((s), __alignof__(struct _xt_align))
+
+/* Standard return verdict, or do jump. */
+#define XT_STANDARD_TARGET ""
+/* Error verdict. */
+#define XT_ERROR_TARGET "ERROR"
+
+#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0)
+#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
+
+struct xt_counters {
+       __u64 pcnt, bcnt;                       /* Packet and byte counters */
+};
+
+/* The argument to IPT_SO_ADD_COUNTERS. */
+struct xt_counters_info {
+       /* Which table. */
+       char name[XT_TABLE_MAXNAMELEN];
+
+       unsigned int num_counters;
+
+       /* The counters (actually `number' of these). */
+       struct xt_counters counters[0];
+};
+
+#define XT_INV_PROTO           0x40    /* Invert the sense of PROTO. */
+
+#ifndef __KERNEL__
+/* fn returns 0 to continue iteration */
+#define XT_MATCH_ITERATE(type, e, fn, args...)                 \
+({                                                             \
+       unsigned int __i;                                       \
+       int __ret = 0;                                          \
+       struct xt_entry_match *__m;                             \
+                                                               \
+       for (__i = sizeof(type);                                \
+            __i < (e)->target_offset;                          \
+            __i += __m->u.match_size) {                        \
+               __m = (void *)e + __i;                          \
+                                                               \
+               __ret = fn(__m , ## args);                      \
+               if (__ret != 0)                                 \
+                       break;                                  \
+       }                                                       \
+       __ret;                                                  \
+})
+
+/* fn returns 0 to continue iteration */
+#define XT_ENTRY_ITERATE_CONTINUE(type, entries, size, n, fn, args...) \
+({                                                             \
+       unsigned int __i, __n;                                  \
+       int __ret = 0;                                          \
+       type *__entry;                                          \
+                                                               \
+       for (__i = 0, __n = 0; __i < (size);                    \
+            __i += __entry->next_offset, __n++) {              \
+               __entry = (void *)(entries) + __i;              \
+               if (__n < n)                                    \
+                       continue;                               \
+                                                               \
+               __ret = fn(__entry , ## args);                  \
+               if (__ret != 0)                                 \
+                       break;                                  \
+       }                                                       \
+       __ret;                                                  \
+})
+
+/* fn returns 0 to continue iteration */
+#define XT_ENTRY_ITERATE(type, entries, size, fn, args...) \
+       XT_ENTRY_ITERATE_CONTINUE(type, entries, size, 0, fn, args)
+
+#endif /* !__KERNEL__ */
+
+/* pos is normally a struct ipt_entry/ip6t_entry/etc. */
+#define xt_entry_foreach(pos, ehead, esize) \
+       for ((pos) = (typeof(pos))(ehead); \
+            (pos) < (typeof(pos))((char *)(ehead) + (esize)); \
+            (pos) = (typeof(pos))((char *)(pos) + (pos)->next_offset))
+
+/* can only be xt_entry_match, so no use of typeof here */
+#define xt_ematch_foreach(pos, entry) \
+       for ((pos) = (struct xt_entry_match *)entry->elems; \
+            (pos) < (struct xt_entry_match *)((char *)(entry) + \
+                    (entry)->target_offset); \
+            (pos) = (struct xt_entry_match *)((char *)(pos) + \
+                    (pos)->u.match_size))
+
+
+#endif /* _UAPI_X_TABLES_H */
diff --git a/include/uapi/linux/netfilter/xt_hashlimit.h b/include/uapi/linux/netfilter/xt_hashlimit.h
new file mode 100644 (file)
index 0000000..cbfc43d
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef _UAPI_XT_HASHLIMIT_H
+#define _UAPI_XT_HASHLIMIT_H
+
+#include <linux/types.h>
+
+/* timings are in milliseconds. */
+#define XT_HASHLIMIT_SCALE 10000
+/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
+ * seconds, or one packet every 59 hours.
+ */
+
+/* packet length accounting is done in 16-byte steps */
+#define XT_HASHLIMIT_BYTE_SHIFT 4
+
+/* details of this structure hidden by the implementation */
+struct xt_hashlimit_htable;
+
+enum {
+       XT_HASHLIMIT_HASH_DIP = 1 << 0,
+       XT_HASHLIMIT_HASH_DPT = 1 << 1,
+       XT_HASHLIMIT_HASH_SIP = 1 << 2,
+       XT_HASHLIMIT_HASH_SPT = 1 << 3,
+       XT_HASHLIMIT_INVERT   = 1 << 4,
+       XT_HASHLIMIT_BYTES    = 1 << 5,
+};
+
+struct hashlimit_cfg {
+       __u32 mode;       /* bitmask of XT_HASHLIMIT_HASH_* */
+       __u32 avg;    /* Average secs between packets * scale */
+       __u32 burst;  /* Period multiplier for upper limit. */
+
+       /* user specified */
+       __u32 size;             /* how many buckets */
+       __u32 max;              /* max number of entries */
+       __u32 gc_interval;      /* gc interval */
+       __u32 expire;   /* when do entries expire? */
+};
+
+struct xt_hashlimit_info {
+       char name [IFNAMSIZ];           /* name */
+       struct hashlimit_cfg cfg;
+
+       /* Used internally by the kernel */
+       struct xt_hashlimit_htable *hinfo;
+       union {
+               void *ptr;
+               struct xt_hashlimit_info *master;
+       } u;
+};
+
+struct hashlimit_cfg1 {
+       __u32 mode;       /* bitmask of XT_HASHLIMIT_HASH_* */
+       __u32 avg;    /* Average secs between packets * scale */
+       __u32 burst;  /* Period multiplier for upper limit. */
+
+       /* user specified */
+       __u32 size;             /* how many buckets */
+       __u32 max;              /* max number of entries */
+       __u32 gc_interval;      /* gc interval */
+       __u32 expire;   /* when do entries expire? */
+
+       __u8 srcmask, dstmask;
+};
+
+struct xt_hashlimit_mtinfo1 {
+       char name[IFNAMSIZ];
+       struct hashlimit_cfg1 cfg;
+
+       /* Used internally by the kernel */
+       struct xt_hashlimit_htable *hinfo __attribute__((aligned(8)));
+};
+
+#endif /* _UAPI_XT_HASHLIMIT_H */
diff --git a/include/uapi/linux/netfilter/xt_physdev.h b/include/uapi/linux/netfilter/xt_physdev.h
new file mode 100644 (file)
index 0000000..db7a298
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _UAPI_XT_PHYSDEV_H
+#define _UAPI_XT_PHYSDEV_H
+
+#include <linux/types.h>
+
+
+#define XT_PHYSDEV_OP_IN               0x01
+#define XT_PHYSDEV_OP_OUT              0x02
+#define XT_PHYSDEV_OP_BRIDGED          0x04
+#define XT_PHYSDEV_OP_ISIN             0x08
+#define XT_PHYSDEV_OP_ISOUT            0x10
+#define XT_PHYSDEV_OP_MASK             (0x20 - 1)
+
+struct xt_physdev_info {
+       char physindev[IFNAMSIZ];
+       char in_mask[IFNAMSIZ];
+       char physoutdev[IFNAMSIZ];
+       char out_mask[IFNAMSIZ];
+       __u8 invert;
+       __u8 bitmask;
+};
+
+#endif /* _UAPI_XT_PHYSDEV_H */
index aafaa5aa54d46bb9a93a8137a22344408298223f..62d5637cc0ac5c40cbca78d70b1fb3184cd31427 100644 (file)
@@ -1 +1,3 @@
 # UAPI Header export list
+header-y += arp_tables.h
+header-y += arpt_mangle.h
diff --git a/include/uapi/linux/netfilter_arp/arp_tables.h b/include/uapi/linux/netfilter_arp/arp_tables.h
new file mode 100644 (file)
index 0000000..a5a86a4
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ *     Format of an ARP firewall descriptor
+ *
+ *     src, tgt, src_mask, tgt_mask, arpop, arpop_mask are always stored in
+ *     network byte order.
+ *     flags are stored in host byte order (of course).
+ */
+
+#ifndef _UAPI_ARPTABLES_H
+#define _UAPI_ARPTABLES_H
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <linux/netfilter_arp.h>
+
+#include <linux/netfilter/x_tables.h>
+
+#ifndef __KERNEL__
+#define ARPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
+#define ARPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
+#define arpt_entry_target xt_entry_target
+#define arpt_standard_target xt_standard_target
+#define arpt_error_target xt_error_target
+#define ARPT_CONTINUE XT_CONTINUE
+#define ARPT_RETURN XT_RETURN
+#define arpt_counters_info xt_counters_info
+#define arpt_counters xt_counters
+#define ARPT_STANDARD_TARGET XT_STANDARD_TARGET
+#define ARPT_ERROR_TARGET XT_ERROR_TARGET
+#define ARPT_ENTRY_ITERATE(entries, size, fn, args...) \
+       XT_ENTRY_ITERATE(struct arpt_entry, entries, size, fn, ## args)
+#endif
+
+#define ARPT_DEV_ADDR_LEN_MAX 16
+
+struct arpt_devaddr_info {
+       char addr[ARPT_DEV_ADDR_LEN_MAX];
+       char mask[ARPT_DEV_ADDR_LEN_MAX];
+};
+
+/* Yes, Virginia, you have to zero the padding. */
+struct arpt_arp {
+       /* Source and target IP addr */
+       struct in_addr src, tgt;
+       /* Mask for src and target IP addr */
+       struct in_addr smsk, tmsk;
+
+       /* Device hw address length, src+target device addresses */
+       __u8 arhln, arhln_mask;
+       struct arpt_devaddr_info src_devaddr;
+       struct arpt_devaddr_info tgt_devaddr;
+
+       /* ARP operation code. */
+       __be16 arpop, arpop_mask;
+
+       /* ARP hardware address and protocol address format. */
+       __be16 arhrd, arhrd_mask;
+       __be16 arpro, arpro_mask;
+
+       /* The protocol address length is only accepted if it is 4
+        * so there is no use in offering a way to do filtering on it.
+        */
+
+       char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
+       unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
+
+       /* Flags word */
+       __u8 flags;
+       /* Inverse flags */
+       __u16 invflags;
+};
+
+/* Values for "flag" field in struct arpt_ip (general arp structure).
+ * No flags defined yet.
+ */
+#define ARPT_F_MASK            0x00    /* All possible flag bits mask. */
+
+/* Values for "inv" field in struct arpt_arp. */
+#define ARPT_INV_VIA_IN                0x0001  /* Invert the sense of IN IFACE. */
+#define ARPT_INV_VIA_OUT       0x0002  /* Invert the sense of OUT IFACE */
+#define ARPT_INV_SRCIP         0x0004  /* Invert the sense of SRC IP. */
+#define ARPT_INV_TGTIP         0x0008  /* Invert the sense of TGT IP. */
+#define ARPT_INV_SRCDEVADDR    0x0010  /* Invert the sense of SRC DEV ADDR. */
+#define ARPT_INV_TGTDEVADDR    0x0020  /* Invert the sense of TGT DEV ADDR. */
+#define ARPT_INV_ARPOP         0x0040  /* Invert the sense of ARP OP. */
+#define ARPT_INV_ARPHRD                0x0080  /* Invert the sense of ARP HRD. */
+#define ARPT_INV_ARPPRO                0x0100  /* Invert the sense of ARP PRO. */
+#define ARPT_INV_ARPHLN                0x0200  /* Invert the sense of ARP HLN. */
+#define ARPT_INV_MASK          0x03FF  /* All possible flag bits mask. */
+
+/* This structure defines each of the firewall rules.  Consists of 3
+   parts which are 1) general ARP header stuff 2) match specific
+   stuff 3) the target to perform if the rule matches */
+struct arpt_entry
+{
+       struct arpt_arp arp;
+
+       /* Size of arpt_entry + matches */
+       __u16 target_offset;
+       /* Size of arpt_entry + matches + target */
+       __u16 next_offset;
+
+       /* Back pointer */
+       unsigned int comefrom;
+
+       /* Packet and byte counters. */
+       struct xt_counters counters;
+
+       /* The matches (if any), then the target. */
+       unsigned char elems[0];
+};
+
+/*
+ * New IP firewall options for [gs]etsockopt at the RAW IP level.
+ * Unlike BSD Linux inherits IP options so you don't have to use a raw
+ * socket for this. Instead we check rights in the calls.
+ *
+ * ATTENTION: check linux/in.h before adding new number here.
+ */
+#define ARPT_BASE_CTL          96
+
+#define ARPT_SO_SET_REPLACE            (ARPT_BASE_CTL)
+#define ARPT_SO_SET_ADD_COUNTERS       (ARPT_BASE_CTL + 1)
+#define ARPT_SO_SET_MAX                        ARPT_SO_SET_ADD_COUNTERS
+
+#define ARPT_SO_GET_INFO               (ARPT_BASE_CTL)
+#define ARPT_SO_GET_ENTRIES            (ARPT_BASE_CTL + 1)
+/* #define ARPT_SO_GET_REVISION_MATCH  (APRT_BASE_CTL + 2) */
+#define ARPT_SO_GET_REVISION_TARGET    (ARPT_BASE_CTL + 3)
+#define ARPT_SO_GET_MAX                        (ARPT_SO_GET_REVISION_TARGET)
+
+/* The argument to ARPT_SO_GET_INFO */
+struct arpt_getinfo {
+       /* Which table: caller fills this in. */
+       char name[XT_TABLE_MAXNAMELEN];
+
+       /* Kernel fills these in. */
+       /* Which hook entry points are valid: bitmask */
+       unsigned int valid_hooks;
+
+       /* Hook entry points: one per netfilter hook. */
+       unsigned int hook_entry[NF_ARP_NUMHOOKS];
+
+       /* Underflow points. */
+       unsigned int underflow[NF_ARP_NUMHOOKS];
+
+       /* Number of entries */
+       unsigned int num_entries;
+
+       /* Size of entries. */
+       unsigned int size;
+};
+
+/* The argument to ARPT_SO_SET_REPLACE. */
+struct arpt_replace {
+       /* Which table. */
+       char name[XT_TABLE_MAXNAMELEN];
+
+       /* Which hook entry points are valid: bitmask.  You can't
+           change this. */
+       unsigned int valid_hooks;
+
+       /* Number of entries */
+       unsigned int num_entries;
+
+       /* Total size of new entries */
+       unsigned int size;
+
+       /* Hook entry points. */
+       unsigned int hook_entry[NF_ARP_NUMHOOKS];
+
+       /* Underflow points. */
+       unsigned int underflow[NF_ARP_NUMHOOKS];
+
+       /* Information about old entries: */
+       /* Number of counters (must be equal to current number of entries). */
+       unsigned int num_counters;
+       /* The old entries' counters. */
+       struct xt_counters __user *counters;
+
+       /* The entries (hang off end: not really an array). */
+       struct arpt_entry entries[0];
+};
+
+/* The argument to ARPT_SO_GET_ENTRIES. */
+struct arpt_get_entries {
+       /* Which table: user fills this in. */
+       char name[XT_TABLE_MAXNAMELEN];
+
+       /* User fills this in: total entry size. */
+       unsigned int size;
+
+       /* The entries. */
+       struct arpt_entry entrytable[0];
+};
+
+/* Helper functions */
+static __inline__ struct xt_entry_target *arpt_get_target(struct arpt_entry *e)
+{
+       return (void *)e + e->target_offset;
+}
+
+/*
+ *     Main firewall chains definitions and global var's definitions.
+ */
+#endif /* _UAPI_ARPTABLES_H */
index aafaa5aa54d46bb9a93a8137a22344408298223f..348717c3a22f6660b106edd712b6e95df0444b68 100644 (file)
@@ -1 +1,19 @@
 # UAPI Header export list
+header-y += ebt_802_3.h
+header-y += ebt_among.h
+header-y += ebt_arp.h
+header-y += ebt_arpreply.h
+header-y += ebt_ip.h
+header-y += ebt_ip6.h
+header-y += ebt_limit.h
+header-y += ebt_log.h
+header-y += ebt_mark_m.h
+header-y += ebt_mark_t.h
+header-y += ebt_nat.h
+header-y += ebt_nflog.h
+header-y += ebt_pkttype.h
+header-y += ebt_redirect.h
+header-y += ebt_stp.h
+header-y += ebt_ulog.h
+header-y += ebt_vlan.h
+header-y += ebtables.h
diff --git a/include/uapi/linux/netfilter_bridge/ebt_802_3.h b/include/uapi/linux/netfilter_bridge/ebt_802_3.h
new file mode 100644 (file)
index 0000000..5bf8491
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef _UAPI__LINUX_BRIDGE_EBT_802_3_H
+#define _UAPI__LINUX_BRIDGE_EBT_802_3_H
+
+#include <linux/types.h>
+
+#define EBT_802_3_SAP 0x01
+#define EBT_802_3_TYPE 0x02
+
+#define EBT_802_3_MATCH "802_3"
+
+/*
+ * If frame has DSAP/SSAP value 0xaa you must check the SNAP type
+ * to discover what kind of packet we're carrying. 
+ */
+#define CHECK_TYPE 0xaa
+
+/*
+ * Control field may be one or two bytes.  If the first byte has
+ * the value 0x03 then the entire length is one byte, otherwise it is two.
+ * One byte controls are used in Unnumbered Information frames.
+ * Two byte controls are used in Numbered Information frames.
+ */
+#define IS_UI 0x03
+
+#define EBT_802_3_MASK (EBT_802_3_SAP | EBT_802_3_TYPE | EBT_802_3)
+
+/* ui has one byte ctrl, ni has two */
+struct hdr_ui {
+       __u8 dsap;
+       __u8 ssap;
+       __u8 ctrl;
+       __u8 orig[3];
+       __be16 type;
+};
+
+struct hdr_ni {
+       __u8 dsap;
+       __u8 ssap;
+       __be16 ctrl;
+       __u8  orig[3];
+       __be16 type;
+};
+
+struct ebt_802_3_hdr {
+       __u8  daddr[6];
+       __u8  saddr[6];
+       __be16 len;
+       union {
+               struct hdr_ui ui;
+               struct hdr_ni ni;
+       } llc;
+};
+
+
+struct ebt_802_3_info {
+       __u8  sap;
+       __be16 type;
+       __u8  bitmask;
+       __u8  invflags;
+};
+
+#endif /* _UAPI__LINUX_BRIDGE_EBT_802_3_H */
diff --git a/include/uapi/linux/netfilter_bridge/ebtables.h b/include/uapi/linux/netfilter_bridge/ebtables.h
new file mode 100644 (file)
index 0000000..ba99336
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ *  ebtables
+ *
+ *     Authors:
+ *     Bart De Schuymer                <bdschuym@pandora.be>
+ *
+ *  ebtables.c,v 2.0, April, 2002
+ *
+ *  This code is stongly inspired on the iptables code which is
+ *  Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
+ */
+
+#ifndef _UAPI__LINUX_BRIDGE_EFF_H
+#define _UAPI__LINUX_BRIDGE_EFF_H
+#include <linux/if.h>
+#include <linux/netfilter_bridge.h>
+#include <linux/if_ether.h>
+
+#define EBT_TABLE_MAXNAMELEN 32
+#define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN
+#define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN
+
+/* verdicts >0 are "branches" */
+#define EBT_ACCEPT   -1
+#define EBT_DROP     -2
+#define EBT_CONTINUE -3
+#define EBT_RETURN   -4
+#define NUM_STANDARD_TARGETS   4
+/* ebtables target modules store the verdict inside an int. We can
+ * reclaim a part of this int for backwards compatible extensions.
+ * The 4 lsb are more than enough to store the verdict. */
+#define EBT_VERDICT_BITS 0x0000000F
+
+struct xt_match;
+struct xt_target;
+
+struct ebt_counter {
+       uint64_t pcnt;
+       uint64_t bcnt;
+};
+
+struct ebt_replace {
+       char name[EBT_TABLE_MAXNAMELEN];
+       unsigned int valid_hooks;
+       /* nr of rules in the table */
+       unsigned int nentries;
+       /* total size of the entries */
+       unsigned int entries_size;
+       /* start of the chains */
+       struct ebt_entries __user *hook_entry[NF_BR_NUMHOOKS];
+       /* nr of counters userspace expects back */
+       unsigned int num_counters;
+       /* where the kernel will put the old counters */
+       struct ebt_counter __user *counters;
+       char __user *entries;
+};
+
+struct ebt_replace_kernel {
+       char name[EBT_TABLE_MAXNAMELEN];
+       unsigned int valid_hooks;
+       /* nr of rules in the table */
+       unsigned int nentries;
+       /* total size of the entries */
+       unsigned int entries_size;
+       /* start of the chains */
+       struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
+       /* nr of counters userspace expects back */
+       unsigned int num_counters;
+       /* where the kernel will put the old counters */
+       struct ebt_counter *counters;
+       char *entries;
+};
+
+struct ebt_entries {
+       /* this field is always set to zero
+        * See EBT_ENTRY_OR_ENTRIES.
+        * Must be same size as ebt_entry.bitmask */
+       unsigned int distinguisher;
+       /* the chain name */
+       char name[EBT_CHAIN_MAXNAMELEN];
+       /* counter offset for this chain */
+       unsigned int counter_offset;
+       /* one standard (accept, drop, return) per hook */
+       int policy;
+       /* nr. of entries */
+       unsigned int nentries;
+       /* entry list */
+       char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
+};
+
+/* used for the bitmask of struct ebt_entry */
+
+/* This is a hack to make a difference between an ebt_entry struct and an
+ * ebt_entries struct when traversing the entries from start to end.
+ * Using this simplifies the code a lot, while still being able to use
+ * ebt_entries.
+ * Contrary, iptables doesn't use something like ebt_entries and therefore uses
+ * different techniques for naming the policy and such. So, iptables doesn't
+ * need a hack like this.
+ */
+#define EBT_ENTRY_OR_ENTRIES 0x01
+/* these are the normal masks */
+#define EBT_NOPROTO 0x02
+#define EBT_802_3 0x04
+#define EBT_SOURCEMAC 0x08
+#define EBT_DESTMAC 0x10
+#define EBT_F_MASK (EBT_NOPROTO | EBT_802_3 | EBT_SOURCEMAC | EBT_DESTMAC \
+   | EBT_ENTRY_OR_ENTRIES)
+
+#define EBT_IPROTO 0x01
+#define EBT_IIN 0x02
+#define EBT_IOUT 0x04
+#define EBT_ISOURCE 0x8
+#define EBT_IDEST 0x10
+#define EBT_ILOGICALIN 0x20
+#define EBT_ILOGICALOUT 0x40
+#define EBT_INV_MASK (EBT_IPROTO | EBT_IIN | EBT_IOUT | EBT_ILOGICALIN \
+   | EBT_ILOGICALOUT | EBT_ISOURCE | EBT_IDEST)
+
+struct ebt_entry_match {
+       union {
+               char name[EBT_FUNCTION_MAXNAMELEN];
+               struct xt_match *match;
+       } u;
+       /* size of data */
+       unsigned int match_size;
+       unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
+};
+
+struct ebt_entry_watcher {
+       union {
+               char name[EBT_FUNCTION_MAXNAMELEN];
+               struct xt_target *watcher;
+       } u;
+       /* size of data */
+       unsigned int watcher_size;
+       unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
+};
+
+struct ebt_entry_target {
+       union {
+               char name[EBT_FUNCTION_MAXNAMELEN];
+               struct xt_target *target;
+       } u;
+       /* size of data */
+       unsigned int target_size;
+       unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
+};
+
+#define EBT_STANDARD_TARGET "standard"
+struct ebt_standard_target {
+       struct ebt_entry_target target;
+       int verdict;
+};
+
+/* one entry */
+struct ebt_entry {
+       /* this needs to be the first field */
+       unsigned int bitmask;
+       unsigned int invflags;
+       __be16 ethproto;
+       /* the physical in-dev */
+       char in[IFNAMSIZ];
+       /* the logical in-dev */
+       char logical_in[IFNAMSIZ];
+       /* the physical out-dev */
+       char out[IFNAMSIZ];
+       /* the logical out-dev */
+       char logical_out[IFNAMSIZ];
+       unsigned char sourcemac[ETH_ALEN];
+       unsigned char sourcemsk[ETH_ALEN];
+       unsigned char destmac[ETH_ALEN];
+       unsigned char destmsk[ETH_ALEN];
+       /* sizeof ebt_entry + matches */
+       unsigned int watchers_offset;
+       /* sizeof ebt_entry + matches + watchers */
+       unsigned int target_offset;
+       /* sizeof ebt_entry + matches + watchers + target */
+       unsigned int next_offset;
+       unsigned char elems[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
+};
+
+/* {g,s}etsockopt numbers */
+#define EBT_BASE_CTL            128
+
+#define EBT_SO_SET_ENTRIES      (EBT_BASE_CTL)
+#define EBT_SO_SET_COUNTERS     (EBT_SO_SET_ENTRIES+1)
+#define EBT_SO_SET_MAX          (EBT_SO_SET_COUNTERS+1)
+
+#define EBT_SO_GET_INFO         (EBT_BASE_CTL)
+#define EBT_SO_GET_ENTRIES      (EBT_SO_GET_INFO+1)
+#define EBT_SO_GET_INIT_INFO    (EBT_SO_GET_ENTRIES+1)
+#define EBT_SO_GET_INIT_ENTRIES (EBT_SO_GET_INIT_INFO+1)
+#define EBT_SO_GET_MAX          (EBT_SO_GET_INIT_ENTRIES+1)
+
+
+/* blatently stolen from ip_tables.h
+ * fn returns 0 to continue iteration */
+#define EBT_MATCH_ITERATE(e, fn, args...)                   \
+({                                                          \
+       unsigned int __i;                                   \
+       int __ret = 0;                                      \
+       struct ebt_entry_match *__match;                    \
+                                                           \
+       for (__i = sizeof(struct ebt_entry);                \
+            __i < (e)->watchers_offset;                    \
+            __i += __match->match_size +                   \
+            sizeof(struct ebt_entry_match)) {              \
+               __match = (void *)(e) + __i;                \
+                                                           \
+               __ret = fn(__match , ## args);              \
+               if (__ret != 0)                             \
+                       break;                              \
+       }                                                   \
+       if (__ret == 0) {                                   \
+               if (__i != (e)->watchers_offset)            \
+                       __ret = -EINVAL;                    \
+       }                                                   \
+       __ret;                                              \
+})
+
+#define EBT_WATCHER_ITERATE(e, fn, args...)                 \
+({                                                          \
+       unsigned int __i;                                   \
+       int __ret = 0;                                      \
+       struct ebt_entry_watcher *__watcher;                \
+                                                           \
+       for (__i = e->watchers_offset;                      \
+            __i < (e)->target_offset;                      \
+            __i += __watcher->watcher_size +               \
+            sizeof(struct ebt_entry_watcher)) {            \
+               __watcher = (void *)(e) + __i;              \
+                                                           \
+               __ret = fn(__watcher , ## args);            \
+               if (__ret != 0)                             \
+                       break;                              \
+       }                                                   \
+       if (__ret == 0) {                                   \
+               if (__i != (e)->target_offset)              \
+                       __ret = -EINVAL;                    \
+       }                                                   \
+       __ret;                                              \
+})
+
+#define EBT_ENTRY_ITERATE(entries, size, fn, args...)       \
+({                                                          \
+       unsigned int __i;                                   \
+       int __ret = 0;                                      \
+       struct ebt_entry *__entry;                          \
+                                                           \
+       for (__i = 0; __i < (size);) {                      \
+               __entry = (void *)(entries) + __i;          \
+               __ret = fn(__entry , ## args);              \
+               if (__ret != 0)                             \
+                       break;                              \
+               if (__entry->bitmask != 0)                  \
+                       __i += __entry->next_offset;        \
+               else                                        \
+                       __i += sizeof(struct ebt_entries);  \
+       }                                                   \
+       if (__ret == 0) {                                   \
+               if (__i != (size))                          \
+                       __ret = -EINVAL;                    \
+       }                                                   \
+       __ret;                                              \
+})
+
+#endif /* _UAPI__LINUX_BRIDGE_EFF_H */
index aafaa5aa54d46bb9a93a8137a22344408298223f..fb008437dde111f01db08e9f7fa442ab57e66dda 100644 (file)
@@ -1 +1,11 @@
 # UAPI Header export list
+header-y += ip_tables.h
+header-y += ipt_CLUSTERIP.h
+header-y += ipt_ECN.h
+header-y += ipt_LOG.h
+header-y += ipt_REJECT.h
+header-y += ipt_TTL.h
+header-y += ipt_ULOG.h
+header-y += ipt_ah.h
+header-y += ipt_ecn.h
+header-y += ipt_ttl.h
diff --git a/include/uapi/linux/netfilter_ipv4/ip_tables.h b/include/uapi/linux/netfilter_ipv4/ip_tables.h
new file mode 100644 (file)
index 0000000..f1e6ef2
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * 25-Jul-1998 Major changes to allow for ip chain table
+ *
+ * 3-Jan-2000 Named tables to allow packet selection for different uses.
+ */
+
+/*
+ *     Format of an IP firewall descriptor
+ *
+ *     src, dst, src_mask, dst_mask are always stored in network byte order.
+ *     flags are stored in host byte order (of course).
+ *     Port numbers are stored in HOST byte order.
+ */
+
+#ifndef _UAPI_IPTABLES_H
+#define _UAPI_IPTABLES_H
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <linux/netfilter_ipv4.h>
+
+#include <linux/netfilter/x_tables.h>
+
+#ifndef __KERNEL__
+#define IPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
+#define IPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
+#define ipt_match xt_match
+#define ipt_target xt_target
+#define ipt_table xt_table
+#define ipt_get_revision xt_get_revision
+#define ipt_entry_match xt_entry_match
+#define ipt_entry_target xt_entry_target
+#define ipt_standard_target xt_standard_target
+#define ipt_error_target xt_error_target
+#define ipt_counters xt_counters
+#define IPT_CONTINUE XT_CONTINUE
+#define IPT_RETURN XT_RETURN
+
+/* This group is older than old (iptables < v1.4.0-rc1~89) */
+#include <linux/netfilter/xt_tcpudp.h>
+#define ipt_udp xt_udp
+#define ipt_tcp xt_tcp
+#define IPT_TCP_INV_SRCPT      XT_TCP_INV_SRCPT
+#define IPT_TCP_INV_DSTPT      XT_TCP_INV_DSTPT
+#define IPT_TCP_INV_FLAGS      XT_TCP_INV_FLAGS
+#define IPT_TCP_INV_OPTION     XT_TCP_INV_OPTION
+#define IPT_TCP_INV_MASK       XT_TCP_INV_MASK
+#define IPT_UDP_INV_SRCPT      XT_UDP_INV_SRCPT
+#define IPT_UDP_INV_DSTPT      XT_UDP_INV_DSTPT
+#define IPT_UDP_INV_MASK       XT_UDP_INV_MASK
+
+/* The argument to IPT_SO_ADD_COUNTERS. */
+#define ipt_counters_info xt_counters_info
+/* Standard return verdict, or do jump. */
+#define IPT_STANDARD_TARGET XT_STANDARD_TARGET
+/* Error verdict. */
+#define IPT_ERROR_TARGET XT_ERROR_TARGET
+
+/* fn returns 0 to continue iteration */
+#define IPT_MATCH_ITERATE(e, fn, args...) \
+       XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args)
+
+/* fn returns 0 to continue iteration */
+#define IPT_ENTRY_ITERATE(entries, size, fn, args...) \
+       XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args)
+#endif
+
+/* Yes, Virginia, you have to zero the padding. */
+struct ipt_ip {
+       /* Source and destination IP addr */
+       struct in_addr src, dst;
+       /* Mask for src and dest IP addr */
+       struct in_addr smsk, dmsk;
+       char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
+       unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
+
+       /* Protocol, 0 = ANY */
+       __u16 proto;
+
+       /* Flags word */
+       __u8 flags;
+       /* Inverse flags */
+       __u8 invflags;
+};
+
+/* Values for "flag" field in struct ipt_ip (general ip structure). */
+#define IPT_F_FRAG             0x01    /* Set if rule is a fragment rule */
+#define IPT_F_GOTO             0x02    /* Set if jump is a goto */
+#define IPT_F_MASK             0x03    /* All possible flag bits mask. */
+
+/* Values for "inv" field in struct ipt_ip. */
+#define IPT_INV_VIA_IN         0x01    /* Invert the sense of IN IFACE. */
+#define IPT_INV_VIA_OUT                0x02    /* Invert the sense of OUT IFACE */
+#define IPT_INV_TOS            0x04    /* Invert the sense of TOS. */
+#define IPT_INV_SRCIP          0x08    /* Invert the sense of SRC IP. */
+#define IPT_INV_DSTIP          0x10    /* Invert the sense of DST OP. */
+#define IPT_INV_FRAG           0x20    /* Invert the sense of FRAG. */
+#define IPT_INV_PROTO          XT_INV_PROTO
+#define IPT_INV_MASK           0x7F    /* All possible flag bits mask. */
+
+/* This structure defines each of the firewall rules.  Consists of 3
+   parts which are 1) general IP header stuff 2) match specific
+   stuff 3) the target to perform if the rule matches */
+struct ipt_entry {
+       struct ipt_ip ip;
+
+       /* Mark with fields that we care about. */
+       unsigned int nfcache;
+
+       /* Size of ipt_entry + matches */
+       __u16 target_offset;
+       /* Size of ipt_entry + matches + target */
+       __u16 next_offset;
+
+       /* Back pointer */
+       unsigned int comefrom;
+
+       /* Packet and byte counters. */
+       struct xt_counters counters;
+
+       /* The matches (if any), then the target. */
+       unsigned char elems[0];
+};
+
+/*
+ * New IP firewall options for [gs]etsockopt at the RAW IP level.
+ * Unlike BSD Linux inherits IP options so you don't have to use a raw
+ * socket for this. Instead we check rights in the calls.
+ *
+ * ATTENTION: check linux/in.h before adding new number here.
+ */
+#define IPT_BASE_CTL           64
+
+#define IPT_SO_SET_REPLACE     (IPT_BASE_CTL)
+#define IPT_SO_SET_ADD_COUNTERS        (IPT_BASE_CTL + 1)
+#define IPT_SO_SET_MAX         IPT_SO_SET_ADD_COUNTERS
+
+#define IPT_SO_GET_INFO                        (IPT_BASE_CTL)
+#define IPT_SO_GET_ENTRIES             (IPT_BASE_CTL + 1)
+#define IPT_SO_GET_REVISION_MATCH      (IPT_BASE_CTL + 2)
+#define IPT_SO_GET_REVISION_TARGET     (IPT_BASE_CTL + 3)
+#define IPT_SO_GET_MAX                 IPT_SO_GET_REVISION_TARGET
+
+/* ICMP matching stuff */
+struct ipt_icmp {
+       __u8 type;                              /* type to match */
+       __u8 code[2];                           /* range of code */
+       __u8 invflags;                          /* Inverse flags */
+};
+
+/* Values for "inv" field for struct ipt_icmp. */
+#define IPT_ICMP_INV   0x01    /* Invert the sense of type/code test */
+
+/* The argument to IPT_SO_GET_INFO */
+struct ipt_getinfo {
+       /* Which table: caller fills this in. */
+       char name[XT_TABLE_MAXNAMELEN];
+
+       /* Kernel fills these in. */
+       /* Which hook entry points are valid: bitmask */
+       unsigned int valid_hooks;
+
+       /* Hook entry points: one per netfilter hook. */
+       unsigned int hook_entry[NF_INET_NUMHOOKS];
+
+       /* Underflow points. */
+       unsigned int underflow[NF_INET_NUMHOOKS];
+
+       /* Number of entries */
+       unsigned int num_entries;
+
+       /* Size of entries. */
+       unsigned int size;
+};
+
+/* The argument to IPT_SO_SET_REPLACE. */
+struct ipt_replace {
+       /* Which table. */
+       char name[XT_TABLE_MAXNAMELEN];
+
+       /* Which hook entry points are valid: bitmask.  You can't
+           change this. */
+       unsigned int valid_hooks;
+
+       /* Number of entries */
+       unsigned int num_entries;
+
+       /* Total size of new entries */
+       unsigned int size;
+
+       /* Hook entry points. */
+       unsigned int hook_entry[NF_INET_NUMHOOKS];
+
+       /* Underflow points. */
+       unsigned int underflow[NF_INET_NUMHOOKS];
+
+       /* Information about old entries: */
+       /* Number of counters (must be equal to current number of entries). */
+       unsigned int num_counters;
+       /* The old entries' counters. */
+       struct xt_counters __user *counters;
+
+       /* The entries (hang off end: not really an array). */
+       struct ipt_entry entries[0];
+};
+
+/* The argument to IPT_SO_GET_ENTRIES. */
+struct ipt_get_entries {
+       /* Which table: user fills this in. */
+       char name[XT_TABLE_MAXNAMELEN];
+
+       /* User fills this in: total entry size. */
+       unsigned int size;
+
+       /* The entries. */
+       struct ipt_entry entrytable[0];
+};
+
+/* Helper functions */
+static __inline__ struct xt_entry_target *
+ipt_get_target(struct ipt_entry *e)
+{
+       return (void *)e + e->target_offset;
+}
+
+/*
+ *     Main firewall chains definitions and global var's definitions.
+ */
+#endif /* _UAPI_IPTABLES_H */
index aafaa5aa54d46bb9a93a8137a22344408298223f..75a668ca2353ad9abfa07bbbd6e515aa49ec37fb 100644 (file)
@@ -1 +1,13 @@
 # UAPI Header export list
+header-y += ip6_tables.h
+header-y += ip6t_HL.h
+header-y += ip6t_LOG.h
+header-y += ip6t_NPT.h
+header-y += ip6t_REJECT.h
+header-y += ip6t_ah.h
+header-y += ip6t_frag.h
+header-y += ip6t_hl.h
+header-y += ip6t_ipv6header.h
+header-y += ip6t_mh.h
+header-y += ip6t_opts.h
+header-y += ip6t_rt.h
diff --git a/include/uapi/linux/netfilter_ipv6/ip6_tables.h b/include/uapi/linux/netfilter_ipv6/ip6_tables.h
new file mode 100644 (file)
index 0000000..bf1ef65
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * 25-Jul-1998 Major changes to allow for ip chain table
+ *
+ * 3-Jan-2000 Named tables to allow packet selection for different uses.
+ */
+
+/*
+ *     Format of an IP6 firewall descriptor
+ *
+ *     src, dst, src_mask, dst_mask are always stored in network byte order.
+ *     flags are stored in host byte order (of course).
+ *     Port numbers are stored in HOST byte order.
+ */
+
+#ifndef _UAPI_IP6_TABLES_H
+#define _UAPI_IP6_TABLES_H
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <linux/netfilter_ipv6.h>
+
+#include <linux/netfilter/x_tables.h>
+
+#ifndef __KERNEL__
+#define IP6T_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
+#define IP6T_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
+#define ip6t_match xt_match
+#define ip6t_target xt_target
+#define ip6t_table xt_table
+#define ip6t_get_revision xt_get_revision
+#define ip6t_entry_match xt_entry_match
+#define ip6t_entry_target xt_entry_target
+#define ip6t_standard_target xt_standard_target
+#define ip6t_error_target xt_error_target
+#define ip6t_counters xt_counters
+#define IP6T_CONTINUE XT_CONTINUE
+#define IP6T_RETURN XT_RETURN
+
+/* Pre-iptables-1.4.0 */
+#include <linux/netfilter/xt_tcpudp.h>
+#define ip6t_tcp xt_tcp
+#define ip6t_udp xt_udp
+#define IP6T_TCP_INV_SRCPT     XT_TCP_INV_SRCPT
+#define IP6T_TCP_INV_DSTPT     XT_TCP_INV_DSTPT
+#define IP6T_TCP_INV_FLAGS     XT_TCP_INV_FLAGS
+#define IP6T_TCP_INV_OPTION    XT_TCP_INV_OPTION
+#define IP6T_TCP_INV_MASK      XT_TCP_INV_MASK
+#define IP6T_UDP_INV_SRCPT     XT_UDP_INV_SRCPT
+#define IP6T_UDP_INV_DSTPT     XT_UDP_INV_DSTPT
+#define IP6T_UDP_INV_MASK      XT_UDP_INV_MASK
+
+#define ip6t_counters_info xt_counters_info
+#define IP6T_STANDARD_TARGET XT_STANDARD_TARGET
+#define IP6T_ERROR_TARGET XT_ERROR_TARGET
+#define IP6T_MATCH_ITERATE(e, fn, args...) \
+       XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args)
+#define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \
+       XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args)
+#endif
+
+/* Yes, Virginia, you have to zero the padding. */
+struct ip6t_ip6 {
+       /* Source and destination IP6 addr */
+       struct in6_addr src, dst;               
+       /* Mask for src and dest IP6 addr */
+       struct in6_addr smsk, dmsk;
+       char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
+       unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
+
+       /* Upper protocol number
+        * - The allowed value is 0 (any) or protocol number of last parsable
+        *   header, which is 50 (ESP), 59 (No Next Header), 135 (MH), or
+        *   the non IPv6 extension headers.
+        * - The protocol numbers of IPv6 extension headers except of ESP and
+        *   MH do not match any packets.
+        * - You also need to set IP6T_FLAGS_PROTO to "flags" to check protocol.
+        */
+       __u16 proto;
+       /* TOS to match iff flags & IP6T_F_TOS */
+       __u8 tos;
+
+       /* Flags word */
+       __u8 flags;
+       /* Inverse flags */
+       __u8 invflags;
+};
+
+/* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */
+#define IP6T_F_PROTO           0x01    /* Set if rule cares about upper 
+                                          protocols */
+#define IP6T_F_TOS             0x02    /* Match the TOS. */
+#define IP6T_F_GOTO            0x04    /* Set if jump is a goto */
+#define IP6T_F_MASK            0x07    /* All possible flag bits mask. */
+
+/* Values for "inv" field in struct ip6t_ip6. */
+#define IP6T_INV_VIA_IN                0x01    /* Invert the sense of IN IFACE. */
+#define IP6T_INV_VIA_OUT               0x02    /* Invert the sense of OUT IFACE */
+#define IP6T_INV_TOS           0x04    /* Invert the sense of TOS. */
+#define IP6T_INV_SRCIP         0x08    /* Invert the sense of SRC IP. */
+#define IP6T_INV_DSTIP         0x10    /* Invert the sense of DST OP. */
+#define IP6T_INV_FRAG          0x20    /* Invert the sense of FRAG. */
+#define IP6T_INV_PROTO         XT_INV_PROTO
+#define IP6T_INV_MASK          0x7F    /* All possible flag bits mask. */
+
+/* This structure defines each of the firewall rules.  Consists of 3
+   parts which are 1) general IP header stuff 2) match specific
+   stuff 3) the target to perform if the rule matches */
+struct ip6t_entry {
+       struct ip6t_ip6 ipv6;
+
+       /* Mark with fields that we care about. */
+       unsigned int nfcache;
+
+       /* Size of ipt_entry + matches */
+       __u16 target_offset;
+       /* Size of ipt_entry + matches + target */
+       __u16 next_offset;
+
+       /* Back pointer */
+       unsigned int comefrom;
+
+       /* Packet and byte counters. */
+       struct xt_counters counters;
+
+       /* The matches (if any), then the target. */
+       unsigned char elems[0];
+};
+
+/* Standard entry */
+struct ip6t_standard {
+       struct ip6t_entry entry;
+       struct xt_standard_target target;
+};
+
+struct ip6t_error {
+       struct ip6t_entry entry;
+       struct xt_error_target target;
+};
+
+#define IP6T_ENTRY_INIT(__size)                                                       \
+{                                                                             \
+       .target_offset  = sizeof(struct ip6t_entry),                           \
+       .next_offset    = (__size),                                            \
+}
+
+#define IP6T_STANDARD_INIT(__verdict)                                         \
+{                                                                             \
+       .entry          = IP6T_ENTRY_INIT(sizeof(struct ip6t_standard)),       \
+       .target         = XT_TARGET_INIT(XT_STANDARD_TARGET,                   \
+                                        sizeof(struct xt_standard_target)),   \
+       .target.verdict = -(__verdict) - 1,                                    \
+}
+
+#define IP6T_ERROR_INIT                                                               \
+{                                                                             \
+       .entry          = IP6T_ENTRY_INIT(sizeof(struct ip6t_error)),          \
+       .target         = XT_TARGET_INIT(XT_ERROR_TARGET,                      \
+                                        sizeof(struct xt_error_target)),      \
+       .target.errorname = "ERROR",                                           \
+}
+
+/*
+ * New IP firewall options for [gs]etsockopt at the RAW IP level.
+ * Unlike BSD Linux inherits IP options so you don't have to use
+ * a raw socket for this. Instead we check rights in the calls.
+ *
+ * ATTENTION: check linux/in6.h before adding new number here.
+ */
+#define IP6T_BASE_CTL                  64
+
+#define IP6T_SO_SET_REPLACE            (IP6T_BASE_CTL)
+#define IP6T_SO_SET_ADD_COUNTERS       (IP6T_BASE_CTL + 1)
+#define IP6T_SO_SET_MAX                        IP6T_SO_SET_ADD_COUNTERS
+
+#define IP6T_SO_GET_INFO               (IP6T_BASE_CTL)
+#define IP6T_SO_GET_ENTRIES            (IP6T_BASE_CTL + 1)
+#define IP6T_SO_GET_REVISION_MATCH     (IP6T_BASE_CTL + 4)
+#define IP6T_SO_GET_REVISION_TARGET    (IP6T_BASE_CTL + 5)
+#define IP6T_SO_GET_MAX                        IP6T_SO_GET_REVISION_TARGET
+
+/* ICMP matching stuff */
+struct ip6t_icmp {
+       __u8 type;                              /* type to match */
+       __u8 code[2];                           /* range of code */
+       __u8 invflags;                          /* Inverse flags */
+};
+
+/* Values for "inv" field for struct ipt_icmp. */
+#define IP6T_ICMP_INV  0x01    /* Invert the sense of type/code test */
+
+/* The argument to IP6T_SO_GET_INFO */
+struct ip6t_getinfo {
+       /* Which table: caller fills this in. */
+       char name[XT_TABLE_MAXNAMELEN];
+
+       /* Kernel fills these in. */
+       /* Which hook entry points are valid: bitmask */
+       unsigned int valid_hooks;
+
+       /* Hook entry points: one per netfilter hook. */
+       unsigned int hook_entry[NF_INET_NUMHOOKS];
+
+       /* Underflow points. */
+       unsigned int underflow[NF_INET_NUMHOOKS];
+
+       /* Number of entries */
+       unsigned int num_entries;
+
+       /* Size of entries. */
+       unsigned int size;
+};
+
+/* The argument to IP6T_SO_SET_REPLACE. */
+struct ip6t_replace {
+       /* Which table. */
+       char name[XT_TABLE_MAXNAMELEN];
+
+       /* Which hook entry points are valid: bitmask.  You can't
+           change this. */
+       unsigned int valid_hooks;
+
+       /* Number of entries */
+       unsigned int num_entries;
+
+       /* Total size of new entries */
+       unsigned int size;
+
+       /* Hook entry points. */
+       unsigned int hook_entry[NF_INET_NUMHOOKS];
+
+       /* Underflow points. */
+       unsigned int underflow[NF_INET_NUMHOOKS];
+
+       /* Information about old entries: */
+       /* Number of counters (must be equal to current number of entries). */
+       unsigned int num_counters;
+       /* The old entries' counters. */
+       struct xt_counters __user *counters;
+
+       /* The entries (hang off end: not really an array). */
+       struct ip6t_entry entries[0];
+};
+
+/* The argument to IP6T_SO_GET_ENTRIES. */
+struct ip6t_get_entries {
+       /* Which table: user fills this in. */
+       char name[XT_TABLE_MAXNAMELEN];
+
+       /* User fills this in: total entry size. */
+       unsigned int size;
+
+       /* The entries. */
+       struct ip6t_entry entrytable[0];
+};
+
+/* Helper functions */
+static __inline__ struct xt_entry_target *
+ip6t_get_target(struct ip6t_entry *e)
+{
+       return (void *)e + e->target_offset;
+}
+
+/*
+ *     Main firewall chains definitions and global var's definitions.
+ */
+
+#endif /* _UAPI_IP6_TABLES_H */
index aafaa5aa54d46bb9a93a8137a22344408298223f..c11bc404053c121fc82604514fd24e6506e1717f 100644 (file)
@@ -1 +1,6 @@
 # UAPI Header export list
+header-y += cld.h
+header-y += debug.h
+header-y += export.h
+header-y += nfsfh.h
+header-y += stats.h
diff --git a/include/uapi/linux/nfsd/debug.h b/include/uapi/linux/nfsd/debug.h
new file mode 100644 (file)
index 0000000..a6f453c
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * linux/include/linux/nfsd/debug.h
+ *
+ * Debugging-related stuff for nfsd
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef _UAPILINUX_NFSD_DEBUG_H
+#define _UAPILINUX_NFSD_DEBUG_H
+
+#include <linux/sunrpc/debug.h>
+
+/*
+ * Enable debugging for nfsd.
+ * Requires RPC_DEBUG.
+ */
+#ifdef RPC_DEBUG
+# define NFSD_DEBUG            1
+#endif
+
+/*
+ * knfsd debug flags
+ */
+#define NFSDDBG_SOCK           0x0001
+#define NFSDDBG_FH             0x0002
+#define NFSDDBG_EXPORT         0x0004
+#define NFSDDBG_SVC            0x0008
+#define NFSDDBG_PROC           0x0010
+#define NFSDDBG_FILEOP         0x0020
+#define NFSDDBG_AUTH           0x0040
+#define NFSDDBG_REPCACHE       0x0080
+#define NFSDDBG_XDR            0x0100
+#define NFSDDBG_LOCKD          0x0200
+#define NFSDDBG_ALL            0x7FFF
+#define NFSDDBG_NOCHANGE       0xFFFF
+
+
+
+#endif /* _UAPILINUX_NFSD_DEBUG_H */
diff --git a/include/uapi/linux/nfsd/export.h b/include/uapi/linux/nfsd/export.h
new file mode 100644 (file)
index 0000000..cf47c31
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * include/linux/nfsd/export.h
+ * 
+ * Public declarations for NFS exports. The definitions for the
+ * syscall interface are in nfsctl.h
+ *
+ * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef _UAPINFSD_EXPORT_H
+#define _UAPINFSD_EXPORT_H
+
+# include <linux/types.h>
+
+/*
+ * Important limits for the exports stuff.
+ */
+#define NFSCLNT_IDMAX          1024
+#define NFSCLNT_ADDRMAX                16
+#define NFSCLNT_KEYMAX         32
+
+/*
+ * Export flags.
+ */
+#define NFSEXP_READONLY                0x0001
+#define NFSEXP_INSECURE_PORT   0x0002
+#define NFSEXP_ROOTSQUASH      0x0004
+#define NFSEXP_ALLSQUASH       0x0008
+#define NFSEXP_ASYNC           0x0010
+#define NFSEXP_GATHERED_WRITES 0x0020
+/* 40 80 100 currently unused */
+#define NFSEXP_NOHIDE          0x0200
+#define NFSEXP_NOSUBTREECHECK  0x0400
+#define        NFSEXP_NOAUTHNLM        0x0800          /* Don't authenticate NLM requests - just trust */
+#define NFSEXP_MSNFS           0x1000  /* do silly things that MS clients expect; no longer supported */
+#define NFSEXP_FSID            0x2000
+#define        NFSEXP_CROSSMOUNT       0x4000
+#define        NFSEXP_NOACL            0x8000  /* reserved for possible ACL related use */
+/*
+ * The NFSEXP_V4ROOT flag causes the kernel to give access only to NFSv4
+ * clients, and only to the single directory that is the root of the
+ * export; further lookup and readdir operations are treated as if every
+ * subdirectory was a mountpoint, and ignored if they are not themselves
+ * exported.  This is used by nfsd and mountd to construct the NFSv4
+ * pseudofilesystem, which provides access only to paths leading to each
+ * exported filesystem.
+ */
+#define        NFSEXP_V4ROOT           0x10000
+/* All flags that we claim to support.  (Note we don't support NOACL.) */
+#define NFSEXP_ALLFLAGS                0x17E3F
+
+/* The flags that may vary depending on security flavor: */
+#define NFSEXP_SECINFO_FLAGS   (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
+                                       | NFSEXP_ALLSQUASH \
+                                       | NFSEXP_INSECURE_PORT)
+
+
+#endif /* _UAPINFSD_EXPORT_H */
diff --git a/include/uapi/linux/nfsd/nfsfh.h b/include/uapi/linux/nfsd/nfsfh.h
new file mode 100644 (file)
index 0000000..616e3b3
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * include/linux/nfsd/nfsfh.h
+ *
+ * This file describes the layout of the file handles as passed
+ * over the wire.
+ *
+ * Earlier versions of knfsd used to sign file handles using keyed MD5
+ * or SHA. I've removed this code, because it doesn't give you more
+ * security than blocking external access to port 2049 on your firewall.
+ *
+ * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef _UAPI_LINUX_NFSD_FH_H
+#define _UAPI_LINUX_NFSD_FH_H
+
+#include <linux/types.h>
+#include <linux/nfs.h>
+#include <linux/nfs2.h>
+#include <linux/nfs3.h>
+#include <linux/nfs4.h>
+
+/*
+ * This is the old "dentry style" Linux NFSv2 file handle.
+ *
+ * The xino and xdev fields are currently used to transport the
+ * ino/dev of the exported inode.
+ */
+struct nfs_fhbase_old {
+       __u32           fb_dcookie;     /* dentry cookie - always 0xfeebbaca */
+       __u32           fb_ino;         /* our inode number */
+       __u32           fb_dirino;      /* dir inode number, 0 for directories */
+       __u32           fb_dev;         /* our device */
+       __u32           fb_xdev;
+       __u32           fb_xino;
+       __u32           fb_generation;
+};
+
+/*
+ * This is the new flexible, extensible style NFSv2/v3 file handle.
+ * by Neil Brown <neilb@cse.unsw.edu.au> - March 2000
+ *
+ * The file handle starts with a sequence of four-byte words.
+ * The first word contains a version number (1) and three descriptor bytes
+ * that tell how the remaining 3 variable length fields should be handled.
+ * These three bytes are auth_type, fsid_type and fileid_type.
+ *
+ * All four-byte values are in host-byte-order.
+ *
+ * The auth_type field specifies how the filehandle can be authenticated
+ * This might allow a file to be confirmed to be in a writable part of a
+ * filetree without checking the path from it up to the root.
+ * Current values:
+ *     0  - No authentication.  fb_auth is 0 bytes long
+ * Possible future values:
+ *     1  - 4 bytes taken from MD5 hash of the remainer of the file handle
+ *          prefixed by a secret and with the important export flags.
+ *
+ * The fsid_type identifies how the filesystem (or export point) is
+ *    encoded.
+ *  Current values:
+ *     0  - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number
+ *        NOTE: we cannot use the kdev_t device id value, because kdev_t.h
+ *              says we mustn't.  We must break it up and reassemble.
+ *     1  - 4 byte user specified identifier
+ *     2  - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED
+ *     3  - 4 byte device id, encoded for user-space, 4 byte inode number
+ *     4  - 4 byte inode number and 4 byte uuid
+ *     5  - 8 byte uuid
+ *     6  - 16 byte uuid
+ *     7  - 8 byte inode number and 16 byte uuid
+ *
+ * The fileid_type identified how the file within the filesystem is encoded.
+ * This is (will be) passed to, and set by, the underlying filesystem if it supports
+ * filehandle operations.  The filesystem must not use the value '0' or '0xff' and may
+ * only use the values 1 and 2 as defined below:
+ *  Current values:
+ *    0   - The root, or export point, of the filesystem.  fb_fileid is 0 bytes.
+ *    1   - 32bit inode number, 32 bit generation number.
+ *    2   - 32bit inode number, 32 bit generation number, 32 bit parent directory inode number.
+ *
+ */
+struct nfs_fhbase_new {
+       __u8            fb_version;     /* == 1, even => nfs_fhbase_old */
+       __u8            fb_auth_type;
+       __u8            fb_fsid_type;
+       __u8            fb_fileid_type;
+       __u32           fb_auth[1];
+/*     __u32           fb_fsid[0]; floating */
+/*     __u32           fb_fileid[0]; floating */
+};
+
+struct knfsd_fh {
+       unsigned int    fh_size;        /* significant for NFSv3.
+                                        * Points to the current size while building
+                                        * a new file handle
+                                        */
+       union {
+               struct nfs_fhbase_old   fh_old;
+               __u32                   fh_pad[NFS4_FHSIZE/4];
+               struct nfs_fhbase_new   fh_new;
+       } fh_base;
+};
+
+#define ofh_dcookie            fh_base.fh_old.fb_dcookie
+#define ofh_ino                        fh_base.fh_old.fb_ino
+#define ofh_dirino             fh_base.fh_old.fb_dirino
+#define ofh_dev                        fh_base.fh_old.fb_dev
+#define ofh_xdev               fh_base.fh_old.fb_xdev
+#define ofh_xino               fh_base.fh_old.fb_xino
+#define ofh_generation         fh_base.fh_old.fb_generation
+
+#define        fh_version              fh_base.fh_new.fb_version
+#define        fh_fsid_type            fh_base.fh_new.fb_fsid_type
+#define        fh_auth_type            fh_base.fh_new.fb_auth_type
+#define        fh_fileid_type          fh_base.fh_new.fb_fileid_type
+#define        fh_auth                 fh_base.fh_new.fb_auth
+#define        fh_fsid                 fh_base.fh_new.fb_auth
+
+
+
+#endif /* _UAPI_LINUX_NFSD_FH_H */
diff --git a/include/uapi/linux/nfsd/stats.h b/include/uapi/linux/nfsd/stats.h
new file mode 100644 (file)
index 0000000..9fb7a06
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * linux/include/linux/nfsd/stats.h
+ *
+ * Statistics for NFS server.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef _UAPILINUX_NFSD_STATS_H
+#define _UAPILINUX_NFSD_STATS_H
+
+#include <linux/nfs4.h>
+
+/* thread usage wraps very million seconds (approx one fortnight) */
+#define        NFSD_USAGE_WRAP (HZ*1000000)
+
+#endif /* _UAPILINUX_NFSD_STATS_H */
index aafaa5aa54d46bb9a93a8137a22344408298223f..8e02e47c20fb65cbc59ec3ae70bd23bb92af7386 100644 (file)
@@ -1 +1,2 @@
 # UAPI Header export list
+header-y += debug.h
diff --git a/include/uapi/linux/sunrpc/debug.h b/include/uapi/linux/sunrpc/debug.h
new file mode 100644 (file)
index 0000000..830e344
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * linux/include/linux/sunrpc/debug.h
+ *
+ * Debugging support for sunrpc module
+ *
+ * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef _UAPI_LINUX_SUNRPC_DEBUG_H_
+#define _UAPI_LINUX_SUNRPC_DEBUG_H_
+
+/*
+ * RPC debug facilities
+ */
+#define RPCDBG_XPRT            0x0001
+#define RPCDBG_CALL            0x0002
+#define RPCDBG_DEBUG           0x0004
+#define RPCDBG_NFS             0x0008
+#define RPCDBG_AUTH            0x0010
+#define RPCDBG_BIND            0x0020
+#define RPCDBG_SCHED           0x0040
+#define RPCDBG_TRANS           0x0080
+#define RPCDBG_SVCXPRT         0x0100
+#define RPCDBG_SVCDSP          0x0200
+#define RPCDBG_MISC            0x0400
+#define RPCDBG_CACHE           0x0800
+#define RPCDBG_ALL             0x7fff
+
+
+/*
+ * Declarations for the sysctl debug interface, which allows to read or
+ * change the debug flags for rpc, nfs, nfsd, and lockd. Since the sunrpc
+ * module currently registers its sysctl table dynamically, the sysctl path
+ * for module FOO is <CTL_SUNRPC, CTL_FOODEBUG>.
+ */
+
+enum {
+       CTL_RPCDEBUG = 1,
+       CTL_NFSDEBUG,
+       CTL_NFSDDEBUG,
+       CTL_NLMDEBUG,
+       CTL_SLOTTABLE_UDP,
+       CTL_SLOTTABLE_TCP,
+       CTL_MIN_RESVPORT,
+       CTL_MAX_RESVPORT,
+};
+
+#endif /* _UAPI_LINUX_SUNRPC_DEBUG_H_ */
index aafaa5aa54d46bb9a93a8137a22344408298223f..0623ec4e728f09550fd8c5e0e464f4a771265bdb 100644 (file)
@@ -1 +1,8 @@
 # UAPI Header export list
+header-y += tc_csum.h
+header-y += tc_gact.h
+header-y += tc_ipt.h
+header-y += tc_mirred.h
+header-y += tc_nat.h
+header-y += tc_pedit.h
+header-y += tc_skbedit.h
index aafaa5aa54d46bb9a93a8137a22344408298223f..53fca39255351730cfd7384d4ca4ccefbb6414c1 100644 (file)
@@ -1 +1,5 @@
 # UAPI Header export list
+header-y += tc_em_cmp.h
+header-y += tc_em_meta.h
+header-y += tc_em_nbyte.h
+header-y += tc_em_text.h
index aafaa5aa54d46bb9a93a8137a22344408298223f..1c97be49971ff377b152af80aca7e51e6c59a9a2 100644 (file)
@@ -1 +1,2 @@
 # UAPI Header export list
+header-y += i2400m.h
index aafaa5aa54d46bb9a93a8137a22344408298223f..5a691e10cd0ecd35db2260c7417145dd5a588aad 100644 (file)
@@ -1 +1,6 @@
 # UAPI Header export list
+header-y += inftl-user.h
+header-y += mtd-abi.h
+header-y += mtd-user.h
+header-y += nftl-user.h
+header-y += ubi-user.h
index aafaa5aa54d46bb9a93a8137a22344408298223f..61257cb146539364bdce89c3b15eff115b81902b 100644 (file)
@@ -1 +1,3 @@
 # UAPI Header export list
+header-y += evtchn.h
+header-y += privcmd.h
index a6267a2d292bfa07a815003410060348656392ce..3729173b7fbcec618be006af9fa8507824a6db7c 100644 (file)
 #define DISPC_IRQ_FRAMEDONEWB          (1 << 23)
 #define DISPC_IRQ_FRAMEDONETV          (1 << 24)
 #define DISPC_IRQ_WBBUFFEROVERFLOW     (1 << 25)
-#define DISPC_IRQ_FRAMEDONE3           (1 << 26)
-#define DISPC_IRQ_VSYNC3               (1 << 27)
-#define DISPC_IRQ_ACBIAS_COUNT_STAT3   (1 << 28)
-#define DISPC_IRQ_SYNC_LOST3           (1 << 29)
+#define DISPC_IRQ_SYNC_LOST3           (1 << 27)
+#define DISPC_IRQ_VSYNC3               (1 << 28)
+#define DISPC_IRQ_ACBIAS_COUNT_STAT3   (1 << 29)
+#define DISPC_IRQ_FRAMEDONE3           (1 << 30)
 
 struct omap_dss_device;
 struct omap_overlay_manager;
@@ -73,6 +73,7 @@ enum omap_plane {
        OMAP_DSS_VIDEO1 = 1,
        OMAP_DSS_VIDEO2 = 2,
        OMAP_DSS_VIDEO3 = 3,
+       OMAP_DSS_WB     = 4,
 };
 
 enum omap_channel {
@@ -186,6 +187,8 @@ enum omap_overlay_caps {
        OMAP_DSS_OVL_CAP_GLOBAL_ALPHA = 1 << 1,
        OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA = 1 << 2,
        OMAP_DSS_OVL_CAP_ZORDER = 1 << 3,
+       OMAP_DSS_OVL_CAP_POS = 1 << 4,
+       OMAP_DSS_OVL_CAP_REPLICATION = 1 << 5,
 };
 
 enum omap_overlay_manager_caps {
@@ -207,6 +210,16 @@ enum omap_hdmi_flags {
        OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP = 1 << 0,
 };
 
+enum omap_dss_output_id {
+       OMAP_DSS_OUTPUT_DPI     = 1 << 0,
+       OMAP_DSS_OUTPUT_DBI     = 1 << 1,
+       OMAP_DSS_OUTPUT_SDI     = 1 << 2,
+       OMAP_DSS_OUTPUT_DSI1    = 1 << 3,
+       OMAP_DSS_OUTPUT_DSI2    = 1 << 4,
+       OMAP_DSS_OUTPUT_VENC    = 1 << 5,
+       OMAP_DSS_OUTPUT_HDMI    = 1 << 6,
+};
+
 /* RFBI */
 
 struct rfbi_timings {
@@ -243,7 +256,7 @@ void rfbi_bus_unlock(void);
 
 /* DSI */
 
-struct omap_dss_dsi_videomode_data {
+struct omap_dss_dsi_videomode_timings {
        /* DSI video mode blanking data */
        /* Unit: byte clock cycles */
        u16 hsa;
@@ -424,6 +437,8 @@ struct omap_overlay {
                        struct omap_overlay_info *info);
 
        int (*wait_for_go)(struct omap_overlay *ovl);
+
+       struct omap_dss_device *(*get_device)(struct omap_overlay *ovl);
 };
 
 struct omap_overlay_manager_info {
@@ -448,9 +463,10 @@ struct omap_overlay_manager {
        enum omap_overlay_manager_caps caps;
        struct list_head overlays;
        enum omap_display_type supported_displays;
+       enum omap_dss_output_id supported_outputs;
 
        /* dynamic fields */
-       struct omap_dss_device *device;
+       struct omap_dss_output *output;
 
        /*
         * The following functions do not block:
@@ -463,9 +479,9 @@ struct omap_overlay_manager {
         * interrupt context
         */
 
-       int (*set_device)(struct omap_overlay_manager *mgr,
-               struct omap_dss_device *dssdev);
-       int (*unset_device)(struct omap_overlay_manager *mgr);
+       int (*set_output)(struct omap_overlay_manager *mgr,
+               struct omap_dss_output *output);
+       int (*unset_output)(struct omap_overlay_manager *mgr);
 
        int (*set_manager_info)(struct omap_overlay_manager *mgr,
                        struct omap_overlay_manager_info *info);
@@ -475,6 +491,8 @@ struct omap_overlay_manager {
        int (*apply)(struct omap_overlay_manager *mgr);
        int (*wait_for_go)(struct omap_overlay_manager *mgr);
        int (*wait_for_vsync)(struct omap_overlay_manager *mgr);
+
+       struct omap_dss_device *(*get_device)(struct omap_overlay_manager *mgr);
 };
 
 /* 22 pins means 1 clk lane and 10 data lanes */
@@ -492,6 +510,37 @@ struct omap_dsi_pin_config {
        int pins[OMAP_DSS_MAX_DSI_PINS];
 };
 
+struct omap_dss_writeback_info {
+       u32 paddr;
+       u32 p_uv_addr;
+       u16 buf_width;
+       u16 width;
+       u16 height;
+       enum omap_color_mode color_mode;
+       u8 rotation;
+       enum omap_dss_rotation_type rotation_type;
+       bool mirror;
+       u8 pre_mult_alpha;
+};
+
+struct omap_dss_output {
+       struct list_head list;
+
+       /* display type supported by the output */
+       enum omap_display_type type;
+
+       /* output instance */
+       enum omap_dss_output_id id;
+
+       /* output's platform device pointer */
+       struct platform_device *pdev;
+
+       /* dynamic fields */
+       struct omap_overlay_manager *manager;
+
+       struct omap_dss_device *device;
+};
+
 struct omap_dss_device {
        struct device dev;
 
@@ -564,7 +613,7 @@ struct omap_dss_device {
 
                enum omap_dss_dsi_pixel_format dsi_pix_fmt;
                enum omap_dss_dsi_mode dsi_mode;
-               struct omap_dss_dsi_videomode_data dsi_vm_data;
+               struct omap_dss_dsi_videomode_timings dsi_vm_timings;
        } panel;
 
        struct {
@@ -590,7 +639,7 @@ struct omap_dss_device {
 
        enum omap_display_caps caps;
 
-       struct omap_overlay_manager *manager;
+       struct omap_dss_output *output;
 
        enum omap_dss_display_state state;
 
@@ -605,6 +654,8 @@ struct omap_dss_device {
 
 struct omap_dss_hdmi_data
 {
+       int ct_cp_hpd_gpio;
+       int ls_oe_gpio;
        int hpd_gpio;
 };
 
@@ -699,6 +750,11 @@ struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
 int omap_dss_get_num_overlays(void);
 struct omap_overlay *omap_dss_get_overlay(int num);
 
+struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id);
+int omapdss_output_set_device(struct omap_dss_output *out,
+               struct omap_dss_device *dssdev);
+int omapdss_output_unset_device(struct omap_dss_output *out);
+
 void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
                u16 *xres, u16 *yres);
 int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev);
@@ -719,6 +775,15 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
 void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
                bool enable);
 int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
+void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings);
+void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h);
+void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
+               enum omap_dss_dsi_pixel_format fmt);
+void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
+               enum omap_dss_dsi_mode mode);
+void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
+               struct omap_dss_dsi_videomode_timings *timings);
 
 int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
                void (*callback)(int, void *), void *data);
@@ -727,6 +792,8 @@ int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
 void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
 int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
                const struct omap_dsi_pin_config *pin_cfg);
+int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
+               unsigned long ddr_clk, unsigned long lp_clk);
 
 int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
@@ -734,22 +801,29 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
 
 int omapdss_dpi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_dpi_display_disable(struct omap_dss_device *dssdev);
-void dpi_set_timings(struct omap_dss_device *dssdev,
-                       struct omap_video_timings *timings);
+void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings);
 int dpi_check_timings(struct omap_dss_device *dssdev,
                        struct omap_video_timings *timings);
+void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines);
 
 int omapdss_sdi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_sdi_display_disable(struct omap_dss_device *dssdev);
+void omapdss_sdi_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings);
+void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs);
 
 int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev);
-int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
-               u16 *x, u16 *y, u16 *w, u16 *h);
-int omap_rfbi_update(struct omap_dss_device *dssdev,
-               u16 x, u16 y, u16 w, u16 h,
-               void (*callback)(void *), void *data);
-int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size,
+int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
+               void *data);
+int omap_rfbi_configure(struct omap_dss_device *dssdev);
+void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h);
+void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev,
+               int pixel_size);
+void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,
                int data_lines);
+void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
+               struct rfbi_timings *timings);
 
 #endif
similarity index 73%
rename from arch/arm/plat-samsung/include/plat/regs-fb.h
rename to include/video/samsung_fimd.h
index 9a78012d6f434ed4772864ba2a3d0915d2f2d5bd..7ae6c07f2ef8617b98d4cdefefc6929e675eb2de 100644 (file)
@@ -1,13 +1,13 @@
-/* arch/arm/plat-samsung/include/plat/regs-fb.h
+/* include/video/samsung_fimd.h
  *
  * Copyright 2008 Openmoko, Inc.
  * Copyright 2008 Simtec Electronics
  *      http://armlinux.simtec.co.uk/
  *      Ben Dooks <ben@simtec.co.uk>
  *
- * S3C Platform - new-style framebuffer register definitions
+ * S3C Platform - new-style fimd and framebuffer register definitions
  *
- * This is the register set for the new style framebuffer interface
+ * This is the register set for the fimd and new style framebuffer interface
  * found from the S3C2443 onwards into the S3C2416, S3C2450 and the
  * S3C64XX series such as the S3C6400 and S3C6410.
  *
  * whichever architecture is selected, it only contains the core of the
  * register set. See <mach/regs-fb.h> to get the specifics.
  *
- * Note, we changed to using regs-fb.h as it avoids any clashes with
- * the original regs-lcd.h so out of the way of regs-lcd.h as well as
- * indicating the newer block is much more than just an LCD interface.
- *
  * 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.
 */
 
-/* Please do not include this file directly, use <mach/regs-fb.h> to
- * ensure all the localised SoC support is included as necessary.
-*/
-
 /* VIDCON0 */
 
 #define VIDCON0                                        (0x00)
 #define BLENDCON_NEW_8BIT_ALPHA_VALUE          (1 << 0)
 #define BLENDCON_NEW_4BIT_ALPHA_VALUE          (0 << 0)
 
+#define S3C_FB_MAX_WIN (5)  /* number of hardware windows available. */
+#define VIDCON1_FSTATUS_EVEN   (1 << 15)
+
+/* Video timing controls */
+#define VIDTCON0                               (0x10)
+#define VIDTCON1                               (0x14)
+#define VIDTCON2                               (0x18)
+
+/* Window position controls */
+
+#define WINCON(_win)                           (0x20 + ((_win) * 4))
+
+/* OSD1 and OSD4 do not have register D */
+
+#define VIDOSD_BASE                            (0x40)
+
+#define VIDINTCON0                             (0x130)
+
+/* WINCONx */
+
+#define WINCONx_CSCWIDTH_MASK                  (0x3 << 26)
+#define WINCONx_CSCWIDTH_SHIFT                 (26)
+#define WINCONx_CSCWIDTH_WIDE                  (0x0 << 26)
+#define WINCONx_CSCWIDTH_NARROW                        (0x3 << 26)
+
+#define WINCONx_ENLOCAL                                (1 << 22)
+#define WINCONx_BUFSTATUS                      (1 << 21)
+#define WINCONx_BUFSEL                         (1 << 20)
+#define WINCONx_BUFAUTOEN                      (1 << 19)
+#define WINCONx_YCbCr                          (1 << 13)
+
+#define WINCON1_LOCALSEL_CAMIF                 (1 << 23)
+
+#define WINCON2_LOCALSEL_CAMIF                 (1 << 23)
+#define WINCON2_BLD_PIX                                (1 << 6)
+
+#define WINCON2_ALPHA_SEL                      (1 << 1)
+#define WINCON2_BPPMODE_MASK                   (0xf << 2)
+#define WINCON2_BPPMODE_SHIFT                  (2)
+#define WINCON2_BPPMODE_1BPP                   (0x0 << 2)
+#define WINCON2_BPPMODE_2BPP                   (0x1 << 2)
+#define WINCON2_BPPMODE_4BPP                   (0x2 << 2)
+#define WINCON2_BPPMODE_8BPP_1232              (0x4 << 2)
+#define WINCON2_BPPMODE_16BPP_565              (0x5 << 2)
+#define WINCON2_BPPMODE_16BPP_A1555            (0x6 << 2)
+#define WINCON2_BPPMODE_16BPP_I1555            (0x7 << 2)
+#define WINCON2_BPPMODE_18BPP_666              (0x8 << 2)
+#define WINCON2_BPPMODE_18BPP_A1665            (0x9 << 2)
+#define WINCON2_BPPMODE_19BPP_A1666            (0xa << 2)
+#define WINCON2_BPPMODE_24BPP_888              (0xb << 2)
+#define WINCON2_BPPMODE_24BPP_A1887            (0xc << 2)
+#define WINCON2_BPPMODE_25BPP_A1888            (0xd << 2)
+#define WINCON2_BPPMODE_28BPP_A4888            (0xd << 2)
+
+#define WINCON3_BLD_PIX                                (1 << 6)
+
+#define WINCON3_ALPHA_SEL                      (1 << 1)
+#define WINCON3_BPPMODE_MASK                   (0xf << 2)
+#define WINCON3_BPPMODE_SHIFT                  (2)
+#define WINCON3_BPPMODE_1BPP                   (0x0 << 2)
+#define WINCON3_BPPMODE_2BPP                   (0x1 << 2)
+#define WINCON3_BPPMODE_4BPP                   (0x2 << 2)
+#define WINCON3_BPPMODE_16BPP_565              (0x5 << 2)
+#define WINCON3_BPPMODE_16BPP_A1555            (0x6 << 2)
+#define WINCON3_BPPMODE_16BPP_I1555            (0x7 << 2)
+#define WINCON3_BPPMODE_18BPP_666              (0x8 << 2)
+#define WINCON3_BPPMODE_18BPP_A1665            (0x9 << 2)
+#define WINCON3_BPPMODE_19BPP_A1666            (0xa << 2)
+#define WINCON3_BPPMODE_24BPP_888              (0xb << 2)
+#define WINCON3_BPPMODE_24BPP_A1887            (0xc << 2)
+#define WINCON3_BPPMODE_25BPP_A1888            (0xd << 2)
+#define WINCON3_BPPMODE_28BPP_A4888            (0xd << 2)
+
+#define VIDINTCON0_FIFIOSEL_WINDOW2            (0x10 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW3            (0x20 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW4            (0x40 << 5)
+
+#define DITHMODE                               (0x170)
+#define WINxMAP(_win)                          (0x180 + ((_win) * 4))
+
+
+#define DITHMODE_R_POS_MASK                    (0x3 << 5)
+#define DITHMODE_R_POS_SHIFT                   (5)
+#define DITHMODE_R_POS_8BIT                    (0x0 << 5)
+#define DITHMODE_R_POS_6BIT                    (0x1 << 5)
+#define DITHMODE_R_POS_5BIT                    (0x2 << 5)
+
+#define DITHMODE_G_POS_MASK                    (0x3 << 3)
+#define DITHMODE_G_POS_SHIFT                   (3)
+#define DITHMODE_G_POS_8BIT                    (0x0 << 3)
+#define DITHMODE_G_POS_6BIT                    (0x1 << 3)
+#define DITHMODE_G_POS_5BIT                    (0x2 << 3)
+
+#define DITHMODE_B_POS_MASK                    (0x3 << 1)
+#define DITHMODE_B_POS_SHIFT                   (1)
+#define DITHMODE_B_POS_8BIT                    (0x0 << 1)
+#define DITHMODE_B_POS_6BIT                    (0x1 << 1)
+#define DITHMODE_B_POS_5BIT                    (0x2 << 1)
+
+#define DITHMODE_DITH_EN                       (1 << 0)
+
+#define WPALCON                                        (0x1A0)
+
+/* Palette control */
+/* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L),
+ * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */
+#define WPALCON_W4PAL_16BPP_A555               (1 << 8)
+#define WPALCON_W3PAL_16BPP_A555               (1 << 7)
+#define WPALCON_W2PAL_16BPP_A555               (1 << 6)
+
+
+/* Notes on per-window bpp settings
+ *
+ * Value       Win0     Win1     Win2     Win3     Win 4
+ * 0000                1(P)     1(P)     1(P)     1(P)     1(P)
+ * 0001                2(P)     2(P)     2(P)     2(P)     2(P)
+ * 0010                4(P)     4(P)     4(P)     4(P)     -none-
+ * 0011                8(P)     8(P)     -none-   -none-   -none-
+ * 0100                -none-   8(A232)  8(A232)  -none-   -none-
+ * 0101                16(565)  16(565)  16(565)  16(565)   16(565)
+ * 0110                -none-   16(A555) 16(A555) 16(A555)  16(A555)
+ * 0111                16(I555) 16(I565) 16(I555) 16(I555)  16(I555)
+ * 1000                18(666)  18(666)  18(666)  18(666)   18(666)
+ * 1001                -none-   18(A665) 18(A665) 18(A665)  16(A665)
+ * 1010                -none-   19(A666) 19(A666) 19(A666)  19(A666)
+ * 1011                24(888)  24(888)  24(888)  24(888)   24(888)
+ * 1100                -none-   24(A887) 24(A887) 24(A887)  24(A887)
+ * 1101                -none-   25(A888) 25(A888) 25(A888)  25(A888)
+ * 1110                -none-   -none-   -none-   -none-    -none-
+ * 1111                -none-   -none-   -none-   -none-    -none-
+*/
+
+/* FIMD Version 8 register offset definitions */
+#define FIMD_V8_VIDTCON0       (0x20010)
+#define FIMD_V8_VIDTCON1       (0x20014)
+#define FIMD_V8_VIDTCON2       (0x20018)
+#define FIMD_V8_VIDTCON3       (0x2001C)
+#define FIMD_V8_VIDCON1                (0x20004)
index 84ad8f02fee5e5904c31c21915db049de7c3b2b3..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,2 +0,0 @@
-header-y += evtchn.h
-header-y += privcmd.h
index a4827f46ee97fffd0021874dabc49877ae67ca4b..956a04682865bbf19b456448b83af6112240dd6f 100644 (file)
@@ -43,4 +43,23 @@ struct xen_hvm_pagetable_dying {
 typedef struct xen_hvm_pagetable_dying xen_hvm_pagetable_dying_t;
 DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_pagetable_dying_t);
  
+enum hvmmem_type_t {
+    HVMMEM_ram_rw,             /* Normal read/write guest RAM */
+    HVMMEM_ram_ro,             /* Read-only; writes are discarded */
+    HVMMEM_mmio_dm,            /* Reads and write go to the device model */
+};
+
+#define HVMOP_get_mem_type    15
+/* Return hvmmem_type_t for the specified pfn. */
+struct xen_hvm_get_mem_type {
+    /* Domain to be queried. */
+    domid_t domid;
+    /* OUT variable. */
+    uint16_t mem_type;
+    uint16_t pad[2]; /* align next field on 8-byte boundary */
+    /* IN variable. */
+    uint64_t pfn;
+};
+DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_get_mem_type);
+
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
index 4c93533da42cbd66fd29f84b4e66c8c7e881c9ff..89e4cf672dfe90e0d1fb75fb667d551dc7094f93 100644 (file)
@@ -496,6 +496,12 @@ config RCU_USER_QS
          excluded from the global RCU state machine and thus doesn't
          to keep the timer tick on for RCU.
 
+         Unless you want to hack and help the development of the full
+         tickless feature, you shouldn't enable this option. It adds
+         unnecessary overhead.
+
+         If unsure say N
+
 config RCU_USER_QS_FORCE
        bool "Force userspace extended QS by default"
        depends on RCU_USER_QS
@@ -504,6 +510,12 @@ config RCU_USER_QS_FORCE
          test this feature that treats userspace as an extended quiescent
          state until we have a real user like a full adaptive nohz option.
 
+         Unless you want to hack and help the development of the full
+         tickless feature, you shouldn't enable this option. It adds
+         unnecessary overhead.
+
+         If unsure say N
+
 config RCU_FANOUT
        int "Tree-based hierarchical RCU fanout value"
        range 2 64 if 64BIT
index d3f0aeed2d39fe06aa07cb4147f747af8b7597ee..f8a66424360d22803b2c20b906ada8faa0d2a48d 100644 (file)
@@ -353,8 +353,9 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data)
 
 void __init mount_block_root(char *name, int flags)
 {
-       char *fs_names = __getname_gfp(GFP_KERNEL
-               | __GFP_NOTRACK_FALSE_POSITIVE);
+       struct page *page = alloc_page(GFP_KERNEL |
+                                       __GFP_NOTRACK_FALSE_POSITIVE);
+       char *fs_names = page_address(page);
        char *p;
 #ifdef CONFIG_BLOCK
        char b[BDEVNAME_SIZE];
@@ -406,7 +407,7 @@ retry:
 #endif
        panic("VFS: Unable to mount root fs on %s", b);
 out:
-       putname(fs_names);
+       put_page(page);
 }
  
 #ifdef CONFIG_ROOT_NFS
index 135959a276bef21628556119247be2e4d0d83610..5e4ded51788eb81f277c0b5674f5602730220df4 100644 (file)
 #include <linux/initrd.h>
 #include <linux/sched.h>
 #include <linux/freezer.h>
+#include <linux/kmod.h>
 
 #include "do_mounts.h"
 
 unsigned long initrd_start, initrd_end;
 int initrd_below_start_ok;
 unsigned int real_root_dev;    /* do_proc_dointvec cannot handle kdev_t */
-static int __initdata old_fd, root_fd;
 static int __initdata mount_initrd = 1;
 
 static int __init no_initrd(char *str)
@@ -33,33 +33,29 @@ static int __init no_initrd(char *str)
 
 __setup("noinitrd", no_initrd);
 
-static int __init do_linuxrc(void *_shell)
+static int init_linuxrc(struct subprocess_info *info, struct cred *new)
 {
-       static const char *argv[] = { "linuxrc", NULL, };
-       extern const char *envp_init[];
-       const char *shell = _shell;
-
-       sys_close(old_fd);sys_close(root_fd);
+       sys_unshare(CLONE_FS | CLONE_FILES);
+       /* move initrd over / and chdir/chroot in initrd root */
+       sys_chdir("/root");
+       sys_mount(".", "/", NULL, MS_MOVE, NULL);
+       sys_chroot(".");
        sys_setsid();
-       return kernel_execve(shell, argv, envp_init);
+       return 0;
 }
 
 static void __init handle_initrd(void)
 {
+       static char *argv[] = { "linuxrc", NULL, };
+       extern char *envp_init[];
        int error;
-       int pid;
 
        real_root_dev = new_encode_dev(ROOT_DEV);
        create_dev("/dev/root.old", Root_RAM0);
        /* mount initrd on rootfs' /root */
        mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);
        sys_mkdir("/old", 0700);
-       root_fd = sys_open("/", 0, 0);
-       old_fd = sys_open("/old", 0, 0);
-       /* move initrd over / and chdir/chroot in initrd root */
-       sys_chdir("/root");
-       sys_mount(".", "/", NULL, MS_MOVE, NULL);
-       sys_chroot(".");
+       sys_chdir("/old");
 
        /*
         * In case that a resume from disk is carried out by linuxrc or one of
@@ -67,27 +63,22 @@ static void __init handle_initrd(void)
         */
        current->flags |= PF_FREEZER_SKIP;
 
-       pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
-       if (pid > 0)
-               while (pid != sys_wait4(-1, NULL, 0, NULL))
-                       yield();
+       call_usermodehelper_fns("/linuxrc", argv, envp_init, UMH_WAIT_PROC,
+                       init_linuxrc, NULL, NULL);
 
        current->flags &= ~PF_FREEZER_SKIP;
 
        /* move initrd to rootfs' /old */
-       sys_fchdir(old_fd);
-       sys_mount("/", ".", NULL, MS_MOVE, NULL);
+       sys_mount("..", ".", NULL, MS_MOVE, NULL);
        /* switch root and cwd back to / of rootfs */
-       sys_fchdir(root_fd);
-       sys_chroot(".");
-       sys_close(old_fd);
-       sys_close(root_fd);
+       sys_chroot("..");
 
        if (new_decode_dev(real_root_dev) == Root_RAM0) {
                sys_chdir("/old");
                return;
        }
 
+       sys_chdir("/");
        ROOT_DEV = new_decode_dev(real_root_dev);
        mount_root();
 
index 313360fe1118ffd17591da27c2ba7dacb499c126..9cf77ab138a68738bb6926b8b31aaf6ba8cd4f6e 100644 (file)
@@ -69,6 +69,7 @@
 #include <linux/slab.h>
 #include <linux/perf_event.h>
 #include <linux/file.h>
+#include <linux/ptrace.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -791,17 +792,17 @@ static void __init do_pre_smp_initcalls(void)
                do_one_initcall(*fn);
 }
 
-static void run_init_process(const char *init_filename)
+static int run_init_process(const char *init_filename)
 {
        argv_init[0] = init_filename;
-       kernel_execve(init_filename, argv_init, envp_init);
+       return kernel_execve(init_filename, argv_init, envp_init);
 }
 
-/* This is a non __init function. Force it to be noinline otherwise gcc
- * makes it inline to init() and it becomes part of init.text section
- */
-static noinline int init_post(void)
+static void __init kernel_init_freeable(void);
+
+static int __ref kernel_init(void *unused)
 {
+       kernel_init_freeable();
        /* need to finish all async __init code before freeing the memory */
        async_synchronize_full();
        free_initmem();
@@ -813,7 +814,8 @@ static noinline int init_post(void)
        flush_delayed_fput();
 
        if (ramdisk_execute_command) {
-               run_init_process(ramdisk_execute_command);
+               if (!run_init_process(ramdisk_execute_command))
+                       return 0;
                printk(KERN_WARNING "Failed to execute %s\n",
                                ramdisk_execute_command);
        }
@@ -825,20 +827,22 @@ static noinline int init_post(void)
         * trying to recover a really broken machine.
         */
        if (execute_command) {
-               run_init_process(execute_command);
+               if (!run_init_process(execute_command))
+                       return 0;
                printk(KERN_WARNING "Failed to execute %s.  Attempting "
                                        "defaults...\n", execute_command);
        }
-       run_init_process("/sbin/init");
-       run_init_process("/etc/init");
-       run_init_process("/bin/init");
-       run_init_process("/bin/sh");
+       if (!run_init_process("/sbin/init") ||
+           !run_init_process("/etc/init") ||
+           !run_init_process("/bin/init") ||
+           !run_init_process("/bin/sh"))
+               return 0;
 
        panic("No init found.  Try passing init= option to kernel. "
              "See Linux Documentation/init.txt for guidance.");
 }
 
-static int __init kernel_init(void * unused)
+static void __init kernel_init_freeable(void)
 {
        /*
         * Wait until kthreadd is all set-up.
@@ -893,7 +897,4 @@ static int __init kernel_init(void * unused)
         * we're essentially up and running. Get rid of the
         * initmem segments and start the user-mode stuff..
         */
-
-       init_post();
-       return 0;
 }
index 6b97e2466fad3c82f50d914c4bbd1724eb8d2dec..71a3ca18c873938238d03abed6c2cf8bb577d130 100644 (file)
@@ -772,7 +772,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
 {
        struct path path;
        struct file *filp;
-       char *name;
+       struct filename *name;
        struct mq_attr attr;
        int fd, error;
        struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
@@ -795,7 +795,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
        ro = mnt_want_write(mnt);       /* we'll drop it in any case */
        error = 0;
        mutex_lock(&root->d_inode->i_mutex);
-       path.dentry = lookup_one_len(name, root, strlen(name));
+       path.dentry = lookup_one_len(name->name, root, strlen(name->name));
        if (IS_ERR(path.dentry)) {
                error = PTR_ERR(path.dentry);
                goto out_putfd;
@@ -804,7 +804,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
 
        if (oflag & O_CREAT) {
                if (path.dentry->d_inode) {     /* entry already exists */
-                       audit_inode(name, path.dentry);
+                       audit_inode(name, path.dentry, 0);
                        if (oflag & O_EXCL) {
                                error = -EEXIST;
                                goto out;
@@ -824,7 +824,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
                        error = -ENOENT;
                        goto out;
                }
-               audit_inode(name, path.dentry);
+               audit_inode(name, path.dentry, 0);
                filp = do_open(&path, oflag);
        }
 
@@ -849,7 +849,7 @@ out_putname:
 SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
 {
        int err;
-       char *name;
+       struct filename *name;
        struct dentry *dentry;
        struct inode *inode = NULL;
        struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
@@ -863,7 +863,8 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
        if (err)
                goto out_name;
        mutex_lock_nested(&mnt->mnt_root->d_inode->i_mutex, I_MUTEX_PARENT);
-       dentry = lookup_one_len(name, mnt->mnt_root, strlen(name));
+       dentry = lookup_one_len(name->name, mnt->mnt_root,
+                               strlen(name->name));
        if (IS_ERR(dentry)) {
                err = PTR_ERR(dentry);
                goto out_unlock;
@@ -978,7 +979,7 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
                goto out_fput;
        }
        info = MQUEUE_I(inode);
-       audit_inode(NULL, f.file->f_path.dentry);
+       audit_inode(NULL, f.file->f_path.dentry, 0);
 
        if (unlikely(!(f.file->f_mode & FMODE_WRITE))) {
                ret = -EBADF;
@@ -1094,7 +1095,7 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
                goto out_fput;
        }
        info = MQUEUE_I(inode);
-       audit_inode(NULL, f.file->f_path.dentry);
+       audit_inode(NULL, f.file->f_path.dentry, 0);
 
        if (unlikely(!(f.file->f_mode & FMODE_READ))) {
                ret = -EBADF;
index 6cd7529c9e6a31a7702c77f38c45289f72d907b8..051e071a06e7a745a96c2fac6317d330dc33da43 100644 (file)
@@ -193,7 +193,7 @@ static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file,
        }
 }
 
-static int acct_on(char *name)
+static int acct_on(struct filename *pathname)
 {
        struct file *file;
        struct vfsmount *mnt;
@@ -201,7 +201,7 @@ static int acct_on(char *name)
        struct bsd_acct_struct *acct = NULL;
 
        /* Difference from BSD - they don't do O_APPEND */
-       file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
+       file = file_open_name(pathname, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
        if (IS_ERR(file))
                return PTR_ERR(file);
 
@@ -260,7 +260,7 @@ SYSCALL_DEFINE1(acct, const char __user *, name)
                return -EPERM;
 
        if (name) {
-               char *tmp = getname(name);
+               struct filename *tmp = getname(name);
                if (IS_ERR(tmp))
                        return (PTR_ERR(tmp));
                error = acct_on(tmp);
index 4d0ceede33194e4d29334899ce3c85dba141fb65..40414e9143db609b194b04e95c798351118f07b7 100644 (file)
@@ -1440,6 +1440,8 @@ void audit_log_link_denied(const char *operation, struct path *link)
 
        ab = audit_log_start(current->audit_context, GFP_KERNEL,
                             AUDIT_ANOM_LINK);
+       if (!ab)
+               return;
        audit_log_format(ab, "op=%s action=denied", operation);
        audit_log_format(ab, " pid=%d comm=", current->pid);
        audit_log_untrustedstring(ab, current->comm);
index 9eb3d79482b64ca398ed38ae4b9ab861048a17a1..d51cba868e1b50fa14877dc4eefdf6be0f3fc1ba 100644 (file)
@@ -74,12 +74,15 @@ static inline int audit_hash_ino(u32 ino)
        return (ino & (AUDIT_INODE_BUCKETS-1));
 }
 
+/* Indicates that audit should log the full pathname. */
+#define AUDIT_NAME_FULL -1
+
 extern int audit_match_class(int class, unsigned syscall);
 extern int audit_comparator(const u32 left, const u32 op, const u32 right);
 extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right);
 extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right);
-extern int audit_compare_dname_path(const char *dname, const char *path,
-                                   int *dirlen);
+extern int parent_len(const char *path);
+extern int audit_compare_dname_path(const char *dname, const char *path, int plen);
 extern struct sk_buff *            audit_make_reply(int pid, int seq, int type,
                                             int done, int multi,
                                             const void *payload, int size);
index 1c22ec3d87bc6f24c2b33a4086cb460812e0387c..9a9ae6e3d290025179a964c577de517f24fbe75c 100644 (file)
@@ -265,7 +265,8 @@ static void audit_update_watch(struct audit_parent *parent,
        /* Run all of the watches on this parent looking for the one that
         * matches the given dname */
        list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
-               if (audit_compare_dname_path(dname, owatch->path, NULL))
+               if (audit_compare_dname_path(dname, owatch->path,
+                                            AUDIT_NAME_FULL))
                        continue;
 
                /* If the update involves invalidating rules, do the inode-based
index c4bcdbaf4d4de9bdc6f22de554c4bb18c8e9ca93..7f19f23d38a3347373ec00a629c6c0b39a8f770a 100644 (file)
@@ -1298,41 +1298,60 @@ int audit_gid_comparator(kgid_t left, u32 op, kgid_t right)
        }
 }
 
-/* Compare given dentry name with last component in given path,
- * return of 0 indicates a match. */
-int audit_compare_dname_path(const char *dname, const char *path,
-                            int *dirlen)
+/**
+ * parent_len - find the length of the parent portion of a pathname
+ * @path: pathname of which to determine length
+ */
+int parent_len(const char *path)
 {
-       int dlen, plen;
+       int plen;
        const char *p;
 
-       if (!dname || !path)
-               return 1;
-
-       dlen = strlen(dname);
        plen = strlen(path);
-       if (plen < dlen)
-               return 1;
+
+       if (plen == 0)
+               return plen;
 
        /* disregard trailing slashes */
        p = path + plen - 1;
        while ((*p == '/') && (p > path))
                p--;
 
-       /* find last path component */
-       p = p - dlen + 1;
-       if (p < path)
+       /* walk backward until we find the next slash or hit beginning */
+       while ((*p != '/') && (p > path))
+               p--;
+
+       /* did we find a slash? Then increment to include it in path */
+       if (*p == '/')
+               p++;
+
+       return p - path;
+}
+
+/**
+ * audit_compare_dname_path - compare given dentry name with last component in
+ *                           given path. Return of 0 indicates a match.
+ * @dname:     dentry name that we're comparing
+ * @path:      full pathname that we're comparing
+ * @parentlen: length of the parent if known. Passing in AUDIT_NAME_FULL
+ *             here indicates that we must compute this value.
+ */
+int audit_compare_dname_path(const char *dname, const char *path, int parentlen)
+{
+       int dlen, pathlen;
+       const char *p;
+
+       dlen = strlen(dname);
+       pathlen = strlen(path);
+       if (pathlen < dlen)
                return 1;
-       else if (p > path) {
-               if (*--p != '/')
-                       return 1;
-               else
-                       p++;
-       }
 
-       /* return length of path's directory component */
-       if (dirlen)
-               *dirlen = p - path;
+       parentlen = parentlen == AUDIT_NAME_FULL ? parent_len(path) : parentlen;
+       if (pathlen - parentlen != dlen)
+               return 1;
+
+       p = path + parentlen;
+
        return strncmp(p, dname, dlen);
 }
 
index f4a7756f999cddcf344e685ea561f358812c41fd..2f186ed80c40589ef9662fb400c82c1a95854f6a 100644 (file)
@@ -81,9 +81,6 @@
  * a name dynamically and also add those to the list anchored by names_list. */
 #define AUDIT_NAMES    5
 
-/* Indicates that audit should log the full pathname. */
-#define AUDIT_NAME_FULL -1
-
 /* no execve audit message should be longer than this (userspace limits) */
 #define MAX_EXECVE_AUDIT_LEN 7500
 
@@ -106,27 +103,29 @@ struct audit_cap_data {
  * we don't let putname() free it (instead we free all of the saved
  * pointers at syscall exit time).
  *
- * Further, in fs/namei.c:path_lookup() we store the inode and device. */
+ * Further, in fs/namei.c:path_lookup() we store the inode and device.
+ */
 struct audit_names {
-       struct list_head list;          /* audit_context->names_list */
-       const char      *name;
-       unsigned long   ino;
-       dev_t           dev;
-       umode_t         mode;
-       kuid_t          uid;
-       kgid_t          gid;
-       dev_t           rdev;
-       u32             osid;
-       struct audit_cap_data fcap;
-       unsigned int    fcap_ver;
-       int             name_len;       /* number of name's characters to log */
-       bool            name_put;       /* call __putname() for this name */
+       struct list_head        list;           /* audit_context->names_list */
+       struct filename *name;
+       unsigned long           ino;
+       dev_t                   dev;
+       umode_t                 mode;
+       kuid_t                  uid;
+       kgid_t                  gid;
+       dev_t                   rdev;
+       u32                     osid;
+       struct audit_cap_data    fcap;
+       unsigned int            fcap_ver;
+       int                     name_len;       /* number of name's characters to log */
+       unsigned char           type;           /* record type */
+       bool                    name_put;       /* call __putname() for this name */
        /*
         * This was an allocated audit_names and not from the array of
         * names allocated in the task audit context.  Thus this name
         * should be freed on syscall exit
         */
-       bool            should_free;
+       bool                    should_free;
 };
 
 struct audit_aux_data {
@@ -998,7 +997,7 @@ static inline void audit_free_names(struct audit_context *context)
                       context->ino_count);
                list_for_each_entry(n, &context->names_list, list) {
                        printk(KERN_ERR "names[%d] = %p = %s\n", i,
-                              n->name, n->name ?: "(null)");
+                              n->name, n->name->name ?: "(null)");
                }
                dump_stack();
                return;
@@ -1555,7 +1554,7 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
                case AUDIT_NAME_FULL:
                        /* log the full path */
                        audit_log_format(ab, " name=");
-                       audit_log_untrustedstring(ab, n->name);
+                       audit_log_untrustedstring(ab, n->name->name);
                        break;
                case 0:
                        /* name was specified as a relative path and the
@@ -1565,7 +1564,7 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
                default:
                        /* log the name's directory component */
                        audit_log_format(ab, " name=");
-                       audit_log_n_untrustedstring(ab, n->name,
+                       audit_log_n_untrustedstring(ab, n->name->name,
                                                    n->name_len);
                }
        } else
@@ -1995,7 +1994,8 @@ retry:
 #endif
 }
 
-static struct audit_names *audit_alloc_name(struct audit_context *context)
+static struct audit_names *audit_alloc_name(struct audit_context *context,
+                                               unsigned char type)
 {
        struct audit_names *aname;
 
@@ -2010,6 +2010,7 @@ static struct audit_names *audit_alloc_name(struct audit_context *context)
        }
 
        aname->ino = (unsigned long)-1;
+       aname->type = type;
        list_add_tail(&aname->list, &context->names_list);
 
        context->name_count++;
@@ -2019,6 +2020,29 @@ static struct audit_names *audit_alloc_name(struct audit_context *context)
        return aname;
 }
 
+/**
+ * audit_reusename - fill out filename with info from existing entry
+ * @uptr: userland ptr to pathname
+ *
+ * Search the audit_names list for the current audit context. If there is an
+ * existing entry with a matching "uptr" then return the filename
+ * associated with that audit_name. If not, return NULL.
+ */
+struct filename *
+__audit_reusename(const __user char *uptr)
+{
+       struct audit_context *context = current->audit_context;
+       struct audit_names *n;
+
+       list_for_each_entry(n, &context->names_list, list) {
+               if (!n->name)
+                       continue;
+               if (n->name->uptr == uptr)
+                       return n->name;
+       }
+       return NULL;
+}
+
 /**
  * audit_getname - add a name to the list
  * @name: name to add
@@ -2026,7 +2050,7 @@ static struct audit_names *audit_alloc_name(struct audit_context *context)
  * Add a name to the list of audit names for this context.
  * Called from fs/namei.c:getname().
  */
-void __audit_getname(const char *name)
+void __audit_getname(struct filename *name)
 {
        struct audit_context *context = current->audit_context;
        struct audit_names *n;
@@ -2040,13 +2064,19 @@ void __audit_getname(const char *name)
                return;
        }
 
-       n = audit_alloc_name(context);
+#if AUDIT_DEBUG
+       /* The filename _must_ have a populated ->name */
+       BUG_ON(!name->name);
+#endif
+
+       n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
        if (!n)
                return;
 
        n->name = name;
        n->name_len = AUDIT_NAME_FULL;
        n->name_put = true;
+       name->aname = n;
 
        if (!context->pwd.dentry)
                get_fs_pwd(current->fs, &context->pwd);
@@ -2059,7 +2089,7 @@ void __audit_getname(const char *name)
  * then we delay the putname until syscall exit.
  * Called from include/linux/fs.h:putname().
  */
-void audit_putname(const char *name)
+void audit_putname(struct filename *name)
 {
        struct audit_context *context = current->audit_context;
 
@@ -2074,7 +2104,7 @@ void audit_putname(const char *name)
 
                        list_for_each_entry(n, &context->names_list, list)
                                printk(KERN_ERR "name[%d] = %p = %s\n", i,
-                                      n->name, n->name ?: "(null)");
+                                      n->name, n->name->name ?: "(null)");
                        }
 #endif
                __putname(name);
@@ -2088,8 +2118,8 @@ void audit_putname(const char *name)
                               " put_count=%d\n",
                               __FILE__, __LINE__,
                               context->serial, context->major,
-                              context->in_syscall, name, context->name_count,
-                              context->put_count);
+                              context->in_syscall, name->name,
+                              context->name_count, context->put_count);
                        dump_stack();
                }
        }
@@ -2132,13 +2162,13 @@ static void audit_copy_inode(struct audit_names *name, const struct dentry *dent
 }
 
 /**
- * audit_inode - store the inode and device from a lookup
+ * __audit_inode - store the inode and device from a lookup
  * @name: name being audited
  * @dentry: dentry being audited
- *
- * Called from fs/namei.c:path_lookup().
+ * @parent: does this dentry represent the parent?
  */
-void __audit_inode(const char *name, const struct dentry *dentry)
+void __audit_inode(struct filename *name, const struct dentry *dentry,
+                  unsigned int parent)
 {
        struct audit_context *context = current->audit_context;
        const struct inode *inode = dentry->d_inode;
@@ -2147,24 +2177,69 @@ void __audit_inode(const char *name, const struct dentry *dentry)
        if (!context->in_syscall)
                return;
 
+       if (!name)
+               goto out_alloc;
+
+#if AUDIT_DEBUG
+       /* The struct filename _must_ have a populated ->name */
+       BUG_ON(!name->name);
+#endif
+       /*
+        * If we have a pointer to an audit_names entry already, then we can
+        * just use it directly if the type is correct.
+        */
+       n = name->aname;
+       if (n) {
+               if (parent) {
+                       if (n->type == AUDIT_TYPE_PARENT ||
+                           n->type == AUDIT_TYPE_UNKNOWN)
+                               goto out;
+               } else {
+                       if (n->type != AUDIT_TYPE_PARENT)
+                               goto out;
+               }
+       }
+
        list_for_each_entry_reverse(n, &context->names_list, list) {
-               if (n->name && (n->name == name))
-                       goto out;
+               /* does the name pointer match? */
+               if (!n->name || n->name->name != name->name)
+                       continue;
+
+               /* match the correct record type */
+               if (parent) {
+                       if (n->type == AUDIT_TYPE_PARENT ||
+                           n->type == AUDIT_TYPE_UNKNOWN)
+                               goto out;
+               } else {
+                       if (n->type != AUDIT_TYPE_PARENT)
+                               goto out;
+               }
        }
 
-       /* unable to find the name from a previous getname() */
-       n = audit_alloc_name(context);
+out_alloc:
+       /* unable to find the name from a previous getname(). Allocate a new
+        * anonymous entry.
+        */
+       n = audit_alloc_name(context, AUDIT_TYPE_NORMAL);
        if (!n)
                return;
 out:
+       if (parent) {
+               n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL;
+               n->type = AUDIT_TYPE_PARENT;
+       } else {
+               n->name_len = AUDIT_NAME_FULL;
+               n->type = AUDIT_TYPE_NORMAL;
+       }
        handle_path(dentry);
        audit_copy_inode(n, dentry, inode);
 }
 
 /**
- * audit_inode_child - collect inode info for created/removed objects
- * @dentry: dentry being audited
+ * __audit_inode_child - collect inode info for created/removed objects
  * @parent: inode of dentry parent
+ * @dentry: dentry being audited
+ * @type:   AUDIT_TYPE_* value that we're looking for
  *
  * For syscalls that create or remove filesystem objects, audit_inode
  * can only collect information for the filesystem object's parent.
@@ -2174,15 +2249,14 @@ out:
  * must be hooked prior, in order to capture the target inode during
  * unsuccessful attempts.
  */
-void __audit_inode_child(const struct dentry *dentry,
-                        const struct inode *parent)
+void __audit_inode_child(const struct inode *parent,
+                        const struct dentry *dentry,
+                        const unsigned char type)
 {
        struct audit_context *context = current->audit_context;
-       const char *found_parent = NULL, *found_child = NULL;
        const struct inode *inode = dentry->d_inode;
        const char *dname = dentry->d_name.name;
-       struct audit_names *n;
-       int dirlen = 0;
+       struct audit_names *n, *found_parent = NULL, *found_child = NULL;
 
        if (!context->in_syscall)
                return;
@@ -2190,62 +2264,65 @@ void __audit_inode_child(const struct dentry *dentry,
        if (inode)
                handle_one(inode);
 
-       /* parent is more likely, look for it first */
+       /* look for a parent entry first */
        list_for_each_entry(n, &context->names_list, list) {
-               if (!n->name)
+               if (!n->name || n->type != AUDIT_TYPE_PARENT)
                        continue;
 
                if (n->ino == parent->i_ino &&
-                   !audit_compare_dname_path(dname, n->name, &dirlen)) {
-                       n->name_len = dirlen; /* update parent data in place */
-                       found_parent = n->name;
-                       goto add_names;
+                   !audit_compare_dname_path(dname, n->name->name, n->name_len)) {
+                       found_parent = n;
+                       break;
                }
        }
 
-       /* no matching parent, look for matching child */
+       /* is there a matching child entry? */
        list_for_each_entry(n, &context->names_list, list) {
-               if (!n->name)
+               /* can only match entries that have a name */
+               if (!n->name || n->type != type)
                        continue;
 
-               /* strcmp() is the more likely scenario */
-               if (!strcmp(dname, n->name) ||
-                    !audit_compare_dname_path(dname, n->name, &dirlen)) {
-                       if (inode)
-                               audit_copy_inode(n, NULL, inode);
-                       else
-                               n->ino = (unsigned long)-1;
-                       found_child = n->name;
-                       goto add_names;
+               /* if we found a parent, make sure this one is a child of it */
+               if (found_parent && (n->name != found_parent->name))
+                       continue;
+
+               if (!strcmp(dname, n->name->name) ||
+                   !audit_compare_dname_path(dname, n->name->name,
+                                               found_parent ?
+                                               found_parent->name_len :
+                                               AUDIT_NAME_FULL)) {
+                       found_child = n;
+                       break;
                }
        }
 
-add_names:
        if (!found_parent) {
-               n = audit_alloc_name(context);
+               /* create a new, "anonymous" parent record */
+               n = audit_alloc_name(context, AUDIT_TYPE_PARENT);
                if (!n)
                        return;
                audit_copy_inode(n, NULL, parent);
        }
 
        if (!found_child) {
-               n = audit_alloc_name(context);
-               if (!n)
+               found_child = audit_alloc_name(context, type);
+               if (!found_child)
                        return;
 
                /* Re-use the name belonging to the slot for a matching parent
                 * directory. All names for this context are relinquished in
                 * audit_free_names() */
                if (found_parent) {
-                       n->name = found_parent;
-                       n->name_len = AUDIT_NAME_FULL;
+                       found_child->name = found_parent->name;
+                       found_child->name_len = AUDIT_NAME_FULL;
                        /* don't call __putname() */
-                       n->name_put = false;
+                       found_child->name_put = false;
                }
-
-               if (inode)
-                       audit_copy_inode(n, NULL, inode);
        }
+       if (inode)
+               audit_copy_inode(found_child, dentry, inode);
+       else
+               found_child->ino = (unsigned long)-1;
 }
 EXPORT_SYMBOL_GPL(__audit_inode_child);
 
index 17e073c309e64a907bdd512c16ae19977223594c..9a61738cefc8828c310618cd9dc6bd1d0ec44959 100644 (file)
@@ -696,6 +696,22 @@ out:
        return ret;
 }
 
+/*
+ * GDB places a breakpoint at this function to know dynamically
+ * loaded objects. It's not defined static so that only one instance with this
+ * name exists in the kernel.
+ */
+
+static int module_event(struct notifier_block *self, unsigned long val,
+       void *data)
+{
+       return 0;
+}
+
+static struct notifier_block dbg_module_load_nb = {
+       .notifier_call  = module_event,
+};
+
 int kgdb_nmicallback(int cpu, void *regs)
 {
 #ifdef CONFIG_SMP
@@ -824,6 +840,7 @@ static void kgdb_register_callbacks(void)
                kgdb_arch_init();
                if (!dbg_is_early)
                        kgdb_arch_late();
+               register_module_notifier(&dbg_module_load_nb);
                register_reboot_notifier(&dbg_reboot_notifier);
                atomic_notifier_chain_register(&panic_notifier_list,
                                               &kgdb_panic_event_nb);
@@ -847,6 +864,7 @@ static void kgdb_unregister_callbacks(void)
        if (kgdb_io_module_registered) {
                kgdb_io_module_registered = 0;
                unregister_reboot_notifier(&dbg_reboot_notifier);
+               unregister_module_notifier(&dbg_module_load_nb);
                atomic_notifier_chain_unregister(&panic_notifier_list,
                                               &kgdb_panic_event_nb);
                kgdb_arch_exit();
index 07c9bbb94a0b3016e9b0d0d11d5c4f6a94cd1658..b03e0e814e43b9f05f598f14f5f9a06618f3f21a 100644 (file)
@@ -129,6 +129,8 @@ kdb_bt(int argc, const char **argv)
                }
                /* Now the inactive tasks */
                kdb_do_each_thread(g, p) {
+                       if (KDB_FLAG(CMD_INTERRUPT))
+                               return 0;
                        if (task_curr(p))
                                continue;
                        if (kdb_bt1(p, mask, argcount, btaprompt))
index 0a69d2adc4f3cb7fb49a14c3ccefb87cfe0084bd..14ff4849262c0c6ecb275ba30da19724819b548c 100644 (file)
@@ -552,6 +552,7 @@ int vkdb_printf(const char *fmt, va_list ap)
 {
        int diag;
        int linecount;
+       int colcount;
        int logging, saved_loglevel = 0;
        int saved_trap_printk;
        int got_printf_lock = 0;
@@ -584,6 +585,10 @@ int vkdb_printf(const char *fmt, va_list ap)
        if (diag || linecount <= 1)
                linecount = 24;
 
+       diag = kdbgetintenv("COLUMNS", &colcount);
+       if (diag || colcount <= 1)
+               colcount = 80;
+
        diag = kdbgetintenv("LOGGING", &logging);
        if (diag)
                logging = 0;
@@ -690,7 +695,7 @@ kdb_printit:
                gdbstub_msg_write(kdb_buffer, retlen);
        } else {
                if (dbg_io_ops && !dbg_io_ops->is_console) {
-                       len = strlen(kdb_buffer);
+                       len = retlen;
                        cp = kdb_buffer;
                        while (len--) {
                                dbg_io_ops->write_char(*cp);
@@ -709,11 +714,29 @@ kdb_printit:
                printk(KERN_INFO "%s", kdb_buffer);
        }
 
-       if (KDB_STATE(PAGER) && strchr(kdb_buffer, '\n'))
-               kdb_nextline++;
+       if (KDB_STATE(PAGER)) {
+               /*
+                * Check printed string to decide how to bump the
+                * kdb_nextline to control when the more prompt should
+                * show up.
+                */
+               int got = 0;
+               len = retlen;
+               while (len--) {
+                       if (kdb_buffer[len] == '\n') {
+                               kdb_nextline++;
+                               got = 0;
+                       } else if (kdb_buffer[len] == '\r') {
+                               got = 0;
+                       } else {
+                               got++;
+                       }
+               }
+               kdb_nextline += got / (colcount + 1);
+       }
 
        /* check for having reached the LINES number of printed lines */
-       if (kdb_nextline == linecount) {
+       if (kdb_nextline >= linecount) {
                char buf1[16] = "";
 
                /* Watch out for recursion here.  Any routine that calls
@@ -765,7 +788,7 @@ kdb_printit:
                        kdb_grepping_flag = 0;
                        kdb_printf("\n");
                } else if (buf1[0] == ' ') {
-                       kdb_printf("\n");
+                       kdb_printf("\r");
                        suspend_grep = 1; /* for this recursion */
                } else if (buf1[0] == '\n') {
                        kdb_nextline = linecount - 1;
index 1261dc7eaeb9723dd0f14349d17581a6936a80a8..4d5f8d5612f349389fee0c22442267b6545c3931 100644 (file)
@@ -2101,6 +2101,8 @@ static int kdb_dmesg(int argc, const char **argv)
                }
                if (!lines--)
                        break;
+               if (KDB_FLAG(CMD_INTERRUPT))
+                       return 0;
 
                kdb_printf("%.*s\n", (int)len - 1, buf);
        }
index cda3ebd49e86f1d219ae9cbd2eaa357e2b48888b..dbccf83c134d86422c0f1ef8fd9d7c81ede05ac4 100644 (file)
@@ -372,6 +372,8 @@ void perf_cgroup_switch(struct task_struct *task, int mode)
 
        list_for_each_entry_rcu(pmu, &pmus, entry) {
                cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
+               if (cpuctx->unique_pmu != pmu)
+                       continue; /* ensure we process each cpuctx once */
 
                /*
                 * perf_cgroup_events says at least one
@@ -395,9 +397,10 @@ void perf_cgroup_switch(struct task_struct *task, int mode)
 
                        if (mode & PERF_CGROUP_SWIN) {
                                WARN_ON_ONCE(cpuctx->cgrp);
-                               /* set cgrp before ctxsw in to
-                                * allow event_filter_match() to not
-                                * have to pass task around
+                               /*
+                                * set cgrp before ctxsw in to allow
+                                * event_filter_match() to not have to pass
+                                * task around
                                 */
                                cpuctx->cgrp = perf_cgroup_from_task(task);
                                cpu_ctx_sched_in(cpuctx, EVENT_ALL, task);
@@ -4412,7 +4415,7 @@ static void perf_event_task_event(struct perf_task_event *task_event)
        rcu_read_lock();
        list_for_each_entry_rcu(pmu, &pmus, entry) {
                cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
-               if (cpuctx->active_pmu != pmu)
+               if (cpuctx->unique_pmu != pmu)
                        goto next;
                perf_event_task_ctx(&cpuctx->ctx, task_event);
 
@@ -4558,7 +4561,7 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)
        rcu_read_lock();
        list_for_each_entry_rcu(pmu, &pmus, entry) {
                cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
-               if (cpuctx->active_pmu != pmu)
+               if (cpuctx->unique_pmu != pmu)
                        goto next;
                perf_event_comm_ctx(&cpuctx->ctx, comm_event);
 
@@ -4754,7 +4757,7 @@ got_name:
        rcu_read_lock();
        list_for_each_entry_rcu(pmu, &pmus, entry) {
                cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
-               if (cpuctx->active_pmu != pmu)
+               if (cpuctx->unique_pmu != pmu)
                        goto next;
                perf_event_mmap_ctx(&cpuctx->ctx, mmap_event,
                                        vma->vm_flags & VM_EXEC);
@@ -5855,8 +5858,8 @@ static void update_pmu_context(struct pmu *pmu, struct pmu *old_pmu)
 
                cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
 
-               if (cpuctx->active_pmu == old_pmu)
-                       cpuctx->active_pmu = pmu;
+               if (cpuctx->unique_pmu == old_pmu)
+                       cpuctx->unique_pmu = pmu;
        }
 }
 
@@ -5991,7 +5994,7 @@ skip_type:
                cpuctx->ctx.pmu = pmu;
                cpuctx->jiffies_interval = 1;
                INIT_LIST_HEAD(&cpuctx->rotation_list);
-               cpuctx->active_pmu = pmu;
+               cpuctx->unique_pmu = pmu;
        }
 
 got_cpu_context:
index 1cd7d581b3b2da32e07c57a8342d597ee7ceb73f..8b20ab7d3aa2951eff91a4e09e0af23a90992747 100644 (file)
@@ -1584,7 +1584,7 @@ long do_fork(unsigned long clone_flags,
         * requested, no event is reported; otherwise, report if the event
         * for the type of forking is enabled.
         */
-       if (likely(user_mode(regs)) && !(clone_flags & CLONE_UNTRACED)) {
+       if (!(clone_flags & CLONE_UNTRACED) && likely(user_mode(regs))) {
                if (clone_flags & CLONE_VFORK)
                        trace = PTRACE_EVENT_VFORK;
                else if ((clone_flags & CSIGNAL) != SIGCHLD)
@@ -1634,6 +1634,17 @@ long do_fork(unsigned long clone_flags,
        return nr;
 }
 
+#ifdef CONFIG_GENERIC_KERNEL_THREAD
+/*
+ * Create a kernel thread.
+ */
+pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+       return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn, NULL,
+               (unsigned long)arg, NULL, NULL);
+}
+#endif
+
 #ifndef ARCH_MIN_MMSTRUCT_ALIGN
 #define ARCH_MIN_MMSTRUCT_ALIGN 0
 #endif
index 49a77727db42603e8e0ac963416d0f6b57823636..4e69e24d3d7d94b4c895735765e06f2f47a95db0 100644 (file)
@@ -148,7 +148,8 @@ static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
  * @host_data: Controller private data pointer
  *
  * Allocates a legacy irq_domain if irq_base is positive or a linear
- * domain otherwise.
+ * domain otherwise. For the legacy domain, IRQ descriptors will also
+ * be allocated.
  *
  * This is intended to implement the expected behaviour for most
  * interrupt controllers which is that a linear mapping should
@@ -162,11 +163,33 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
                                         const struct irq_domain_ops *ops,
                                         void *host_data)
 {
-       if (first_irq > 0)
-               return irq_domain_add_legacy(of_node, size, first_irq, 0,
+       if (first_irq > 0) {
+               int irq_base;
+
+               if (IS_ENABLED(CONFIG_SPARSE_IRQ)) {
+                       /*
+                        * Set the descriptor allocator to search for a
+                        * 1-to-1 mapping, such as irq_alloc_desc_at().
+                        * Use of_node_to_nid() which is defined to
+                        * numa_node_id() on platforms that have no custom
+                        * implementation.
+                        */
+                       irq_base = irq_alloc_descs(first_irq, first_irq, size,
+                                                  of_node_to_nid(of_node));
+                       if (irq_base < 0) {
+                               WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
+                                    first_irq);
+                               irq_base = first_irq;
+                       }
+               } else
+                       irq_base = first_irq;
+
+               return irq_domain_add_legacy(of_node, size, irq_base, 0,
                                             ops, host_data);
-       else
-               return irq_domain_add_linear(of_node, size, ops, host_data);
+       }
+
+       /* A linear domain is the default */
+       return irq_domain_add_linear(of_node, size, ops, host_data);
 }
 
 /**
index 6f99aead66c6b897fbe14b9fb03b2a77bd17bc47..1c317e386831869a3c4ff17a675a06b3b985c06d 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/notifier.h>
 #include <linux/suspend.h>
 #include <linux/rwsem.h>
+#include <linux/ptrace.h>
 #include <asm/uaccess.h>
 
 #include <trace/events/module.h>
@@ -221,11 +222,13 @@ static int ____call_usermodehelper(void *data)
        retval = kernel_execve(sub_info->path,
                               (const char *const *)sub_info->argv,
                               (const char *const *)sub_info->envp);
+       if (!retval)
+               return 0;
 
        /* Exec failed? */
 fail:
        sub_info->retval = retval;
-       return 0;
+       do_exit(0);
 }
 
 static int call_helper(void *data)
@@ -292,7 +295,7 @@ static int wait_for_helper(void *data)
        }
 
        umh_complete(sub_info);
-       return 0;
+       do_exit(0);
 }
 
 /* This is run by khelper thread  */
index 146a6fa968254fe00b4aa6a4a423113f083b3e89..29fb60caecb53125fa76e852609d38f4380cab4c 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/freezer.h>
+#include <linux/ptrace.h>
 #include <trace/events/sched.h>
 
 static DEFINE_SPINLOCK(kthread_create_lock);
index 4fb2376ddf0660575970a29db0637ac4c70c2020..74df86bd9204aef5ec9d14ca8b4b0094777bef87 100644 (file)
@@ -74,6 +74,7 @@ static struct lock_class_key rcu_fqs_class[RCU_NUM_LVLS];
        .orphan_nxttail = &sname##_state.orphan_nxtlist, \
        .orphan_donetail = &sname##_state.orphan_donelist, \
        .barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \
+       .onoff_mutex = __MUTEX_INITIALIZER(sname##_state.onoff_mutex), \
        .name = #sname, \
 }
 
@@ -1197,7 +1198,7 @@ static int rcu_gp_init(struct rcu_state *rsp)
        raw_spin_unlock_irq(&rnp->lock);
 
        /* Exclude any concurrent CPU-hotplug operations. */
-       get_online_cpus();
+       mutex_lock(&rsp->onoff_mutex);
 
        /*
         * Set the quiescent-state-needed bits in all the rcu_node
@@ -1234,7 +1235,7 @@ static int rcu_gp_init(struct rcu_state *rsp)
                cond_resched();
        }
 
-       put_online_cpus();
+       mutex_unlock(&rsp->onoff_mutex);
        return 1;
 }
 
@@ -1700,6 +1701,7 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
        /* Remove the dead CPU from the bitmasks in the rcu_node hierarchy. */
 
        /* Exclude any attempts to start a new grace period. */
+       mutex_lock(&rsp->onoff_mutex);
        raw_spin_lock_irqsave(&rsp->onofflock, flags);
 
        /* Orphan the dead CPU's callbacks, and adopt them if appropriate. */
@@ -1744,6 +1746,7 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
        init_callback_list(rdp);
        /* Disallow further callbacks on this CPU. */
        rdp->nxttail[RCU_NEXT_TAIL] = NULL;
+       mutex_unlock(&rsp->onoff_mutex);
 }
 
 #else /* #ifdef CONFIG_HOTPLUG_CPU */
@@ -2648,6 +2651,9 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
        struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
        struct rcu_node *rnp = rcu_get_root(rsp);
 
+       /* Exclude new grace periods. */
+       mutex_lock(&rsp->onoff_mutex);
+
        /* Set up local state, ensuring consistent view of global state. */
        raw_spin_lock_irqsave(&rnp->lock, flags);
        rdp->beenonline = 1;     /* We have now been online. */
@@ -2662,14 +2668,6 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
        rcu_prepare_for_idle_init(cpu);
        raw_spin_unlock(&rnp->lock);            /* irqs remain disabled. */
 
-       /*
-        * A new grace period might start here.  If so, we won't be part
-        * of it, but that is OK, as we are currently in a quiescent state.
-        */
-
-       /* Exclude any attempts to start a new GP on large systems. */
-       raw_spin_lock(&rsp->onofflock);         /* irqs already disabled. */
-
        /* Add CPU to rcu_node bitmasks. */
        rnp = rdp->mynode;
        mask = rdp->grpmask;
@@ -2693,8 +2691,9 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
                raw_spin_unlock(&rnp->lock); /* irqs already disabled. */
                rnp = rnp->parent;
        } while (rnp != NULL && !(rnp->qsmaskinit & mask));
+       local_irq_restore(flags);
 
-       raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
+       mutex_unlock(&rsp->onoff_mutex);
 }
 
 static void __cpuinit rcu_prepare_cpu(int cpu)
index 5faf05d683265222127e6496668b6821018ff999..a240f032848eec8d00e156da54fce3cd24a4b525 100644 (file)
@@ -394,11 +394,17 @@ struct rcu_state {
        struct rcu_head **orphan_donetail;      /* Tail of above. */
        long qlen_lazy;                         /* Number of lazy callbacks. */
        long qlen;                              /* Total number of callbacks. */
+       /* End of fields guarded by onofflock. */
+
+       struct mutex onoff_mutex;               /* Coordinate hotplug & GPs. */
+
        struct mutex barrier_mutex;             /* Guards barrier fields. */
        atomic_t barrier_cpu_count;             /* # CPUs waiting on. */
        struct completion barrier_completion;   /* Wake at barrier end. */
        unsigned long n_barrier_done;           /* ++ at start and end of */
                                                /*  _rcu_barrier(). */
+       /* End of fields guarded by barrier_mutex. */
+
        unsigned long jiffies_force_qs;         /* Time at which to invoke */
                                                /*  force_quiescent_state(). */
        unsigned long n_force_qs;               /* Number of calls to */
index c1774723643838ea565a9419838bc0509ee48353..2d8927fda712f5ee1e19f1fe364fbad557d8a736 100644 (file)
@@ -505,7 +505,7 @@ static inline void init_hrtick(void)
 #ifdef CONFIG_SMP
 
 #ifndef tsk_is_polling
-#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+#define tsk_is_polling(t) 0
 #endif
 
 void resched_task(struct task_struct *p)
@@ -6122,6 +6122,17 @@ static void sched_init_numa(void)
         * numbers.
         */
 
+       /*
+        * Here, we should temporarily reset sched_domains_numa_levels to 0.
+        * If it fails to allocate memory for array sched_domains_numa_masks[][],
+        * the array will contain less then 'level' members. This could be
+        * dangerous when we use it to iterate array sched_domains_numa_masks[][]
+        * in other functions.
+        *
+        * We reset it to 'level' at the end of this function.
+        */
+       sched_domains_numa_levels = 0;
+
        sched_domains_numa_masks = kzalloc(sizeof(void *) * level, GFP_KERNEL);
        if (!sched_domains_numa_masks)
                return;
@@ -6176,11 +6187,68 @@ static void sched_init_numa(void)
        }
 
        sched_domain_topology = tl;
+
+       sched_domains_numa_levels = level;
+}
+
+static void sched_domains_numa_masks_set(int cpu)
+{
+       int i, j;
+       int node = cpu_to_node(cpu);
+
+       for (i = 0; i < sched_domains_numa_levels; i++) {
+               for (j = 0; j < nr_node_ids; j++) {
+                       if (node_distance(j, node) <= sched_domains_numa_distance[i])
+                               cpumask_set_cpu(cpu, sched_domains_numa_masks[i][j]);
+               }
+       }
+}
+
+static void sched_domains_numa_masks_clear(int cpu)
+{
+       int i, j;
+       for (i = 0; i < sched_domains_numa_levels; i++) {
+               for (j = 0; j < nr_node_ids; j++)
+                       cpumask_clear_cpu(cpu, sched_domains_numa_masks[i][j]);
+       }
+}
+
+/*
+ * Update sched_domains_numa_masks[level][node] array when new cpus
+ * are onlined.
+ */
+static int sched_domains_numa_masks_update(struct notifier_block *nfb,
+                                          unsigned long action,
+                                          void *hcpu)
+{
+       int cpu = (long)hcpu;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_ONLINE:
+               sched_domains_numa_masks_set(cpu);
+               break;
+
+       case CPU_DEAD:
+               sched_domains_numa_masks_clear(cpu);
+               break;
+
+       default:
+               return NOTIFY_DONE;
+       }
+
+       return NOTIFY_OK;
 }
 #else
 static inline void sched_init_numa(void)
 {
 }
+
+static int sched_domains_numa_masks_update(struct notifier_block *nfb,
+                                          unsigned long action,
+                                          void *hcpu)
+{
+       return 0;
+}
 #endif /* CONFIG_NUMA */
 
 static int __sdt_alloc(const struct cpumask *cpu_map)
@@ -6629,6 +6697,7 @@ void __init sched_init_smp(void)
        mutex_unlock(&sched_domains_mutex);
        put_online_cpus();
 
+       hotcpu_notifier(sched_domains_numa_masks_update, CPU_PRI_SCHED_ACTIVE);
        hotcpu_notifier(cpuset_cpu_active, CPU_PRI_CPUSET_ACTIVE);
        hotcpu_notifier(cpuset_cpu_inactive, CPU_PRI_CPUSET_INACTIVE);
 
index ba744cf80696203b65406c7aef8faae3a23048d0..d226c6a3fd28933d02edd485a9c8353db2212c02 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/export.h>
 #include <linux/timex.h>
 #include <linux/capability.h>
-#include <linux/clocksource.h>
+#include <linux/timekeeper_internal.h>
 #include <linux/errno.h>
 #include <linux/syscalls.h>
 #include <linux/security.h>
index fd42bd452b7528642495e6b619715ccb424b5e2e..8601f0db12612a1e18a3a11968b9444630f94ad5 100644 (file)
@@ -16,6 +16,10 @@ config ARCH_CLOCKSOURCE_DATA
 config GENERIC_TIME_VSYSCALL
        bool
 
+# Timekeeping vsyscall support
+config GENERIC_TIME_VSYSCALL_OLD
+       bool
+
 # ktime_t scalar 64bit nsec representation
 config KTIME_SCALAR
        bool
index aa27d391bfc8b408ced23985bc4946067b5eba87..f11d83b1294992db1e13c5f9266fb14f1bbde573 100644 (file)
@@ -37,7 +37,6 @@
 static struct alarm_base {
        spinlock_t              lock;
        struct timerqueue_head  timerqueue;
-       struct hrtimer          timer;
        ktime_t                 (*gettime)(void);
        clockid_t               base_clockid;
 } alarm_bases[ALARM_NUMTYPE];
@@ -46,6 +45,8 @@ static struct alarm_base {
 static ktime_t freezer_delta;
 static DEFINE_SPINLOCK(freezer_delta_lock);
 
+static struct wakeup_source *ws;
+
 #ifdef CONFIG_RTC_CLASS
 /* rtc timer and device for setting alarm wakeups at suspend */
 static struct rtc_timer                rtctimer;
@@ -130,50 +131,35 @@ static inline void alarmtimer_rtc_timer_init(void) { }
  * @base: pointer to the base where the timer is being run
  * @alarm: pointer to alarm being enqueued.
  *
- * Adds alarm to a alarm_base timerqueue and if necessary sets
- * an hrtimer to run.
+ * Adds alarm to a alarm_base timerqueue
  *
  * Must hold base->lock when calling.
  */
 static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm)
 {
+       if (alarm->state & ALARMTIMER_STATE_ENQUEUED)
+               timerqueue_del(&base->timerqueue, &alarm->node);
+
        timerqueue_add(&base->timerqueue, &alarm->node);
        alarm->state |= ALARMTIMER_STATE_ENQUEUED;
-
-       if (&alarm->node == timerqueue_getnext(&base->timerqueue)) {
-               hrtimer_try_to_cancel(&base->timer);
-               hrtimer_start(&base->timer, alarm->node.expires,
-                               HRTIMER_MODE_ABS);
-       }
 }
 
 /**
- * alarmtimer_remove - Removes an alarm timer from an alarm_base timerqueue
+ * alarmtimer_dequeue - Removes an alarm timer from an alarm_base timerqueue
  * @base: pointer to the base where the timer is running
  * @alarm: pointer to alarm being removed
  *
- * Removes alarm to a alarm_base timerqueue and if necessary sets
- * a new timer to run.
+ * Removes alarm to a alarm_base timerqueue
  *
  * Must hold base->lock when calling.
  */
-static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm)
+static void alarmtimer_dequeue(struct alarm_base *base, struct alarm *alarm)
 {
-       struct timerqueue_node *next = timerqueue_getnext(&base->timerqueue);
-
        if (!(alarm->state & ALARMTIMER_STATE_ENQUEUED))
                return;
 
        timerqueue_del(&base->timerqueue, &alarm->node);
        alarm->state &= ~ALARMTIMER_STATE_ENQUEUED;
-
-       if (next == &alarm->node) {
-               hrtimer_try_to_cancel(&base->timer);
-               next = timerqueue_getnext(&base->timerqueue);
-               if (!next)
-                       return;
-               hrtimer_start(&base->timer, next->expires, HRTIMER_MODE_ABS);
-       }
 }
 
 
@@ -188,42 +174,23 @@ static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm)
  */
 static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
 {
-       struct alarm_base *base = container_of(timer, struct alarm_base, timer);
-       struct timerqueue_node *next;
+       struct alarm *alarm = container_of(timer, struct alarm, timer);
+       struct alarm_base *base = &alarm_bases[alarm->type];
        unsigned long flags;
-       ktime_t now;
        int ret = HRTIMER_NORESTART;
        int restart = ALARMTIMER_NORESTART;
 
        spin_lock_irqsave(&base->lock, flags);
-       now = base->gettime();
-       while ((next = timerqueue_getnext(&base->timerqueue))) {
-               struct alarm *alarm;
-               ktime_t expired = next->expires;
-
-               if (expired.tv64 > now.tv64)
-                       break;
-
-               alarm = container_of(next, struct alarm, node);
-
-               timerqueue_del(&base->timerqueue, &alarm->node);
-               alarm->state &= ~ALARMTIMER_STATE_ENQUEUED;
-
-               alarm->state |= ALARMTIMER_STATE_CALLBACK;
-               spin_unlock_irqrestore(&base->lock, flags);
-               if (alarm->function)
-                       restart = alarm->function(alarm, now);
-               spin_lock_irqsave(&base->lock, flags);
-               alarm->state &= ~ALARMTIMER_STATE_CALLBACK;
+       alarmtimer_dequeue(base, alarm);
+       spin_unlock_irqrestore(&base->lock, flags);
 
-               if (restart != ALARMTIMER_NORESTART) {
-                       timerqueue_add(&base->timerqueue, &alarm->node);
-                       alarm->state |= ALARMTIMER_STATE_ENQUEUED;
-               }
-       }
+       if (alarm->function)
+               restart = alarm->function(alarm, base->gettime());
 
-       if (next) {
-               hrtimer_set_expires(&base->timer, next->expires);
+       spin_lock_irqsave(&base->lock, flags);
+       if (restart != ALARMTIMER_NORESTART) {
+               hrtimer_set_expires(&alarm->timer, alarm->node.expires);
+               alarmtimer_enqueue(base, alarm);
                ret = HRTIMER_RESTART;
        }
        spin_unlock_irqrestore(&base->lock, flags);
@@ -250,6 +217,7 @@ static int alarmtimer_suspend(struct device *dev)
        unsigned long flags;
        struct rtc_device *rtc;
        int i;
+       int ret;
 
        spin_lock_irqsave(&freezer_delta_lock, flags);
        min = freezer_delta;
@@ -279,8 +247,10 @@ static int alarmtimer_suspend(struct device *dev)
        if (min.tv64 == 0)
                return 0;
 
-       /* XXX - Should we enforce a minimum sleep time? */
-       WARN_ON(min.tv64 < NSEC_PER_SEC);
+       if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) {
+               __pm_wakeup_event(ws, 2 * MSEC_PER_SEC);
+               return -EBUSY;
+       }
 
        /* Setup an rtc timer to fire that far in the future */
        rtc_timer_cancel(rtc, &rtctimer);
@@ -288,9 +258,11 @@ static int alarmtimer_suspend(struct device *dev)
        now = rtc_tm_to_ktime(tm);
        now = ktime_add(now, min);
 
-       rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0));
-
-       return 0;
+       /* Set alarm, if in the past reject suspend briefly to handle */
+       ret = rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0));
+       if (ret < 0)
+               __pm_wakeup_event(ws, MSEC_PER_SEC);
+       return ret;
 }
 #else
 static int alarmtimer_suspend(struct device *dev)
@@ -324,6 +296,9 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
                enum alarmtimer_restart (*function)(struct alarm *, ktime_t))
 {
        timerqueue_init(&alarm->node);
+       hrtimer_init(&alarm->timer, alarm_bases[type].base_clockid,
+                       HRTIMER_MODE_ABS);
+       alarm->timer.function = alarmtimer_fired;
        alarm->function = function;
        alarm->type = type;
        alarm->state = ALARMTIMER_STATE_INACTIVE;
@@ -334,17 +309,19 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
  * @alarm: ptr to alarm to set
  * @start: time to run the alarm
  */
-void alarm_start(struct alarm *alarm, ktime_t start)
+int alarm_start(struct alarm *alarm, ktime_t start)
 {
        struct alarm_base *base = &alarm_bases[alarm->type];
        unsigned long flags;
+       int ret;
 
        spin_lock_irqsave(&base->lock, flags);
-       if (alarmtimer_active(alarm))
-               alarmtimer_remove(base, alarm);
        alarm->node.expires = start;
        alarmtimer_enqueue(base, alarm);
+       ret = hrtimer_start(&alarm->timer, alarm->node.expires,
+                               HRTIMER_MODE_ABS);
        spin_unlock_irqrestore(&base->lock, flags);
+       return ret;
 }
 
 /**
@@ -358,18 +335,12 @@ int alarm_try_to_cancel(struct alarm *alarm)
 {
        struct alarm_base *base = &alarm_bases[alarm->type];
        unsigned long flags;
-       int ret = -1;
-       spin_lock_irqsave(&base->lock, flags);
-
-       if (alarmtimer_callback_running(alarm))
-               goto out;
+       int ret;
 
-       if (alarmtimer_is_queued(alarm)) {
-               alarmtimer_remove(base, alarm);
-               ret = 1;
-       } else
-               ret = 0;
-out:
+       spin_lock_irqsave(&base->lock, flags);
+       ret = hrtimer_try_to_cancel(&alarm->timer);
+       if (ret >= 0)
+               alarmtimer_dequeue(base, alarm);
        spin_unlock_irqrestore(&base->lock, flags);
        return ret;
 }
@@ -802,10 +773,6 @@ static int __init alarmtimer_init(void)
        for (i = 0; i < ALARM_NUMTYPE; i++) {
                timerqueue_init_head(&alarm_bases[i].timerqueue);
                spin_lock_init(&alarm_bases[i].lock);
-               hrtimer_init(&alarm_bases[i].timer,
-                               alarm_bases[i].base_clockid,
-                               HRTIMER_MODE_ABS);
-               alarm_bases[i].timer.function = alarmtimer_fired;
        }
 
        error = alarmtimer_rtc_interface_setup();
@@ -821,6 +788,7 @@ static int __init alarmtimer_init(void)
                error = PTR_ERR(pdev);
                goto out_drv;
        }
+       ws = wakeup_source_register("alarmtimer");
        return 0;
 
 out_drv:
index 46da0537c10b4d78e3c5645d8b709bb3503cc2af..6629bf7b52856849899c348156b65ce3cc732cd4 100644 (file)
@@ -37,7 +37,7 @@
  * requested HZ value. It is also not recommended
  * for "tick-less" systems.
  */
-#define NSEC_PER_JIFFY ((u32)((((u64)NSEC_PER_SEC)<<8)/SHIFTED_HZ))
+#define NSEC_PER_JIFFY ((NSEC_PER_SEC+HZ/2)/HZ)
 
 /* Since jiffies uses a simple NSEC_PER_JIFFY multiplier
  * conversion, the .shift value could be zero. However
@@ -95,3 +95,33 @@ struct clocksource * __init __weak clocksource_default_clock(void)
 {
        return &clocksource_jiffies;
 }
+
+struct clocksource refined_jiffies;
+
+int register_refined_jiffies(long cycles_per_second)
+{
+       u64 nsec_per_tick, shift_hz;
+       long cycles_per_tick;
+
+
+
+       refined_jiffies = clocksource_jiffies;
+       refined_jiffies.name = "refined-jiffies";
+       refined_jiffies.rating++;
+
+       /* Calc cycles per tick */
+       cycles_per_tick = (cycles_per_second + HZ/2)/HZ;
+       /* shift_hz stores hz<<8 for extra accuracy */
+       shift_hz = (u64)cycles_per_second << 8;
+       shift_hz += cycles_per_tick/2;
+       do_div(shift_hz, cycles_per_tick);
+       /* Calculate nsec_per_tick using shift_hz */
+       nsec_per_tick = (u64)NSEC_PER_SEC << 8;
+       nsec_per_tick += (u32)shift_hz/2;
+       do_div(nsec_per_tick, (u32)shift_hz);
+
+       refined_jiffies.mult = ((u32)nsec_per_tick) << JIFFIES_SHIFT;
+
+       clocksource_register(&refined_jiffies);
+       return 0;
+}
index f423bdd035c2234fb91910b60d096992405a28ba..a40260885265707603d72dee9df79f030e973221 100644 (file)
@@ -835,7 +835,7 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
                 */
                if (ts->tick_stopped) {
                        touch_softlockup_watchdog();
-                       if (idle_cpu(cpu))
+                       if (is_idle_task(current))
                                ts->idle_jiffies++;
                }
                update_process_times(user_mode(regs));
index 5ce06a3fa91e01af6a3cfc7fbbc828af2824fae8..e424970bb562657af3d37de69320ba0f07ed9b70 100644 (file)
@@ -8,6 +8,7 @@
  *
  */
 
+#include <linux/timekeeper_internal.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/tick.h>
 #include <linux/stop_machine.h>
 
-/* Structure holding internal timekeeping values. */
-struct timekeeper {
-       /* Current clocksource used for timekeeping. */
-       struct clocksource      *clock;
-       /* NTP adjusted clock multiplier */
-       u32                     mult;
-       /* The shift value of the current clocksource. */
-       u32                     shift;
-       /* Number of clock cycles in one NTP interval. */
-       cycle_t                 cycle_interval;
-       /* Number of clock shifted nano seconds in one NTP interval. */
-       u64                     xtime_interval;
-       /* shifted nano seconds left over when rounding cycle_interval */
-       s64                     xtime_remainder;
-       /* Raw nano seconds accumulated per NTP interval. */
-       u32                     raw_interval;
-
-       /* Current CLOCK_REALTIME time in seconds */
-       u64                     xtime_sec;
-       /* Clock shifted nano seconds */
-       u64                     xtime_nsec;
-
-       /* Difference between accumulated time and NTP time in ntp
-        * shifted nano seconds. */
-       s64                     ntp_error;
-       /* Shift conversion between clock shifted nano seconds and
-        * ntp shifted nano seconds. */
-       u32                     ntp_error_shift;
-
-       /*
-        * wall_to_monotonic is what we need to add to xtime (or xtime corrected
-        * for sub jiffie times) to get to monotonic time.  Monotonic is pegged
-        * at zero at system boot time, so wall_to_monotonic will be negative,
-        * however, we will ALWAYS keep the tv_nsec part positive so we can use
-        * the usual normalization.
-        *
-        * wall_to_monotonic is moved after resume from suspend for the
-        * monotonic time not to jump. We need to add total_sleep_time to
-        * wall_to_monotonic to get the real boot based time offset.
-        *
-        * - wall_to_monotonic is no longer the boot time, getboottime must be
-        * used instead.
-        */
-       struct timespec         wall_to_monotonic;
-       /* Offset clock monotonic -> clock realtime */
-       ktime_t                 offs_real;
-       /* time spent in suspend */
-       struct timespec         total_sleep_time;
-       /* Offset clock monotonic -> clock boottime */
-       ktime_t                 offs_boot;
-       /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */
-       struct timespec         raw_time;
-       /* Seqlock for all timekeeper values */
-       seqlock_t               lock;
-};
 
 static struct timekeeper timekeeper;
 
@@ -96,15 +42,6 @@ static inline void tk_normalize_xtime(struct timekeeper *tk)
        }
 }
 
-static struct timespec tk_xtime(struct timekeeper *tk)
-{
-       struct timespec ts;
-
-       ts.tv_sec = tk->xtime_sec;
-       ts.tv_nsec = (long)(tk->xtime_nsec >> tk->shift);
-       return ts;
-}
-
 static void tk_set_xtime(struct timekeeper *tk, const struct timespec *ts)
 {
        tk->xtime_sec = ts->tv_sec;
@@ -246,14 +183,11 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
 /* must hold write on timekeeper.lock */
 static void timekeeping_update(struct timekeeper *tk, bool clearntp)
 {
-       struct timespec xt;
-
        if (clearntp) {
                tk->ntp_error = 0;
                ntp_clear();
        }
-       xt = tk_xtime(tk);
-       update_vsyscall(&xt, &tk->wall_to_monotonic, tk->clock, tk->mult);
+       update_vsyscall(tk);
 }
 
 /**
@@ -1113,7 +1047,7 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
        accumulate_nsecs_to_secs(tk);
 
        /* Accumulate raw time */
-       raw_nsecs = tk->raw_interval << shift;
+       raw_nsecs = (u64)tk->raw_interval << shift;
        raw_nsecs += tk->raw_time.tv_nsec;
        if (raw_nsecs >= NSEC_PER_SEC) {
                u64 raw_secs = raw_nsecs;
@@ -1130,6 +1064,33 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
        return offset;
 }
 
+#ifdef CONFIG_GENERIC_TIME_VSYSCALL_OLD
+static inline void old_vsyscall_fixup(struct timekeeper *tk)
+{
+       s64 remainder;
+
+       /*
+       * Store only full nanoseconds into xtime_nsec after rounding
+       * it up and add the remainder to the error difference.
+       * XXX - This is necessary to avoid small 1ns inconsistnecies caused
+       * by truncating the remainder in vsyscalls. However, it causes
+       * additional work to be done in timekeeping_adjust(). Once
+       * the vsyscall implementations are converted to use xtime_nsec
+       * (shifted nanoseconds), and CONFIG_GENERIC_TIME_VSYSCALL_OLD
+       * users are removed, this can be killed.
+       */
+       remainder = tk->xtime_nsec & ((1ULL << tk->shift) - 1);
+       tk->xtime_nsec -= remainder;
+       tk->xtime_nsec += 1ULL << tk->shift;
+       tk->ntp_error += remainder << tk->ntp_error_shift;
+
+}
+#else
+#define old_vsyscall_fixup(tk)
+#endif
+
+
+
 /**
  * update_wall_time - Uses the current clocksource to increment the wall time
  *
@@ -1141,7 +1102,6 @@ static void update_wall_time(void)
        cycle_t offset;
        int shift = 0, maxshift;
        unsigned long flags;
-       s64 remainder;
 
        write_seqlock_irqsave(&tk->lock, flags);
 
@@ -1183,20 +1143,11 @@ static void update_wall_time(void)
        /* correct the clock when NTP error is too big */
        timekeeping_adjust(tk, offset);
 
-
        /*
-       * Store only full nanoseconds into xtime_nsec after rounding
-       * it up and add the remainder to the error difference.
-       * XXX - This is necessary to avoid small 1ns inconsistnecies caused
-       * by truncating the remainder in vsyscalls. However, it causes
-       * additional work to be done in timekeeping_adjust(). Once
-       * the vsyscall implementations are converted to use xtime_nsec
-       * (shifted nanoseconds), this can be killed.
-       */
-       remainder = tk->xtime_nsec & ((1ULL << tk->shift) - 1);
-       tk->xtime_nsec -= remainder;
-       tk->xtime_nsec += 1ULL << tk->shift;
-       tk->ntp_error += remainder << tk->ntp_error_shift;
+        * XXX This can be killed once everyone converts
+        * to the new update_vsyscall.
+        */
+       old_vsyscall_fixup(tk);
 
        /*
         * Finally, make sure that after the rounding
index d5de1b2292aad651da76bfbd2c5d037ff9852237..367d008584823a6fe01ed013cda8c3693fcfd761 100644 (file)
@@ -63,6 +63,7 @@ EXPORT_SYMBOL(jiffies_64);
 #define TVR_SIZE (1 << TVR_BITS)
 #define TVN_MASK (TVN_SIZE - 1)
 #define TVR_MASK (TVR_SIZE - 1)
+#define MAX_TVAL ((unsigned long)((1ULL << (TVR_BITS + 4*TVN_BITS)) - 1))
 
 struct tvec {
        struct list_head vec[TVN_SIZE];
@@ -359,11 +360,12 @@ __internal_add_timer(struct tvec_base *base, struct timer_list *timer)
                vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);
        } else {
                int i;
-               /* If the timeout is larger than 0xffffffff on 64-bit
-                * architectures then we use the maximum timeout:
+               /* If the timeout is larger than MAX_TVAL (on 64-bit
+                * architectures or with CONFIG_BASE_SMALL=1) then we
+                * use the maximum timeout.
                 */
-               if (idx > 0xffffffffUL) {
-                       idx = 0xffffffffUL;
+               if (idx > MAX_TVAL) {
+                       idx = MAX_TVAL;
                        expires = idx + base->timer_jiffies;
                }
                i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
index ae0de80c1c8878f34d27a7677d37cc7c64eca256..32f12150fc4f4a82aace1ff42afc17969f8692a3 100644 (file)
@@ -21,7 +21,7 @@ char *kvasprintf(gfp_t gfp, const char *fmt, va_list ap)
        len = vsnprintf(NULL, 0, fmt, aq);
        va_end(aq);
 
-       p = kmalloc(len+1, gfp);
+       p = kmalloc_track_caller(len+1, gfp);
        if (!p)
                return NULL;
 
index e76d85cf31755c6de5b9ca5898756254e0525845..3675452b23ca175b612489e362aa7274b75d96a5 100644 (file)
@@ -38,6 +38,25 @@ struct scatterlist *sg_next(struct scatterlist *sg)
 }
 EXPORT_SYMBOL(sg_next);
 
+/**
+ * sg_nents - return total count of entries in scatterlist
+ * @sg:                The scatterlist
+ *
+ * Description:
+ * Allows to know how many entries are in sg, taking into acount
+ * chaining as well
+ *
+ **/
+int sg_nents(struct scatterlist *sg)
+{
+       int nents;
+       for (nents = 0; sg; sg = sg_next(sg))
+               nents++;
+       return nents;
+}
+EXPORT_SYMBOL(sg_nents);
+
+
 /**
  * sg_last - return the last scatterlist entry in a list
  * @sgl:       First entry in the scatterlist
index b41823cc05e61caf4b862418fde58a5025bfb748..d3ca2b3ee17657f8045c4dca291721ac6c38c9be 100644 (file)
@@ -158,16 +158,16 @@ static ssize_t read_ahead_kb_store(struct device *dev,
                                  const char *buf, size_t count)
 {
        struct backing_dev_info *bdi = dev_get_drvdata(dev);
-       char *end;
        unsigned long read_ahead_kb;
-       ssize_t ret = -EINVAL;
+       ssize_t ret;
 
-       read_ahead_kb = simple_strtoul(buf, &end, 10);
-       if (*buf && (end[0] == '\0' || (end[0] == '\n' && end[1] == '\0'))) {
-               bdi->ra_pages = read_ahead_kb >> (PAGE_SHIFT - 10);
-               ret = count;
-       }
-       return ret;
+       ret = kstrtoul(buf, 10, &read_ahead_kb);
+       if (ret < 0)
+               return ret;
+
+       bdi->ra_pages = read_ahead_kb >> (PAGE_SHIFT - 10);
+
+       return count;
 }
 
 #define K(pages) ((pages) << (PAGE_SHIFT - 10))
@@ -187,16 +187,17 @@ static ssize_t min_ratio_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
        struct backing_dev_info *bdi = dev_get_drvdata(dev);
-       char *end;
        unsigned int ratio;
-       ssize_t ret = -EINVAL;
+       ssize_t ret;
+
+       ret = kstrtouint(buf, 10, &ratio);
+       if (ret < 0)
+               return ret;
+
+       ret = bdi_set_min_ratio(bdi, ratio);
+       if (!ret)
+               ret = count;
 
-       ratio = simple_strtoul(buf, &end, 10);
-       if (*buf && (end[0] == '\0' || (end[0] == '\n' && end[1] == '\0'))) {
-               ret = bdi_set_min_ratio(bdi, ratio);
-               if (!ret)
-                       ret = count;
-       }
        return ret;
 }
 BDI_SHOW(min_ratio, bdi->min_ratio)
@@ -205,16 +206,17 @@ static ssize_t max_ratio_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
        struct backing_dev_info *bdi = dev_get_drvdata(dev);
-       char *end;
        unsigned int ratio;
-       ssize_t ret = -EINVAL;
+       ssize_t ret;
+
+       ret = kstrtouint(buf, 10, &ratio);
+       if (ret < 0)
+               return ret;
+
+       ret = bdi_set_max_ratio(bdi, ratio);
+       if (!ret)
+               ret = count;
 
-       ratio = simple_strtoul(buf, &end, 10);
-       if (*buf && (end[0] == '\0' || (end[0] == '\n' && end[1] == '\0'))) {
-               ret = bdi_set_max_ratio(bdi, ratio);
-               if (!ret)
-                       ret = count;
-       }
        return ret;
 }
 BDI_SHOW(max_ratio, bdi->max_ratio)
index 5ad5ce23c1e082bc999222f42e542d942794c7c7..830893b2b3c776b07070d7257e771406b388dec8 100644 (file)
@@ -1602,10 +1602,18 @@ void writeback_set_ratelimit(void)
 }
 
 static int __cpuinit
-ratelimit_handler(struct notifier_block *self, unsigned long u, void *v)
+ratelimit_handler(struct notifier_block *self, unsigned long action,
+                 void *hcpu)
 {
-       writeback_set_ratelimit();
-       return NOTIFY_DONE;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_ONLINE:
+       case CPU_DEAD:
+               writeback_set_ratelimit();
+               return NOTIFY_OK;
+       default:
+               return NOTIFY_DONE;
+       }
 }
 
 static struct notifier_block __cpuinitdata ratelimit_nb = {
index cc12072f8787d5adacc6cd49a78849ca5c2005a6..67afba5117f2ebe80ef54e487d068fdf99e986bb 100644 (file)
@@ -2220,12 +2220,14 @@ static struct dentry *shmem_fh_to_dentry(struct super_block *sb,
 {
        struct inode *inode;
        struct dentry *dentry = NULL;
-       u64 inum = fid->raw[2];
-       inum = (inum << 32) | fid->raw[1];
+       u64 inum;
 
        if (fh_len < 3)
                return NULL;
 
+       inum = fid->raw[2];
+       inum = (inum << 32) | fid->raw[1];
+
        inode = ilookup5(sb, (unsigned long)(inum + fid->raw[0]),
                        shmem_match, fid->raw);
        if (inode) {
index 9c217255ac49374834689590f6e2bd9752e23da2..069a24e64403f19bd6f51c9d9a9ef4b56deef48d 100644 (file)
@@ -168,6 +168,7 @@ void kmem_cache_destroy(struct kmem_cache *s)
                list_del(&s->list);
 
                if (!__kmem_cache_shutdown(s)) {
+                       mutex_unlock(&slab_mutex);
                        if (s->flags & SLAB_DESTROY_BY_RCU)
                                rcu_barrier();
 
@@ -175,12 +176,14 @@ void kmem_cache_destroy(struct kmem_cache *s)
                        kmem_cache_free(kmem_cache, s);
                } else {
                        list_add(&s->list, &slab_caches);
+                       mutex_unlock(&slab_mutex);
                        printk(KERN_ERR "kmem_cache_destroy %s: Slab cache still has objects\n",
                                s->name);
                        dump_stack();
                }
+       } else {
+               mutex_unlock(&slab_mutex);
        }
-       mutex_unlock(&slab_mutex);
        put_online_cpus();
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
index 14e254c768fc5090e9c2276085b3c6f96c6255f6..71cd288b200179d4962222337f3947342fcebe57 100644 (file)
@@ -1483,7 +1483,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        struct file *swap_file, *victim;
        struct address_space *mapping;
        struct inode *inode;
-       char *pathname;
+       struct filename *pathname;
        int oom_score_adj;
        int i, type, prev;
        int err;
@@ -1498,8 +1498,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        if (IS_ERR(pathname))
                goto out;
 
-       victim = filp_open(pathname, O_RDWR|O_LARGEFILE, 0);
-       putname(pathname);
+       victim = file_open_name(pathname, O_RDWR|O_LARGEFILE, 0);
        err = PTR_ERR(victim);
        if (IS_ERR(victim))
                goto out;
@@ -1936,7 +1935,7 @@ static int setup_swap_map_and_extents(struct swap_info_struct *p,
 SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 {
        struct swap_info_struct *p;
-       char *name;
+       struct filename *name;
        struct file *swap_file = NULL;
        struct address_space *mapping;
        int i;
@@ -1967,7 +1966,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
                name = NULL;
                goto bad_swap;
        }
-       swap_file = filp_open(name, O_RDWR|O_LARGEFILE, 0);
+       swap_file = file_open_name(name, O_RDWR|O_LARGEFILE, 0);
        if (IS_ERR(swap_file)) {
                error = PTR_ERR(swap_file);
                swap_file = NULL;
@@ -2053,7 +2052,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 
        printk(KERN_INFO "Adding %uk swap on %s.  "
                        "Priority:%d extents:%d across:%lluk %s%s%s\n",
-               p->pages<<(PAGE_SHIFT-10), name, p->prio,
+               p->pages<<(PAGE_SHIFT-10), name->name, p->prio,
                nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10),
                (p->flags & SWP_SOLIDSTATE) ? "SS" : "",
                (p->flags & SWP_DISCARDABLE) ? "D" : "",
index add69d0fd99d2b34025c0d8fb42f703ca6ea38c0..fbbf1fa00940e2c843f1706ea1a6bcfff349c555 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/export.h>
 #include "vlan.h"
 
-bool vlan_do_receive(struct sk_buff **skbp, bool last_handler)
+bool vlan_do_receive(struct sk_buff **skbp)
 {
        struct sk_buff *skb = *skbp;
        u16 vlan_id = skb->vlan_tci & VLAN_VID_MASK;
@@ -13,14 +13,8 @@ bool vlan_do_receive(struct sk_buff **skbp, bool last_handler)
        struct vlan_pcpu_stats *rx_stats;
 
        vlan_dev = vlan_find_dev(skb->dev, vlan_id);
-       if (!vlan_dev) {
-               /* Only the last call to vlan_do_receive() should change
-                * pkt_type to PACKET_OTHERHOST
-                */
-               if (vlan_id && last_handler)
-                       skb->pkt_type = PACKET_OTHERHOST;
+       if (!vlan_dev)
                return false;
-       }
 
        skb = *skbp = skb_share_check(skb, GFP_ATOMIC);
        if (unlikely(!skb))
index 8260f132b32e0a9d706c38b0969d0879a3f6bf94..34d41767093500ba7cda60a2a1990ede456f35bd 100644 (file)
@@ -76,6 +76,20 @@ inline int p9_is_proto_dotu(struct p9_client *clnt)
 }
 EXPORT_SYMBOL(p9_is_proto_dotu);
 
+/*
+ * Some error codes are taken directly from the server replies,
+ * make sure they are valid.
+ */
+static int safe_errno(int err)
+{
+       if ((err > 0) || (err < -MAX_ERRNO)) {
+               p9_debug(P9_DEBUG_ERROR, "Invalid error code %d\n", err);
+               return -EPROTO;
+       }
+       return err;
+}
+
+
 /* Interpret mount option for protocol version */
 static int get_protocol_version(char *s)
 {
@@ -782,7 +796,7 @@ again:
                return req;
 reterr:
        p9_free_req(c, req);
-       return ERR_PTR(err);
+       return ERR_PTR(safe_errno(err));
 }
 
 /**
@@ -865,7 +879,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
                return req;
 reterr:
        p9_free_req(c, req);
-       return ERR_PTR(err);
+       return ERR_PTR(safe_errno(err));
 }
 
 static struct p9_fid *p9_fid_create(struct p9_client *clnt)
index 15656b8573f38b87e396998bb419f3415adb9d30..02efb25c295705141b3c477a2712864674ae42cc 100644 (file)
@@ -316,8 +316,7 @@ static void p9_read_work(struct work_struct *work)
                                                m->rsize - m->rpos);
        p9_debug(P9_DEBUG_TRANS, "mux %p got %d bytes\n", m, err);
        if (err == -EAGAIN) {
-               clear_bit(Rworksched, &m->wsched);
-               return;
+               goto end_clear;
        }
 
        if (err <= 0)
@@ -379,19 +378,20 @@ static void p9_read_work(struct work_struct *work)
                m->req = NULL;
        }
 
+end_clear:
+       clear_bit(Rworksched, &m->wsched);
+
        if (!list_empty(&m->req_list)) {
                if (test_and_clear_bit(Rpending, &m->wsched))
                        n = POLLIN;
                else
                        n = p9_fd_poll(m->client, NULL);
 
-               if (n & POLLIN) {
+               if ((n & POLLIN) && !test_and_set_bit(Rworksched, &m->wsched)) {
                        p9_debug(P9_DEBUG_TRANS, "sched read work %p\n", m);
                        schedule_work(&m->rq);
-               } else
-                       clear_bit(Rworksched, &m->wsched);
-       } else
-               clear_bit(Rworksched, &m->wsched);
+               }
+       }
 
        return;
 error:
@@ -453,12 +453,13 @@ static void p9_write_work(struct work_struct *work)
        }
 
        if (!m->wsize) {
+               spin_lock(&m->client->lock);
                if (list_empty(&m->unsent_req_list)) {
                        clear_bit(Wworksched, &m->wsched);
+                       spin_unlock(&m->client->lock);
                        return;
                }
 
-               spin_lock(&m->client->lock);
                req = list_entry(m->unsent_req_list.next, struct p9_req_t,
                               req_list);
                req->status = REQ_STATUS_SENT;
@@ -476,10 +477,9 @@ static void p9_write_work(struct work_struct *work)
        clear_bit(Wpending, &m->wsched);
        err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos);
        p9_debug(P9_DEBUG_TRANS, "mux %p sent %d bytes\n", m, err);
-       if (err == -EAGAIN) {
-               clear_bit(Wworksched, &m->wsched);
-               return;
-       }
+       if (err == -EAGAIN)
+               goto end_clear;
+
 
        if (err < 0)
                goto error;
@@ -492,19 +492,21 @@ static void p9_write_work(struct work_struct *work)
        if (m->wpos == m->wsize)
                m->wpos = m->wsize = 0;
 
-       if (m->wsize == 0 && !list_empty(&m->unsent_req_list)) {
+end_clear:
+       clear_bit(Wworksched, &m->wsched);
+
+       if (m->wsize || !list_empty(&m->unsent_req_list)) {
                if (test_and_clear_bit(Wpending, &m->wsched))
                        n = POLLOUT;
                else
                        n = p9_fd_poll(m->client, NULL);
 
-               if (n & POLLOUT) {
+               if ((n & POLLOUT) &&
+                  !test_and_set_bit(Wworksched, &m->wsched)) {
                        p9_debug(P9_DEBUG_TRANS, "sched write work %p\n", m);
                        schedule_work(&m->wq);
-               } else
-                       clear_bit(Wworksched, &m->wsched);
-       } else
-               clear_bit(Wworksched, &m->wsched);
+               }
+       }
 
        return;
 
index 68e8f364bbf8e01fbae9134eb98a24fa676d0e51..fe43bc7b063f5f49b31c237f3f418b56de15379d 100644 (file)
@@ -265,6 +265,9 @@ static int br_parse_ip_options(struct sk_buff *skb)
        struct net_device *dev = skb->dev;
        u32 len;
 
+       if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+               goto inhdr_error;
+
        iph = ip_hdr(skb);
        opt = &(IPCB(skb)->opt);
 
index 1e0a1847c3bbee7fd5aeb8654bf0d9da08ce5ca9..09cb3f6dc40c4a573a9597ca851b9a91a09a1c3d 100644 (file)
@@ -3300,18 +3300,18 @@ ncls:
                                && !skb_pfmemalloc_protocol(skb))
                goto drop;
 
-       rx_handler = rcu_dereference(skb->dev->rx_handler);
        if (vlan_tx_tag_present(skb)) {
                if (pt_prev) {
                        ret = deliver_skb(skb, pt_prev, orig_dev);
                        pt_prev = NULL;
                }
-               if (vlan_do_receive(&skb, !rx_handler))
+               if (vlan_do_receive(&skb))
                        goto another_round;
                else if (unlikely(!skb))
                        goto unlock;
        }
 
+       rx_handler = rcu_dereference(skb->dev->rx_handler);
        if (rx_handler) {
                if (pt_prev) {
                        ret = deliver_skb(skb, pt_prev, orig_dev);
@@ -3331,6 +3331,9 @@ ncls:
                }
        }
 
+       if (vlan_tx_nonzero_tag_present(skb))
+               skb->pkt_type = PACKET_OTHERHOST;
+
        /* deliver only exact match when indicated */
        null_or_dev = deliver_exact ? skb->dev : NULL;
 
@@ -3471,17 +3474,31 @@ out:
        return netif_receive_skb(skb);
 }
 
-inline void napi_gro_flush(struct napi_struct *napi)
+/* napi->gro_list contains packets ordered by age.
+ * youngest packets at the head of it.
+ * Complete skbs in reverse order to reduce latencies.
+ */
+void napi_gro_flush(struct napi_struct *napi, bool flush_old)
 {
-       struct sk_buff *skb, *next;
+       struct sk_buff *skb, *prev = NULL;
 
-       for (skb = napi->gro_list; skb; skb = next) {
-               next = skb->next;
+       /* scan list and build reverse chain */
+       for (skb = napi->gro_list; skb != NULL; skb = skb->next) {
+               skb->prev = prev;
+               prev = skb;
+       }
+
+       for (skb = prev; skb; skb = prev) {
                skb->next = NULL;
+
+               if (flush_old && NAPI_GRO_CB(skb)->age == jiffies)
+                       return;
+
+               prev = skb->prev;
                napi_gro_complete(skb);
+               napi->gro_count--;
        }
 
-       napi->gro_count = 0;
        napi->gro_list = NULL;
 }
 EXPORT_SYMBOL(napi_gro_flush);
@@ -3542,6 +3559,7 @@ enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 
        napi->gro_count++;
        NAPI_GRO_CB(skb)->count = 1;
+       NAPI_GRO_CB(skb)->age = jiffies;
        skb_shinfo(skb)->gso_size = skb_gro_len(skb);
        skb->next = napi->gro_list;
        napi->gro_list = skb;
@@ -3631,20 +3649,22 @@ gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
 }
 EXPORT_SYMBOL(napi_skb_finish);
 
-void skb_gro_reset_offset(struct sk_buff *skb)
+static void skb_gro_reset_offset(struct sk_buff *skb)
 {
+       const struct skb_shared_info *pinfo = skb_shinfo(skb);
+       const skb_frag_t *frag0 = &pinfo->frags[0];
+
        NAPI_GRO_CB(skb)->data_offset = 0;
        NAPI_GRO_CB(skb)->frag0 = NULL;
        NAPI_GRO_CB(skb)->frag0_len = 0;
 
        if (skb->mac_header == skb->tail &&
-           !PageHighMem(skb_frag_page(&skb_shinfo(skb)->frags[0]))) {
-               NAPI_GRO_CB(skb)->frag0 =
-                       skb_frag_address(&skb_shinfo(skb)->frags[0]);
-               NAPI_GRO_CB(skb)->frag0_len = skb_frag_size(&skb_shinfo(skb)->frags[0]);
+           pinfo->nr_frags &&
+           !PageHighMem(skb_frag_page(frag0))) {
+               NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0);
+               NAPI_GRO_CB(skb)->frag0_len = skb_frag_size(frag0);
        }
 }
-EXPORT_SYMBOL(skb_gro_reset_offset);
 
 gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
@@ -3876,7 +3896,7 @@ void napi_complete(struct napi_struct *n)
        if (unlikely(test_bit(NAPI_STATE_NPSVC, &n->state)))
                return;
 
-       napi_gro_flush(n);
+       napi_gro_flush(n, false);
        local_irq_save(flags);
        __napi_complete(n);
        local_irq_restore(flags);
@@ -3981,8 +4001,17 @@ static void net_rx_action(struct softirq_action *h)
                                local_irq_enable();
                                napi_complete(n);
                                local_irq_disable();
-                       } else
+                       } else {
+                               if (n->gro_list) {
+                                       /* flush too old packets
+                                        * If HZ < 1000, flush all packets.
+                                        */
+                                       local_irq_enable();
+                                       napi_gro_flush(n, HZ >= 1000);
+                                       local_irq_disable();
+                               }
                                list_move_tail(&n->poll_list, &sd->poll_list);
+                       }
                }
 
                netpoll_poll_unlock(have);
index baca771caae2df503a1b0f1bcc9a4fcb577777e8..22571488730a7d1bbc2f5f2ec545abf850dcdf4a 100644 (file)
@@ -1301,8 +1301,6 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
        if (!dst)
                goto discard;
 
-       __skb_pull(skb, skb_network_offset(skb));
-
        if (!neigh_event_send(neigh, skb)) {
                int err;
                struct net_device *dev = neigh->dev;
@@ -1312,6 +1310,7 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
                        neigh_hh_init(neigh, dst);
 
                do {
+                       __skb_pull(skb, skb_network_offset(skb));
                        seq = read_seqbegin(&neigh->ha_lock);
                        err = dev_hard_header(skb, dev, ntohs(skb->protocol),
                                              neigh->ha, NULL, skb->len);
@@ -1342,9 +1341,8 @@ int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
        unsigned int seq;
        int err;
 
-       __skb_pull(skb, skb_network_offset(skb));
-
        do {
+               __skb_pull(skb, skb_network_offset(skb));
                seq = read_seqbegin(&neigh->ha_lock);
                err = dev_hard_header(skb, dev, ntohs(skb->protocol),
                                      neigh->ha, NULL, skb->len);
index 148e73d2c4515d777d577733f32205c38d03932e..d1dc14c2aac4ee00fa6dab706131bbe41d3790f7 100644 (file)
@@ -248,8 +248,8 @@ struct pktgen_dev {
        int removal_mark;       /* non-zero => the device is marked for
                                 * removal by worker thread */
 
-       int min_pkt_size;       /* = ETH_ZLEN; */
-       int max_pkt_size;       /* = ETH_ZLEN; */
+       int min_pkt_size;
+       int max_pkt_size;
        int pkt_overhead;       /* overhead for MPLS, VLANs, IPSEC etc */
        int nfrags;
        struct page *page;
@@ -449,8 +449,6 @@ static void pktgen_stop_all_threads_ifs(void);
 static void pktgen_stop(struct pktgen_thread *t);
 static void pktgen_clear_counters(struct pktgen_dev *pkt_dev);
 
-static unsigned int scan_ip6(const char *s, char ip[16]);
-
 /* Module parameters, defaults. */
 static int pg_count_d __read_mostly = 1000;
 static int pg_delay_d __read_mostly;
@@ -702,8 +700,8 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
                                &pkt_dev->cur_in6_saddr,
                                &pkt_dev->cur_in6_daddr);
        } else
-               seq_printf(seq, "     cur_saddr: 0x%x  cur_daddr: 0x%x\n",
-                          pkt_dev->cur_saddr, pkt_dev->cur_daddr);
+               seq_printf(seq, "     cur_saddr: %pI4  cur_daddr: %pI4\n",
+                          &pkt_dev->cur_saddr, &pkt_dev->cur_daddr);
 
        seq_printf(seq, "     cur_udp_dst: %d  cur_udp_src: %d\n",
                   pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src);
@@ -1299,7 +1297,7 @@ static ssize_t pktgen_if_write(struct file *file,
                        return -EFAULT;
                buf[len] = 0;
 
-               scan_ip6(buf, pkt_dev->in6_daddr.s6_addr);
+               in6_pton(buf, -1, pkt_dev->in6_daddr.s6_addr, -1, NULL);
                snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_daddr);
 
                pkt_dev->cur_in6_daddr = pkt_dev->in6_daddr;
@@ -1322,7 +1320,7 @@ static ssize_t pktgen_if_write(struct file *file,
                        return -EFAULT;
                buf[len] = 0;
 
-               scan_ip6(buf, pkt_dev->min_in6_daddr.s6_addr);
+               in6_pton(buf, -1, pkt_dev->min_in6_daddr.s6_addr, -1, NULL);
                snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->min_in6_daddr);
 
                pkt_dev->cur_in6_daddr = pkt_dev->min_in6_daddr;
@@ -1344,7 +1342,7 @@ static ssize_t pktgen_if_write(struct file *file,
                        return -EFAULT;
                buf[len] = 0;
 
-               scan_ip6(buf, pkt_dev->max_in6_daddr.s6_addr);
+               in6_pton(buf, -1, pkt_dev->max_in6_daddr.s6_addr, -1, NULL);
                snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->max_in6_daddr);
 
                if (debug)
@@ -1365,7 +1363,7 @@ static ssize_t pktgen_if_write(struct file *file,
                        return -EFAULT;
                buf[len] = 0;
 
-               scan_ip6(buf, pkt_dev->in6_saddr.s6_addr);
+               in6_pton(buf, -1, pkt_dev->in6_saddr.s6_addr, -1, NULL);
                snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_saddr);
 
                pkt_dev->cur_in6_saddr = pkt_dev->in6_saddr;
@@ -2036,19 +2034,17 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
        /* Set up Dest MAC */
        memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN);
 
-       /* Set up pkt size */
-       pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size;
-
        if (pkt_dev->flags & F_IPV6) {
-               /*
-                * Skip this automatic address setting until locks or functions
-                * gets exported
-                */
-
-#ifdef NOTNOW
                int i, set = 0, err = 1;
                struct inet6_dev *idev;
 
+               if (pkt_dev->min_pkt_size == 0) {
+                       pkt_dev->min_pkt_size = 14 + sizeof(struct ipv6hdr)
+                                               + sizeof(struct udphdr)
+                                               + sizeof(struct pktgen_hdr)
+                                               + pkt_dev->pkt_overhead;
+               }
+
                for (i = 0; i < IN6_ADDR_HSIZE; i++)
                        if (pkt_dev->cur_in6_saddr.s6_addr[i]) {
                                set = 1;
@@ -2069,9 +2065,8 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
                                struct inet6_ifaddr *ifp;
 
                                read_lock_bh(&idev->lock);
-                               for (ifp = idev->addr_list; ifp;
-                                    ifp = ifp->if_next) {
-                                       if (ifp->scope == IFA_LINK &&
+                               list_for_each_entry(ifp, &idev->addr_list, if_list) {
+                                       if ((ifp->scope & IFA_LINK) &&
                                            !(ifp->flags & IFA_F_TENTATIVE)) {
                                                pkt_dev->cur_in6_saddr = ifp->addr;
                                                err = 0;
@@ -2084,8 +2079,14 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
                        if (err)
                                pr_err("ERROR: IPv6 link address not available\n");
                }
-#endif
        } else {
+               if (pkt_dev->min_pkt_size == 0) {
+                       pkt_dev->min_pkt_size = 14 + sizeof(struct iphdr)
+                                               + sizeof(struct udphdr)
+                                               + sizeof(struct pktgen_hdr)
+                                               + pkt_dev->pkt_overhead;
+               }
+
                pkt_dev->saddr_min = 0;
                pkt_dev->saddr_max = 0;
                if (strlen(pkt_dev->src_min) == 0) {
@@ -2111,6 +2112,10 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
                pkt_dev->daddr_max = in_aton(pkt_dev->dst_max);
        }
        /* Initialize current values. */
+       pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size;
+       if (pkt_dev->min_pkt_size > pkt_dev->max_pkt_size)
+               pkt_dev->max_pkt_size = pkt_dev->min_pkt_size;
+
        pkt_dev->cur_dst_mac_offset = 0;
        pkt_dev->cur_src_mac_offset = 0;
        pkt_dev->cur_saddr = pkt_dev->saddr_min;
@@ -2758,97 +2763,6 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
        return skb;
 }
 
-/*
- * scan_ip6, fmt_ip taken from dietlibc-0.21
- * Author Felix von Leitner <felix-dietlibc@fefe.de>
- *
- * Slightly modified for kernel.
- * Should be candidate for net/ipv4/utils.c
- * --ro
- */
-
-static unsigned int scan_ip6(const char *s, char ip[16])
-{
-       unsigned int i;
-       unsigned int len = 0;
-       unsigned long u;
-       char suffix[16];
-       unsigned int prefixlen = 0;
-       unsigned int suffixlen = 0;
-       __be32 tmp;
-       char *pos;
-
-       for (i = 0; i < 16; i++)
-               ip[i] = 0;
-
-       for (;;) {
-               if (*s == ':') {
-                       len++;
-                       if (s[1] == ':') {      /* Found "::", skip to part 2 */
-                               s += 2;
-                               len++;
-                               break;
-                       }
-                       s++;
-               }
-
-               u = simple_strtoul(s, &pos, 16);
-               i = pos - s;
-               if (!i)
-                       return 0;
-               if (prefixlen == 12 && s[i] == '.') {
-
-                       /* the last 4 bytes may be written as IPv4 address */
-
-                       tmp = in_aton(s);
-                       memcpy((struct in_addr *)(ip + 12), &tmp, sizeof(tmp));
-                       return i + len;
-               }
-               ip[prefixlen++] = (u >> 8);
-               ip[prefixlen++] = (u & 255);
-               s += i;
-               len += i;
-               if (prefixlen == 16)
-                       return len;
-       }
-
-/* part 2, after "::" */
-       for (;;) {
-               if (*s == ':') {
-                       if (suffixlen == 0)
-                               break;
-                       s++;
-                       len++;
-               } else if (suffixlen != 0)
-                       break;
-
-               u = simple_strtol(s, &pos, 16);
-               i = pos - s;
-               if (!i) {
-                       if (*s)
-                               len--;
-                       break;
-               }
-               if (suffixlen + prefixlen <= 12 && s[i] == '.') {
-                       tmp = in_aton(s);
-                       memcpy((struct in_addr *)(suffix + suffixlen), &tmp,
-                              sizeof(tmp));
-                       suffixlen += 4;
-                       len += strlen(s);
-                       break;
-               }
-               suffix[suffixlen++] = (u >> 8);
-               suffix[suffixlen++] = (u & 255);
-               s += i;
-               len += i;
-               if (prefixlen + suffixlen == 16)
-                       break;
-       }
-       for (i = 0; i < suffixlen; i++)
-               ip[16 - suffixlen + i] = suffix[i];
-       return len;
-}
-
 static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
                                        struct pktgen_dev *pkt_dev)
 {
@@ -2927,7 +2841,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
                  sizeof(struct ipv6hdr) - sizeof(struct udphdr) -
                  pkt_dev->pkt_overhead;
 
-       if (datalen < sizeof(struct pktgen_hdr)) {
+       if (datalen < 0 || datalen < sizeof(struct pktgen_hdr)) {
                datalen = sizeof(struct pktgen_hdr);
                net_info_ratelimited("increased datalen to %d\n", datalen);
        }
@@ -3548,8 +3462,6 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
        }
 
        pkt_dev->removal_mark = 0;
-       pkt_dev->min_pkt_size = ETH_ZLEN;
-       pkt_dev->max_pkt_size = ETH_ZLEN;
        pkt_dev->nfrags = 0;
        pkt_dev->delay = pg_delay_d;
        pkt_dev->count = pg_count_d;
index cdc28598f4efadb83b79a006a71ea676b508a655..6e04b1fa11f2d4c6d0e0aacb27441688c5fe1438 100644 (file)
@@ -655,53 +655,6 @@ void consume_skb(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(consume_skb);
 
-/**
- *     skb_recycle - clean up an skb for reuse
- *     @skb: buffer
- *
- *     Recycles the skb to be reused as a receive buffer. This
- *     function does any necessary reference count dropping, and
- *     cleans up the skbuff as if it just came from __alloc_skb().
- */
-void skb_recycle(struct sk_buff *skb)
-{
-       struct skb_shared_info *shinfo;
-
-       skb_release_head_state(skb);
-
-       shinfo = skb_shinfo(skb);
-       memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
-       atomic_set(&shinfo->dataref, 1);
-
-       memset(skb, 0, offsetof(struct sk_buff, tail));
-       skb->data = skb->head + NET_SKB_PAD;
-       skb_reset_tail_pointer(skb);
-}
-EXPORT_SYMBOL(skb_recycle);
-
-/**
- *     skb_recycle_check - check if skb can be reused for receive
- *     @skb: buffer
- *     @skb_size: minimum receive buffer size
- *
- *     Checks that the skb passed in is not shared or cloned, and
- *     that it is linear and its head portion at least as large as
- *     skb_size so that it can be recycled as a receive buffer.
- *     If these conditions are met, this function does any necessary
- *     reference count dropping and cleans up the skbuff as if it
- *     just came from __alloc_skb().
- */
-bool skb_recycle_check(struct sk_buff *skb, int skb_size)
-{
-       if (!skb_is_recycleable(skb, skb_size))
-               return false;
-
-       skb_recycle(skb);
-
-       return true;
-}
-EXPORT_SYMBOL(skb_recycle_check);
-
 static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
 {
        new->tstamp             = old->tstamp;
index f5613d569c23a17a806d8579d08a3b103735a84a..e3487e46193912fec01410593fcbcb49266ce374 100644 (file)
@@ -107,6 +107,18 @@ static inline int xdigit2bin(char c, int delim)
        return IN6PTON_UNKNOWN;
 }
 
+/**
+ * in4_pton - convert an IPv4 address from literal to binary representation
+ * @src: the start of the IPv4 address string
+ * @srclen: the length of the string, -1 means strlen(src)
+ * @dst: the binary (u8[4] array) representation of the IPv4 address
+ * @delim: the delimiter of the IPv4 address in @src, -1 means no delimiter
+ * @end: A pointer to the end of the parsed string will be placed here
+ *
+ * Return one on success, return zero when any error occurs
+ * and @end will point to the end of the parsed string.
+ *
+ */
 int in4_pton(const char *src, int srclen,
             u8 *dst,
             int delim, const char **end)
@@ -161,6 +173,18 @@ out:
 }
 EXPORT_SYMBOL(in4_pton);
 
+/**
+ * in6_pton - convert an IPv6 address from literal to binary representation
+ * @src: the start of the IPv6 address string
+ * @srclen: the length of the string, -1 means strlen(src)
+ * @dst: the binary (u8[16] array) representation of the IPv6 address
+ * @delim: the delimiter of the IPv6 address in @src, -1 means no delimiter
+ * @end: A pointer to the end of the parsed string will be placed here
+ *
+ * Return one on success, return zero when any error occurs
+ * and @end will point to the end of the parsed string.
+ *
+ */
 int in6_pton(const char *src, int srclen,
             u8 *dst,
             int delim, const char **end)
index 68c93d1bb03adb9fef46ff264a783dad82a962ea..825c608826de1c4b5dea08c46e6ff4255117c990 100644 (file)
@@ -322,7 +322,8 @@ int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 {
        int r = secpath_exists(skb) ? 0 : IN_DEV_RPFILTER(idev);
 
-       if (!r && !fib_num_tclassid_users(dev_net(dev))) {
+       if (!r && !fib_num_tclassid_users(dev_net(dev)) &&
+           (dev->ifindex != oif || !IN_DEV_TX_REDIRECTS(idev))) {
                *itag = 0;
                return 0;
        }
index 267753060ffc5c7efe6a3e183113d8dc3fbb49e6..71b125cd5db18a3af37d124d4eb3495f3e03fdea 100644 (file)
@@ -840,6 +840,8 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
        change_nexthops(fi) {
                nexthop_nh->nh_parent = fi;
                nexthop_nh->nh_pcpu_rth_output = alloc_percpu(struct rtable __rcu *);
+               if (!nexthop_nh->nh_pcpu_rth_output)
+                       goto failure;
        } endfor_nexthops(fi)
 
        if (cfg->fc_mx) {
index f0c5b9c1a95714e2e206cf6cd178a90626271fcc..d34ce2972c8f90bca6809342aab5451c9138241e 100644 (file)
@@ -406,7 +406,7 @@ struct dst_entry *inet_csk_route_req(struct sock *sk,
        rt = ip_route_output_flow(net, fl4, sk);
        if (IS_ERR(rt))
                goto no_route;
-       if (opt && opt->opt.is_strictroute && rt->rt_gateway)
+       if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway)
                goto route_err;
        return &rt->dst;
 
@@ -442,7 +442,7 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk,
        rt = ip_route_output_flow(net, fl4, sk);
        if (IS_ERR(rt))
                goto no_route;
-       if (opt && opt->opt.is_strictroute && rt->rt_gateway)
+       if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway)
                goto route_err;
        rcu_read_unlock();
        return &rt->dst;
index ab09b126423ce3e56fd1fee2f6bda54e4b851022..694de3b7aebfede6073433201e1200cf72008997 100644 (file)
@@ -85,7 +85,7 @@ int ip_forward(struct sk_buff *skb)
 
        rt = skb_rtable(skb);
 
-       if (opt->is_strictroute && opt->nexthop != rt->rt_gateway)
+       if (opt->is_strictroute && rt->rt_uses_gateway)
                goto sr_failed;
 
        if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) &&
index 24a29a39e9a885dfa96300067fd37154b0875f53..6537a408a4fb451d906b574def4746c064399fd9 100644 (file)
@@ -193,7 +193,7 @@ static inline int ip_finish_output2(struct sk_buff *skb)
        }
 
        rcu_read_lock_bh();
-       nexthop = rt->rt_gateway ? rt->rt_gateway : ip_hdr(skb)->daddr;
+       nexthop = (__force u32) rt_nexthop(rt, ip_hdr(skb)->daddr);
        neigh = __ipv4_neigh_lookup_noref(dev, nexthop);
        if (unlikely(!neigh))
                neigh = __neigh_create(&arp_tbl, &nexthop, dev, false);
@@ -371,7 +371,7 @@ int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl)
        skb_dst_set_noref(skb, &rt->dst);
 
 packet_routed:
-       if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_gateway)
+       if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_uses_gateway)
                goto no_route;
 
        /* OK, we know where to send it, allocate and build IP header. */
index 978bca4818aef0c52dda4011c2a98b7ef0326559..1831092f999fb32880f2d5e721c242236b000228 100644 (file)
@@ -374,7 +374,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 
        memset(&fl4, 0, sizeof(fl4));
        flowi4_init_output(&fl4, tunnel->parms.link,
-                          htonl(tunnel->parms.i_key), RT_TOS(tos),
+                          be32_to_cpu(tunnel->parms.i_key), RT_TOS(tos),
                           RT_SCOPE_UNIVERSE,
                           IPPROTO_IPIP, 0,
                           dst, tiph->saddr, 0, 0);
@@ -441,7 +441,7 @@ static int vti_tunnel_bind_dev(struct net_device *dev)
                struct flowi4 fl4;
                memset(&fl4, 0, sizeof(fl4));
                flowi4_init_output(&fl4, tunnel->parms.link,
-                                  htonl(tunnel->parms.i_key),
+                                  be32_to_cpu(tunnel->parms.i_key),
                                   RT_TOS(iph->tos), RT_SCOPE_UNIVERSE,
                                   IPPROTO_IPIP, 0,
                                   iph->daddr, iph->saddr, 0, 0);
index ff622069fcefbe5ac2248440c2059b5a16d524e0..432f4bb77238fcc5c80d5ab7c6ad35bb55609c53 100644 (file)
@@ -802,7 +802,8 @@ void ip_rt_send_redirect(struct sk_buff *skb)
        net = dev_net(rt->dst.dev);
        peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, 1);
        if (!peer) {
-               icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
+               icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST,
+                         rt_nexthop(rt, ip_hdr(skb)->daddr));
                return;
        }
 
@@ -827,7 +828,9 @@ void ip_rt_send_redirect(struct sk_buff *skb)
            time_after(jiffies,
                       (peer->rate_last +
                        (ip_rt_redirect_load << peer->rate_tokens)))) {
-               icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
+               __be32 gw = rt_nexthop(rt, ip_hdr(skb)->daddr);
+
+               icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, gw);
                peer->rate_last = jiffies;
                ++peer->rate_tokens;
 #ifdef CONFIG_IP_ROUTE_VERBOSE
@@ -835,7 +838,7 @@ void ip_rt_send_redirect(struct sk_buff *skb)
                    peer->rate_tokens == ip_rt_redirect_number)
                        net_warn_ratelimited("host %pI4/if%d ignores redirects for %pI4 to %pI4\n",
                                             &ip_hdr(skb)->saddr, inet_iif(skb),
-                                            &ip_hdr(skb)->daddr, &rt->rt_gateway);
+                                            &ip_hdr(skb)->daddr, &gw);
 #endif
        }
 out_put_peer:
@@ -904,22 +907,32 @@ out:      kfree_skb(skb);
        return 0;
 }
 
-static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
+static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
 {
+       struct dst_entry *dst = &rt->dst;
        struct fib_result res;
 
+       if (dst->dev->mtu < mtu)
+               return;
+
        if (mtu < ip_rt_min_pmtu)
                mtu = ip_rt_min_pmtu;
 
+       if (!rt->rt_pmtu) {
+               dst->obsolete = DST_OBSOLETE_KILL;
+       } else {
+               rt->rt_pmtu = mtu;
+               dst->expires = max(1UL, jiffies + ip_rt_mtu_expires);
+       }
+
        rcu_read_lock();
-       if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) {
+       if (fib_lookup(dev_net(dst->dev), fl4, &res) == 0) {
                struct fib_nh *nh = &FIB_RES_NH(res);
 
                update_or_create_fnhe(nh, fl4->daddr, 0, mtu,
                                      jiffies + ip_rt_mtu_expires);
        }
        rcu_read_unlock();
-       return mtu;
 }
 
 static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
@@ -929,14 +942,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
        struct flowi4 fl4;
 
        ip_rt_build_flow_key(&fl4, sk, skb);
-       mtu = __ip_rt_update_pmtu(rt, &fl4, mtu);
-
-       if (!rt->rt_pmtu) {
-               dst->obsolete = DST_OBSOLETE_KILL;
-       } else {
-               rt->rt_pmtu = mtu;
-               rt->dst.expires = max(1UL, jiffies + ip_rt_mtu_expires);
-       }
+       __ip_rt_update_pmtu(rt, &fl4, mtu);
 }
 
 void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
@@ -1120,7 +1126,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
        mtu = dst->dev->mtu;
 
        if (unlikely(dst_metric_locked(dst, RTAX_MTU))) {
-               if (rt->rt_gateway && mtu > 576)
+               if (rt->rt_uses_gateway && mtu > 576)
                        mtu = 576;
        }
 
@@ -1171,7 +1177,9 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
                if (fnhe->fnhe_gw) {
                        rt->rt_flags |= RTCF_REDIRECTED;
                        rt->rt_gateway = fnhe->fnhe_gw;
-               }
+                       rt->rt_uses_gateway = 1;
+               } else if (!rt->rt_gateway)
+                       rt->rt_gateway = daddr;
 
                orig = rcu_dereference(fnhe->fnhe_rth);
                rcu_assign_pointer(fnhe->fnhe_rth, rt);
@@ -1180,13 +1188,6 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
 
                fnhe->fnhe_stamp = jiffies;
                ret = true;
-       } else {
-               /* Routes we intend to cache in nexthop exception have
-                * the DST_NOCACHE bit clear.  However, if we are
-                * unsuccessful at storing this route into the cache
-                * we really need to set it.
-                */
-               rt->dst.flags |= DST_NOCACHE;
        }
        spin_unlock_bh(&fnhe_lock);
 
@@ -1201,8 +1202,6 @@ static bool rt_cache_route(struct fib_nh *nh, struct rtable *rt)
        if (rt_is_input_route(rt)) {
                p = (struct rtable **)&nh->nh_rth_input;
        } else {
-               if (!nh->nh_pcpu_rth_output)
-                       goto nocache;
                p = (struct rtable **)__this_cpu_ptr(nh->nh_pcpu_rth_output);
        }
        orig = *p;
@@ -1211,16 +1210,8 @@ static bool rt_cache_route(struct fib_nh *nh, struct rtable *rt)
        if (prev == orig) {
                if (orig)
                        rt_free(orig);
-       } else {
-               /* Routes we intend to cache in the FIB nexthop have
-                * the DST_NOCACHE bit clear.  However, if we are
-                * unsuccessful at storing this route into the cache
-                * we really need to set it.
-                */
-nocache:
-               rt->dst.flags |= DST_NOCACHE;
+       } else
                ret = false;
-       }
 
        return ret;
 }
@@ -1281,8 +1272,10 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr,
        if (fi) {
                struct fib_nh *nh = &FIB_RES_NH(*res);
 
-               if (nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK)
+               if (nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK) {
                        rt->rt_gateway = nh->nh_gw;
+                       rt->rt_uses_gateway = 1;
+               }
                dst_init_metrics(&rt->dst, fi->fib_metrics, true);
 #ifdef CONFIG_IP_ROUTE_CLASSID
                rt->dst.tclassid = nh->nh_tclassid;
@@ -1291,8 +1284,18 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr,
                        cached = rt_bind_exception(rt, fnhe, daddr);
                else if (!(rt->dst.flags & DST_NOCACHE))
                        cached = rt_cache_route(nh, rt);
-       }
-       if (unlikely(!cached))
+               if (unlikely(!cached)) {
+                       /* Routes we intend to cache in nexthop exception or
+                        * FIB nexthop have the DST_NOCACHE bit clear.
+                        * However, if we are unsuccessful at storing this
+                        * route into the cache we really need to set it.
+                        */
+                       rt->dst.flags |= DST_NOCACHE;
+                       if (!rt->rt_gateway)
+                               rt->rt_gateway = daddr;
+                       rt_add_uncached_list(rt);
+               }
+       } else
                rt_add_uncached_list(rt);
 
 #ifdef CONFIG_IP_ROUTE_CLASSID
@@ -1360,6 +1363,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        rth->rt_iif     = 0;
        rth->rt_pmtu    = 0;
        rth->rt_gateway = 0;
+       rth->rt_uses_gateway = 0;
        INIT_LIST_HEAD(&rth->rt_uncached);
        if (our) {
                rth->dst.input= ip_local_deliver;
@@ -1429,7 +1433,6 @@ static int __mkroute_input(struct sk_buff *skb,
                return -EINVAL;
        }
 
-
        err = fib_validate_source(skb, saddr, daddr, tos, FIB_RES_OIF(*res),
                                  in_dev->dev, in_dev, &itag);
        if (err < 0) {
@@ -1439,10 +1442,13 @@ static int __mkroute_input(struct sk_buff *skb,
                goto cleanup;
        }
 
-       if (out_dev == in_dev && err &&
+       do_cache = res->fi && !itag;
+       if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) &&
            (IN_DEV_SHARED_MEDIA(out_dev) ||
-            inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res))))
+            inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) {
                flags |= RTCF_DOREDIRECT;
+               do_cache = false;
+       }
 
        if (skb->protocol != htons(ETH_P_IP)) {
                /* Not IP (i.e. ARP). Do not create route, if it is
@@ -1459,15 +1465,11 @@ static int __mkroute_input(struct sk_buff *skb,
                }
        }
 
-       do_cache = false;
-       if (res->fi) {
-               if (!itag) {
-                       rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
-                       if (rt_cache_valid(rth)) {
-                               skb_dst_set_noref(skb, &rth->dst);
-                               goto out;
-                       }
-                       do_cache = true;
+       if (do_cache) {
+               rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
+               if (rt_cache_valid(rth)) {
+                       skb_dst_set_noref(skb, &rth->dst);
+                       goto out;
                }
        }
 
@@ -1486,6 +1488,7 @@ static int __mkroute_input(struct sk_buff *skb,
        rth->rt_iif     = 0;
        rth->rt_pmtu    = 0;
        rth->rt_gateway = 0;
+       rth->rt_uses_gateway = 0;
        INIT_LIST_HEAD(&rth->rt_uncached);
 
        rth->dst.input = ip_forward;
@@ -1656,6 +1659,7 @@ local_input:
        rth->rt_iif     = 0;
        rth->rt_pmtu    = 0;
        rth->rt_gateway = 0;
+       rth->rt_uses_gateway = 0;
        INIT_LIST_HEAD(&rth->rt_uncached);
        if (res.type == RTN_UNREACHABLE) {
                rth->dst.input= ip_error;
@@ -1758,6 +1762,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
        struct in_device *in_dev;
        u16 type = res->type;
        struct rtable *rth;
+       bool do_cache;
 
        in_dev = __in_dev_get_rcu(dev_out);
        if (!in_dev)
@@ -1794,24 +1799,36 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
        }
 
        fnhe = NULL;
+       do_cache = fi != NULL;
        if (fi) {
                struct rtable __rcu **prth;
+               struct fib_nh *nh = &FIB_RES_NH(*res);
 
-               fnhe = find_exception(&FIB_RES_NH(*res), fl4->daddr);
+               fnhe = find_exception(nh, fl4->daddr);
                if (fnhe)
                        prth = &fnhe->fnhe_rth;
-               else
-                       prth = __this_cpu_ptr(FIB_RES_NH(*res).nh_pcpu_rth_output);
+               else {
+                       if (unlikely(fl4->flowi4_flags &
+                                    FLOWI_FLAG_KNOWN_NH &&
+                                    !(nh->nh_gw &&
+                                      nh->nh_scope == RT_SCOPE_LINK))) {
+                               do_cache = false;
+                               goto add;
+                       }
+                       prth = __this_cpu_ptr(nh->nh_pcpu_rth_output);
+               }
                rth = rcu_dereference(*prth);
                if (rt_cache_valid(rth)) {
                        dst_hold(&rth->dst);
                        return rth;
                }
        }
+
+add:
        rth = rt_dst_alloc(dev_out,
                           IN_DEV_CONF_GET(in_dev, NOPOLICY),
                           IN_DEV_CONF_GET(in_dev, NOXFRM),
-                          fi);
+                          do_cache);
        if (!rth)
                return ERR_PTR(-ENOBUFS);
 
@@ -1824,6 +1841,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
        rth->rt_iif     = orig_oif ? : 0;
        rth->rt_pmtu    = 0;
        rth->rt_gateway = 0;
+       rth->rt_uses_gateway = 0;
        INIT_LIST_HEAD(&rth->rt_uncached);
 
        RT_CACHE_STAT_INC(out_slow_tot);
@@ -2102,6 +2120,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
                rt->rt_flags = ort->rt_flags;
                rt->rt_type = ort->rt_type;
                rt->rt_gateway = ort->rt_gateway;
+               rt->rt_uses_gateway = ort->rt_uses_gateway;
 
                INIT_LIST_HEAD(&rt->rt_uncached);
 
@@ -2180,28 +2199,31 @@ static int rt_fill_info(struct net *net,  __be32 dst, __be32 src,
                if (nla_put_be32(skb, RTA_PREFSRC, fl4->saddr))
                        goto nla_put_failure;
        }
-       if (rt->rt_gateway &&
+       if (rt->rt_uses_gateway &&
            nla_put_be32(skb, RTA_GATEWAY, rt->rt_gateway))
                goto nla_put_failure;
 
+       expires = rt->dst.expires;
+       if (expires) {
+               unsigned long now = jiffies;
+
+               if (time_before(now, expires))
+                       expires -= now;
+               else
+                       expires = 0;
+       }
+
        memcpy(metrics, dst_metrics_ptr(&rt->dst), sizeof(metrics));
-       if (rt->rt_pmtu)
+       if (rt->rt_pmtu && expires)
                metrics[RTAX_MTU - 1] = rt->rt_pmtu;
        if (rtnetlink_put_metrics(skb, metrics) < 0)
                goto nla_put_failure;
 
        if (fl4->flowi4_mark &&
-           nla_put_be32(skb, RTA_MARK, fl4->flowi4_mark))
+           nla_put_u32(skb, RTA_MARK, fl4->flowi4_mark))
                goto nla_put_failure;
 
        error = rt->dst.error;
-       expires = rt->dst.expires;
-       if (expires) {
-               if (time_before(jiffies, expires))
-                       expires -= jiffies;
-               else
-                       expires = 0;
-       }
 
        if (rt_is_input_route(rt)) {
                if (nla_put_u32(skb, RTA_IIF, rt->rt_iif))
index 9205e492dc9d8a36b05f18ccedcdf4704867c986..63d4eccc674ddd1d297368166792e99c636658f6 100644 (file)
@@ -248,6 +248,8 @@ int proc_tcp_fastopen_key(ctl_table *ctl, int write, void __user *buffer,
        ctxt = rcu_dereference(tcp_fastopen_ctx);
        if (ctxt)
                memcpy(user_key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH);
+       else
+               memset(user_key, 0, sizeof(user_key));
        rcu_read_unlock();
 
        snprintf(tbl.data, tbl.maxlen, "%08x-%08x-%08x-%08x",
index 75735c9a6a9df2bf4026266c8c30d92bd474092c..ef998b008a570ba0976b911d85d0b98bb6d834fb 100644 (file)
@@ -708,10 +708,11 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
        arg.csumoffset = offsetof(struct tcphdr, check) / 2;
        arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0;
        /* When socket is gone, all binding information is lost.
-        * routing might fail in this case. using iif for oif to
-        * make sure we can deliver it
+        * routing might fail in this case. No choice here, if we choose to force
+        * input interface, we will misroute in case of asymmetric route.
         */
-       arg.bound_dev_if = sk ? sk->sk_bound_dev_if : inet_iif(skb);
+       if (sk)
+               arg.bound_dev_if = sk->sk_bound_dev_if;
 
        net = dev_net(skb_dst(skb)->dev);
        arg.tos = ip_hdr(skb)->tos;
index 681ea2f413e2ff624c41b8301d0095cf46ac73d9..05c5ab8d983c462f75ab6143ca653669d36c1005 100644 (file)
@@ -91,6 +91,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
                                              RTCF_LOCAL);
        xdst->u.rt.rt_type = rt->rt_type;
        xdst->u.rt.rt_gateway = rt->rt_gateway;
+       xdst->u.rt.rt_uses_gateway = rt->rt_uses_gateway;
        xdst->u.rt.rt_pmtu = rt->rt_pmtu;
        INIT_LIST_HEAD(&xdst->u.rt.rt_uncached);
 
index e22e6d88bac68173ecd6ca06e5bb7161583910ff..a974247a9ae40bdb6c83cf5a60a6432761bd84e7 100644 (file)
@@ -822,13 +822,6 @@ out:
        return segs;
 }
 
-struct ipv6_gro_cb {
-       struct napi_gro_cb napi;
-       int proto;
-};
-
-#define IPV6_GRO_CB(skb) ((struct ipv6_gro_cb *)(skb)->cb)
-
 static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
                                         struct sk_buff *skb)
 {
@@ -874,28 +867,31 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
                iph = ipv6_hdr(skb);
        }
 
-       IPV6_GRO_CB(skb)->proto = proto;
+       NAPI_GRO_CB(skb)->proto = proto;
 
        flush--;
        nlen = skb_network_header_len(skb);
 
        for (p = *head; p; p = p->next) {
-               struct ipv6hdr *iph2;
+               const struct ipv6hdr *iph2;
+               __be32 first_word; /* <Version:4><Traffic_Class:8><Flow_Label:20> */
 
                if (!NAPI_GRO_CB(p)->same_flow)
                        continue;
 
                iph2 = ipv6_hdr(p);
+               first_word = *(__be32 *)iph ^ *(__be32 *)iph2 ;
 
-               /* All fields must match except length. */
+               /* All fields must match except length and Traffic Class. */
                if (nlen != skb_network_header_len(p) ||
-                   memcmp(iph, iph2, offsetof(struct ipv6hdr, payload_len)) ||
+                   (first_word & htonl(0xF00FFFFF)) ||
                    memcmp(&iph->nexthdr, &iph2->nexthdr,
                           nlen - offsetof(struct ipv6hdr, nexthdr))) {
                        NAPI_GRO_CB(p)->same_flow = 0;
                        continue;
                }
-
+               /* flush if Traffic Class fields are different */
+               NAPI_GRO_CB(p)->flush |= !!(first_word & htonl(0x0FF00000));
                NAPI_GRO_CB(p)->flush |= flush;
        }
 
@@ -927,7 +923,7 @@ static int ipv6_gro_complete(struct sk_buff *skb)
                                 sizeof(*iph));
 
        rcu_read_lock();
-       ops = rcu_dereference(inet6_protos[IPV6_GRO_CB(skb)->proto]);
+       ops = rcu_dereference(inet6_protos[NAPI_GRO_CB(skb)->proto]);
        if (WARN_ON(!ops || !ops->gro_complete))
                goto out_unlock;
 
index 49c890386ce9ba6b76e401191d7d64484da7a238..26175bffbaa060ad8da6357330ff596a5391cef6 100644 (file)
@@ -877,7 +877,8 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
        __tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr);
 
        fl6.flowi6_proto = IPPROTO_TCP;
-       fl6.flowi6_oif = inet6_iif(skb);
+       if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL)
+               fl6.flowi6_oif = inet6_iif(skb);
        fl6.fl6_dport = t1->dest;
        fl6.fl6_sport = t1->source;
        security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
index accfa00ffcdf0ee9cc9cc0046d977130888faccf..a16b7b4b1e026a9af85b47f0c596e472b2b71ded 100644 (file)
@@ -56,7 +56,6 @@ void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
        u64 tsfdelta;
 
        spin_lock_bh(&ifmsh->sync_offset_lock);
-
        if (ifmsh->sync_offset_clockdrift_max < beacon_int_fraction) {
                msync_dbg(sdata, "TBTT : max clockdrift=%lld; adjusting\n",
                          (long long) ifmsh->sync_offset_clockdrift_max);
@@ -69,11 +68,11 @@ void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
                tsfdelta = -beacon_int_fraction;
                ifmsh->sync_offset_clockdrift_max -= beacon_int_fraction;
        }
+       spin_unlock_bh(&ifmsh->sync_offset_lock);
 
        tsf = drv_get_tsf(local, sdata);
        if (tsf != -1ULL)
                drv_set_tsf(local, sdata, tsf + tsfdelta);
-       spin_unlock_bh(&ifmsh->sync_offset_lock);
 }
 
 static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
index 2ce89732d0f21755939699b55e3382ac98baeaca..3af0cc4130f1986e1cf672a9246830d478e222e9 100644 (file)
@@ -34,7 +34,7 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
                skb_queue_len(&local->skb_queue_unreliable);
        while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
               (skb = skb_dequeue(&local->skb_queue_unreliable))) {
-               dev_kfree_skb_irq(skb);
+               ieee80211_free_txskb(hw, skb);
                tmp--;
                I802_DEBUG_INC(local->tx_status_drop);
        }
@@ -159,7 +159,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
                           "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n",
                           skb_queue_len(&sta->tx_filtered[ac]),
                           !!test_sta_flag(sta, WLAN_STA_PS_STA), jiffies);
-       dev_kfree_skb(skb);
+       ieee80211_free_txskb(&local->hw, skb);
 }
 
 static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid)
index e0e0d1d0e8301d4a8803b7af811e24d752347a88..c9bf83f36657c3ca9929e64d2fd27c47a6486e3a 100644 (file)
@@ -354,7 +354,7 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
                        total += skb_queue_len(&sta->ps_tx_buf[ac]);
                        if (skb) {
                                purged++;
-                               dev_kfree_skb(skb);
+                               ieee80211_free_txskb(&local->hw, skb);
                                break;
                        }
                }
@@ -466,7 +466,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
                        ps_dbg(tx->sdata,
                               "STA %pM TX buffer for AC %d full - dropping oldest frame\n",
                               sta->sta.addr, ac);
-                       dev_kfree_skb(old);
+                       ieee80211_free_txskb(&local->hw, old);
                } else
                        tx->local->total_ps_buffered++;
 
@@ -1103,7 +1103,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
                spin_unlock(&tx->sta->lock);
 
                if (purge_skb)
-                       dev_kfree_skb(purge_skb);
+                       ieee80211_free_txskb(&tx->local->hw, purge_skb);
        }
 
        /* reset session timer */
@@ -1214,7 +1214,7 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
                if (WARN_ON_ONCE(q >= local->hw.queues)) {
                        __skb_unlink(skb, skbs);
-                       dev_kfree_skb(skb);
+                       ieee80211_free_txskb(&local->hw, skb);
                        continue;
                }
 #endif
@@ -1356,7 +1356,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
        if (unlikely(res == TX_DROP)) {
                I802_DEBUG_INC(tx->local->tx_handlers_drop);
                if (tx->skb)
-                       dev_kfree_skb(tx->skb);
+                       ieee80211_free_txskb(&tx->local->hw, tx->skb);
                else
                        __skb_queue_purge(&tx->skbs);
                return -1;
@@ -1393,7 +1393,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
        res_prepare = ieee80211_tx_prepare(sdata, &tx, skb);
 
        if (unlikely(res_prepare == TX_DROP)) {
-               dev_kfree_skb(skb);
+               ieee80211_free_txskb(&local->hw, skb);
                goto out;
        } else if (unlikely(res_prepare == TX_QUEUED)) {
                goto out;
@@ -1465,7 +1465,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
        headroom = max_t(int, 0, headroom);
 
        if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
-               dev_kfree_skb(skb);
+               ieee80211_free_txskb(&local->hw, skb);
                rcu_read_unlock();
                return;
        }
@@ -2050,8 +2050,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                head_need += IEEE80211_ENCRYPT_HEADROOM;
                head_need += local->tx_headroom;
                head_need = max_t(int, 0, head_need);
-               if (ieee80211_skb_resize(sdata, skb, head_need, true))
-                       goto fail;
+               if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
+                       ieee80211_free_txskb(&local->hw, skb);
+                       return NETDEV_TX_OK;
+               }
        }
 
        if (encaps_data) {
@@ -2184,7 +2186,7 @@ void ieee80211_tx_pending(unsigned long data)
                        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
                        if (WARN_ON(!info->control.vif)) {
-                               kfree_skb(skb);
+                               ieee80211_free_txskb(&local->hw, skb);
                                continue;
                        }
 
index 56f6d5d81a7735d33ea7cc777945024850dfe177..cc4c8095681ad70dd0c40fa1a5459debed396a01 100644 (file)
@@ -50,6 +50,7 @@ enum {
                                      * local
                                      */
        IP_VS_RT_MODE_CONNECT   = 8, /* Always bind route to saddr */
+       IP_VS_RT_MODE_KNOWN_NH  = 16,/* Route via remote addr */
 };
 
 /*
@@ -113,6 +114,8 @@ static struct rtable *do_output_route4(struct net *net, __be32 daddr,
        fl4.daddr = daddr;
        fl4.saddr = (rt_mode & IP_VS_RT_MODE_CONNECT) ? *saddr : 0;
        fl4.flowi4_tos = rtos;
+       fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ?
+                          FLOWI_FLAG_KNOWN_NH : 0;
 
 retry:
        rt = ip_route_output_key(net, &fl4);
@@ -1061,7 +1064,8 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
        if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip,
                                      RT_TOS(iph->tos),
                                      IP_VS_RT_MODE_LOCAL |
-                                       IP_VS_RT_MODE_NON_LOCAL, NULL)))
+                                     IP_VS_RT_MODE_NON_LOCAL |
+                                     IP_VS_RT_MODE_KNOWN_NH, NULL)))
                goto tx_error_icmp;
        if (rt->rt_flags & RTCF_LOCAL) {
                ip_rt_put(rt);
index 0f2e3ad69c473afb5f7fcdbc1cbb05b5c0be46f7..01e944a017a4db6be96c3d4a8e7adc8d7890b34e 100644 (file)
@@ -169,6 +169,8 @@ static void netlink_sock_destruct(struct sock *sk)
        if (nlk->cb) {
                if (nlk->cb->done)
                        nlk->cb->done(nlk->cb);
+
+               module_put(nlk->cb->module);
                netlink_destroy_callback(nlk->cb);
        }
 
@@ -1758,6 +1760,7 @@ static int netlink_dump(struct sock *sk)
        nlk->cb = NULL;
        mutex_unlock(nlk->cb_mutex);
 
+       module_put(cb->module);
        netlink_consume_callback(cb);
        return 0;
 
@@ -1767,9 +1770,9 @@ errout_skb:
        return err;
 }
 
-int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
-                      const struct nlmsghdr *nlh,
-                      struct netlink_dump_control *control)
+int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+                        const struct nlmsghdr *nlh,
+                        struct netlink_dump_control *control)
 {
        struct netlink_callback *cb;
        struct sock *sk;
@@ -1784,6 +1787,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
        cb->done = control->done;
        cb->nlh = nlh;
        cb->data = control->data;
+       cb->module = control->module;
        cb->min_dump_alloc = control->min_dump_alloc;
        atomic_inc(&skb->users);
        cb->skb = skb;
@@ -1794,19 +1798,28 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
                return -ECONNREFUSED;
        }
        nlk = nlk_sk(sk);
-       /* A dump is in progress... */
+
        mutex_lock(nlk->cb_mutex);
+       /* A dump is in progress... */
        if (nlk->cb) {
                mutex_unlock(nlk->cb_mutex);
                netlink_destroy_callback(cb);
-               sock_put(sk);
-               return -EBUSY;
+               ret = -EBUSY;
+               goto out;
        }
+       /* add reference of module which cb->dump belongs to */
+       if (!try_module_get(cb->module)) {
+               mutex_unlock(nlk->cb_mutex);
+               netlink_destroy_callback(cb);
+               ret = -EPROTONOSUPPORT;
+               goto out;
+       }
+
        nlk->cb = cb;
        mutex_unlock(nlk->cb_mutex);
 
        ret = netlink_dump(sk);
-
+out:
        sock_put(sk);
 
        if (ret)
@@ -1817,7 +1830,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
         */
        return -EINTR;
 }
-EXPORT_SYMBOL(netlink_dump_start);
+EXPORT_SYMBOL(__netlink_dump_start);
 
 void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
 {
index 96531d4033a2160a6ba8c2ce7799025865fe863d..88eace57dd6bb11265bf3b765b5ac76cbb2ec3da 100644 (file)
@@ -1122,7 +1122,7 @@ rds_send_pong(struct rds_connection *conn, __be16 dport)
        rds_stats_inc(s_send_pong);
 
        if (!test_bit(RDS_LL_SEND_FULL, &conn->c_flags))
-               rds_send_xmit(conn);
+               queue_delayed_work(rds_wq, &conn->c_send_w, 0);
 
        rds_message_put(rm);
        return 0;
index 34c522021004dc31f3ffe04b279333240ab311e1..909dc0c31aab224a9978f4b144c825d676fa65e0 100644 (file)
@@ -239,7 +239,7 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct
        }
        return q;
 err:
-       dprintk("RPC:       gss_fill_context returning %ld\n", -PTR_ERR(p));
+       dprintk("RPC:       %s returning %ld\n", __func__, -PTR_ERR(p));
        return p;
 }
 
@@ -301,10 +301,10 @@ __gss_find_upcall(struct rpc_pipe *pipe, uid_t uid)
                if (pos->uid != uid)
                        continue;
                atomic_inc(&pos->count);
-               dprintk("RPC:       gss_find_upcall found msg %p\n", pos);
+               dprintk("RPC:       %s found msg %p\n", __func__, pos);
                return pos;
        }
-       dprintk("RPC:       gss_find_upcall found nothing\n");
+       dprintk("RPC:       %s found nothing\n", __func__);
        return NULL;
 }
 
@@ -507,8 +507,8 @@ gss_refresh_upcall(struct rpc_task *task)
        struct rpc_pipe *pipe;
        int err = 0;
 
-       dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid,
-                                                               cred->cr_uid);
+       dprintk("RPC: %5u %s for uid %u\n",
+               task->tk_pid, __func__, cred->cr_uid);
        gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred);
        if (PTR_ERR(gss_msg) == -EAGAIN) {
                /* XXX: warning on the first, under the assumption we
@@ -539,8 +539,8 @@ gss_refresh_upcall(struct rpc_task *task)
        spin_unlock(&pipe->lock);
        gss_release_msg(gss_msg);
 out:
-       dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n",
-                       task->tk_pid, cred->cr_uid, err);
+       dprintk("RPC: %5u %s for uid %u result %d\n",
+               task->tk_pid, __func__, cred->cr_uid, err);
        return err;
 }
 
@@ -553,7 +553,7 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
        DEFINE_WAIT(wait);
        int err = 0;
 
-       dprintk("RPC:       gss_upcall for uid %u\n", cred->cr_uid);
+       dprintk("RPC:       %s for uid %u\n", __func__, cred->cr_uid);
 retry:
        gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred);
        if (PTR_ERR(gss_msg) == -EAGAIN) {
@@ -594,8 +594,8 @@ out_intr:
        finish_wait(&gss_msg->waitqueue, &wait);
        gss_release_msg(gss_msg);
 out:
-       dprintk("RPC:       gss_create_upcall for uid %u result %d\n",
-                       cred->cr_uid, err);
+       dprintk("RPC:       %s for uid %u result %d\n",
+               __func__, cred->cr_uid, err);
        return err;
 }
 
@@ -681,7 +681,7 @@ err_put_ctx:
 err:
        kfree(buf);
 out:
-       dprintk("RPC:       gss_pipe_downcall returning %Zd\n", err);
+       dprintk("RPC:       %s returning %Zd\n", __func__, err);
        return err;
 }
 
@@ -747,8 +747,8 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
        struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg);
 
        if (msg->errno < 0) {
-               dprintk("RPC:       gss_pipe_destroy_msg releasing msg %p\n",
-                               gss_msg);
+               dprintk("RPC:       %s releasing msg %p\n",
+                       __func__, gss_msg);
                atomic_inc(&gss_msg->count);
                gss_unhash_msg(gss_msg);
                if (msg->errno == -ETIMEDOUT)
@@ -976,7 +976,7 @@ gss_destroying_context(struct rpc_cred *cred)
 static void
 gss_do_free_ctx(struct gss_cl_ctx *ctx)
 {
-       dprintk("RPC:       gss_free_ctx\n");
+       dprintk("RPC:       %s\n", __func__);
 
        gss_delete_sec_context(&ctx->gc_gss_ctx);
        kfree(ctx->gc_wire_ctx.data);
@@ -999,7 +999,7 @@ gss_free_ctx(struct gss_cl_ctx *ctx)
 static void
 gss_free_cred(struct gss_cred *gss_cred)
 {
-       dprintk("RPC:       gss_free_cred %p\n", gss_cred);
+       dprintk("RPC:       %s cred=%p\n", __func__, gss_cred);
        kfree(gss_cred);
 }
 
@@ -1049,8 +1049,8 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
        struct gss_cred *cred = NULL;
        int err = -ENOMEM;
 
-       dprintk("RPC:       gss_create_cred for uid %d, flavor %d\n",
-               acred->uid, auth->au_flavor);
+       dprintk("RPC:       %s for uid %d, flavor %d\n",
+               __func__, acred->uid, auth->au_flavor);
 
        if (!(cred = kzalloc(sizeof(*cred), GFP_NOFS)))
                goto out_err;
@@ -1069,7 +1069,7 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
        return &cred->gc_base;
 
 out_err:
-       dprintk("RPC:       gss_create_cred failed with error %d\n", err);
+       dprintk("RPC:       %s failed with error %d\n", __func__, err);
        return ERR_PTR(err);
 }
 
@@ -1127,7 +1127,7 @@ gss_marshal(struct rpc_task *task, __be32 *p)
        struct kvec     iov;
        struct xdr_buf  verf_buf;
 
-       dprintk("RPC: %5u gss_marshal\n", task->tk_pid);
+       dprintk("RPC: %5u %s\n", task->tk_pid, __func__);
 
        *p++ = htonl(RPC_AUTH_GSS);
        cred_len = p++;
@@ -1253,7 +1253,7 @@ gss_validate(struct rpc_task *task, __be32 *p)
        u32             flav,len;
        u32             maj_stat;
 
-       dprintk("RPC: %5u gss_validate\n", task->tk_pid);
+       dprintk("RPC: %5u %s\n", task->tk_pid, __func__);
 
        flav = ntohl(*p++);
        if ((len = ntohl(*p++)) > RPC_MAX_AUTH_SIZE)
@@ -1271,20 +1271,20 @@ gss_validate(struct rpc_task *task, __be32 *p)
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
                clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
        if (maj_stat) {
-               dprintk("RPC: %5u gss_validate: gss_verify_mic returned "
-                               "error 0x%08x\n", task->tk_pid, maj_stat);
+               dprintk("RPC: %5u %s: gss_verify_mic returned error 0x%08x\n",
+                       task->tk_pid, __func__, maj_stat);
                goto out_bad;
        }
        /* We leave it to unwrap to calculate au_rslack. For now we just
         * calculate the length of the verifier: */
        cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2;
        gss_put_ctx(ctx);
-       dprintk("RPC: %5u gss_validate: gss_verify_mic succeeded.\n",
-                       task->tk_pid);
+       dprintk("RPC: %5u %s: gss_verify_mic succeeded.\n",
+                       task->tk_pid, __func__);
        return p + XDR_QUADLEN(len);
 out_bad:
        gss_put_ctx(ctx);
-       dprintk("RPC: %5u gss_validate failed.\n", task->tk_pid);
+       dprintk("RPC: %5u %s failed.\n", task->tk_pid, __func__);
        return NULL;
 }
 
@@ -1466,7 +1466,7 @@ gss_wrap_req(struct rpc_task *task,
        struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
        int             status = -EIO;
 
-       dprintk("RPC: %5u gss_wrap_req\n", task->tk_pid);
+       dprintk("RPC: %5u %s\n", task->tk_pid, __func__);
        if (ctx->gc_proc != RPC_GSS_PROC_DATA) {
                /* The spec seems a little ambiguous here, but I think that not
                 * wrapping context destruction requests makes the most sense.
@@ -1489,7 +1489,7 @@ gss_wrap_req(struct rpc_task *task,
        }
 out:
        gss_put_ctx(ctx);
-       dprintk("RPC: %5u gss_wrap_req returning %d\n", task->tk_pid, status);
+       dprintk("RPC: %5u %s returning %d\n", task->tk_pid, __func__, status);
        return status;
 }
 
@@ -1604,8 +1604,8 @@ out_decode:
        status = gss_unwrap_req_decode(decode, rqstp, p, obj);
 out:
        gss_put_ctx(ctx);
-       dprintk("RPC: %5u gss_unwrap_resp returning %d\n", task->tk_pid,
-                       status);
+       dprintk("RPC: %5u %s returning %d\n",
+               task->tk_pid, __func__, status);
        return status;
 }
 
index fa48c60aef2305430956ef9735b20f6a0f62c073..cdc7564b4512d7f79606bc87fb7726a668a9b9a0 100644 (file)
@@ -490,61 +490,86 @@ EXPORT_SYMBOL_GPL(rpc_create);
  * same transport while varying parameters such as the authentication
  * flavour.
  */
-struct rpc_clnt *
-rpc_clone_client(struct rpc_clnt *clnt)
+static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
+                                          struct rpc_clnt *clnt)
 {
-       struct rpc_clnt *new;
        struct rpc_xprt *xprt;
-       int err = -ENOMEM;
+       struct rpc_clnt *new;
+       int err;
 
-       new = kmemdup(clnt, sizeof(*new), GFP_KERNEL);
-       if (!new)
-               goto out_no_clnt;
-       new->cl_parent = clnt;
-       /* Turn off autobind on clones */
-       new->cl_autobind = 0;
-       INIT_LIST_HEAD(&new->cl_tasks);
-       spin_lock_init(&new->cl_lock);
-       rpc_init_rtt(&new->cl_rtt_default, clnt->cl_timeout->to_initval);
-       new->cl_metrics = rpc_alloc_iostats(clnt);
-       if (new->cl_metrics == NULL)
-               goto out_no_stats;
-       if (clnt->cl_principal) {
-               new->cl_principal = kstrdup(clnt->cl_principal, GFP_KERNEL);
-               if (new->cl_principal == NULL)
-                       goto out_no_principal;
-       }
+       err = -ENOMEM;
        rcu_read_lock();
        xprt = xprt_get(rcu_dereference(clnt->cl_xprt));
        rcu_read_unlock();
        if (xprt == NULL)
-               goto out_no_transport;
-       rcu_assign_pointer(new->cl_xprt, xprt);
-       atomic_set(&new->cl_count, 1);
-       err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
-       if (err != 0)
-               goto out_no_path;
-       rpc_clnt_set_nodename(new, utsname()->nodename);
-       if (new->cl_auth)
-               atomic_inc(&new->cl_auth->au_count);
+               goto out_err;
+       args->servername = xprt->servername;
+
+       new = rpc_new_client(args, xprt);
+       if (IS_ERR(new)) {
+               err = PTR_ERR(new);
+               goto out_put;
+       }
+
        atomic_inc(&clnt->cl_count);
-       rpc_register_client(new);
-       rpciod_up();
+       new->cl_parent = clnt;
+
+       /* Turn off autobind on clones */
+       new->cl_autobind = 0;
+       new->cl_softrtry = clnt->cl_softrtry;
+       new->cl_discrtry = clnt->cl_discrtry;
+       new->cl_chatty = clnt->cl_chatty;
        return new;
-out_no_path:
+
+out_put:
        xprt_put(xprt);
-out_no_transport:
-       kfree(new->cl_principal);
-out_no_principal:
-       rpc_free_iostats(new->cl_metrics);
-out_no_stats:
-       kfree(new);
-out_no_clnt:
+out_err:
        dprintk("RPC:       %s: returned error %d\n", __func__, err);
        return ERR_PTR(err);
 }
+
+/**
+ * rpc_clone_client - Clone an RPC client structure
+ *
+ * @clnt: RPC client whose parameters are copied
+ *
+ * Returns a fresh RPC client or an ERR_PTR.
+ */
+struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt)
+{
+       struct rpc_create_args args = {
+               .program        = clnt->cl_program,
+               .prognumber     = clnt->cl_prog,
+               .version        = clnt->cl_vers,
+               .authflavor     = clnt->cl_auth->au_flavor,
+               .client_name    = clnt->cl_principal,
+       };
+       return __rpc_clone_client(&args, clnt);
+}
 EXPORT_SYMBOL_GPL(rpc_clone_client);
 
+/**
+ * rpc_clone_client_set_auth - Clone an RPC client structure and set its auth
+ *
+ * @clnt: RPC client whose parameters are copied
+ * @auth: security flavor for new client
+ *
+ * Returns a fresh RPC client or an ERR_PTR.
+ */
+struct rpc_clnt *
+rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
+{
+       struct rpc_create_args args = {
+               .program        = clnt->cl_program,
+               .prognumber     = clnt->cl_prog,
+               .version        = clnt->cl_vers,
+               .authflavor     = flavor,
+               .client_name    = clnt->cl_principal,
+       };
+       return __rpc_clone_client(&args, clnt);
+}
+EXPORT_SYMBOL_GPL(rpc_clone_client_set_auth);
+
 /*
  * Kill all tasks for the given client.
  * XXX: kill their descendants as well?
index 21fde99e5c56e4ed6413d51f46a3945bff67f7d9..80f5dd23417d92c932be96225b8c65723774aa40 100644 (file)
@@ -1119,8 +1119,8 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
                return -ENOMEM;
        if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL))
                return -ENOMEM;
-       dprintk("RPC:   sending pipefs MOUNT notification for net %p%s\n", net,
-                                                               NET_NAME(net));
+       dprintk("RPC:       sending pipefs MOUNT notification for net %p%s\n",
+               net, NET_NAME(net));
        sn->pipefs_sb = sb;
        err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
                                           RPC_PIPEFS_MOUNT,
@@ -1155,8 +1155,8 @@ static void rpc_kill_sb(struct super_block *sb)
        sn->pipefs_sb = NULL;
        mutex_unlock(&sn->pipefs_sb_lock);
        put_net(net);
-       dprintk("RPC:   sending pipefs UMOUNT notification for net %p%s\n", net,
-                                                               NET_NAME(net));
+       dprintk("RPC:       sending pipefs UMOUNT notification for net %p%s\n",
+               net, NET_NAME(net));
        blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
                                           RPC_PIPEFS_UMOUNT,
                                           sb);
index 128494ec9a6490e29de2ce52a0ae7b2a2a0368e3..6357fcb00c7e2046f8acb901d7005429d23158cd 100644 (file)
@@ -1022,7 +1022,7 @@ static int rpciod_start(void)
         * Create the rpciod thread and wait for it to start.
         */
        dprintk("RPC:       creating workqueue rpciod\n");
-       wq = alloc_workqueue("rpciod", WQ_MEM_RECLAIM, 0);
+       wq = alloc_workqueue("rpciod", WQ_MEM_RECLAIM, 1);
        rpciod_workqueue = wq;
        return rpciod_workqueue != NULL;
 }
index bac973a313673eaab9dc5300a86cef0cfbd577e0..194d865fae722216b71a7e78c84328b2d70b1b9b 100644 (file)
@@ -208,6 +208,35 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl,
        return xcl->xcl_ops->xpo_create(serv, net, sap, len, flags);
 }
 
+/*
+ * svc_xprt_received conditionally queues the transport for processing
+ * by another thread. The caller must hold the XPT_BUSY bit and must
+ * not thereafter touch transport data.
+ *
+ * Note: XPT_DATA only gets cleared when a read-attempt finds no (or
+ * insufficient) data.
+ */
+static void svc_xprt_received(struct svc_xprt *xprt)
+{
+       BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags));
+       /* As soon as we clear busy, the xprt could be closed and
+        * 'put', so we need a reference to call svc_xprt_enqueue with:
+        */
+       svc_xprt_get(xprt);
+       clear_bit(XPT_BUSY, &xprt->xpt_flags);
+       svc_xprt_enqueue(xprt);
+       svc_xprt_put(xprt);
+}
+
+void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *new)
+{
+       clear_bit(XPT_TEMP, &new->xpt_flags);
+       spin_lock_bh(&serv->sv_lock);
+       list_add(&new->xpt_list, &serv->sv_permsocks);
+       spin_unlock_bh(&serv->sv_lock);
+       svc_xprt_received(new);
+}
+
 int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
                    struct net *net, const int family,
                    const unsigned short port, int flags)
@@ -232,13 +261,8 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
                        module_put(xcl->xcl_owner);
                        return PTR_ERR(newxprt);
                }
-
-               clear_bit(XPT_TEMP, &newxprt->xpt_flags);
-               spin_lock_bh(&serv->sv_lock);
-               list_add(&newxprt->xpt_list, &serv->sv_permsocks);
-               spin_unlock_bh(&serv->sv_lock);
+               svc_add_new_perm_xprt(serv, newxprt);
                newport = svc_xprt_local_port(newxprt);
-               clear_bit(XPT_BUSY, &newxprt->xpt_flags);
                return newport;
        }
  err:
@@ -394,27 +418,6 @@ static struct svc_xprt *svc_xprt_dequeue(struct svc_pool *pool)
        return xprt;
 }
 
-/*
- * svc_xprt_received conditionally queues the transport for processing
- * by another thread. The caller must hold the XPT_BUSY bit and must
- * not thereafter touch transport data.
- *
- * Note: XPT_DATA only gets cleared when a read-attempt finds no (or
- * insufficient) data.
- */
-void svc_xprt_received(struct svc_xprt *xprt)
-{
-       BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags));
-       /* As soon as we clear busy, the xprt could be closed and
-        * 'put', so we need a reference to call svc_xprt_enqueue with:
-        */
-       svc_xprt_get(xprt);
-       clear_bit(XPT_BUSY, &xprt->xpt_flags);
-       svc_xprt_enqueue(xprt);
-       svc_xprt_put(xprt);
-}
-EXPORT_SYMBOL_GPL(svc_xprt_received);
-
 /**
  * svc_reserve - change the space reserved for the reply to a request.
  * @rqstp:  The request in question
@@ -565,33 +568,12 @@ static void svc_check_conn_limits(struct svc_serv *serv)
        }
 }
 
-/*
- * Receive the next request on any transport.  This code is carefully
- * organised not to touch any cachelines in the shared svc_serv
- * structure, only cachelines in the local svc_pool.
- */
-int svc_recv(struct svc_rqst *rqstp, long timeout)
+int svc_alloc_arg(struct svc_rqst *rqstp)
 {
-       struct svc_xprt         *xprt = NULL;
-       struct svc_serv         *serv = rqstp->rq_server;
-       struct svc_pool         *pool = rqstp->rq_pool;
-       int                     len, i;
-       int                     pages;
-       struct xdr_buf          *arg;
-       DECLARE_WAITQUEUE(wait, current);
-       long                    time_left;
-
-       dprintk("svc: server %p waiting for data (to = %ld)\n",
-               rqstp, timeout);
-
-       if (rqstp->rq_xprt)
-               printk(KERN_ERR
-                       "svc_recv: service %p, transport not NULL!\n",
-                        rqstp);
-       if (waitqueue_active(&rqstp->rq_wait))
-               printk(KERN_ERR
-                       "svc_recv: service %p, wait queue active!\n",
-                        rqstp);
+       struct svc_serv *serv = rqstp->rq_server;
+       struct xdr_buf *arg;
+       int pages;
+       int i;
 
        /* now allocate needed pages.  If we get a failure, sleep briefly */
        pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE;
@@ -621,11 +603,15 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
        arg->page_len = (pages-2)*PAGE_SIZE;
        arg->len = (pages-1)*PAGE_SIZE;
        arg->tail[0].iov_len = 0;
+       return 0;
+}
 
-       try_to_freeze();
-       cond_resched();
-       if (signalled() || kthread_should_stop())
-               return -EINTR;
+struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout)
+{
+       struct svc_xprt *xprt;
+       struct svc_pool         *pool = rqstp->rq_pool;
+       DECLARE_WAITQUEUE(wait, current);
+       long                    time_left;
 
        /* Normally we will wait up to 5 seconds for any required
         * cache information to be provided.
@@ -663,7 +649,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
                if (kthread_should_stop()) {
                        set_current_state(TASK_RUNNING);
                        spin_unlock_bh(&pool->sp_lock);
-                       return -EINTR;
+                       return ERR_PTR(-EINTR);
                }
 
                add_wait_queue(&rqstp->rq_wait, &wait);
@@ -684,48 +670,58 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
                        spin_unlock_bh(&pool->sp_lock);
                        dprintk("svc: server %p, no data yet\n", rqstp);
                        if (signalled() || kthread_should_stop())
-                               return -EINTR;
+                               return ERR_PTR(-EINTR);
                        else
-                               return -EAGAIN;
+                               return ERR_PTR(-EAGAIN);
                }
        }
        spin_unlock_bh(&pool->sp_lock);
+       return xprt;
+}
+
+void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt)
+{
+       spin_lock_bh(&serv->sv_lock);
+       set_bit(XPT_TEMP, &newxpt->xpt_flags);
+       list_add(&newxpt->xpt_list, &serv->sv_tempsocks);
+       serv->sv_tmpcnt++;
+       if (serv->sv_temptimer.function == NULL) {
+               /* setup timer to age temp transports */
+               setup_timer(&serv->sv_temptimer, svc_age_temp_xprts,
+                           (unsigned long)serv);
+               mod_timer(&serv->sv_temptimer,
+                         jiffies + svc_conn_age_period * HZ);
+       }
+       spin_unlock_bh(&serv->sv_lock);
+       svc_xprt_received(newxpt);
+}
+
+static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt)
+{
+       struct svc_serv *serv = rqstp->rq_server;
+       int len = 0;
 
-       len = 0;
        if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
                dprintk("svc_recv: found XPT_CLOSE\n");
                svc_delete_xprt(xprt);
                /* Leave XPT_BUSY set on the dead xprt: */
-               goto out;
+               return 0;
        }
        if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) {
                struct svc_xprt *newxpt;
+               /*
+                * We know this module_get will succeed because the
+                * listener holds a reference too
+                */
+               __module_get(xprt->xpt_class->xcl_owner);
+               svc_check_conn_limits(xprt->xpt_server);
                newxpt = xprt->xpt_ops->xpo_accept(xprt);
-               if (newxpt) {
-                       /*
-                        * We know this module_get will succeed because the
-                        * listener holds a reference too
-                        */
-                       __module_get(newxpt->xpt_class->xcl_owner);
-                       svc_check_conn_limits(xprt->xpt_server);
-                       spin_lock_bh(&serv->sv_lock);
-                       set_bit(XPT_TEMP, &newxpt->xpt_flags);
-                       list_add(&newxpt->xpt_list, &serv->sv_tempsocks);
-                       serv->sv_tmpcnt++;
-                       if (serv->sv_temptimer.function == NULL) {
-                               /* setup timer to age temp transports */
-                               setup_timer(&serv->sv_temptimer,
-                                           svc_age_temp_xprts,
-                                           (unsigned long)serv);
-                               mod_timer(&serv->sv_temptimer,
-                                         jiffies + svc_conn_age_period * HZ);
-                       }
-                       spin_unlock_bh(&serv->sv_lock);
-                       svc_xprt_received(newxpt);
-               }
+               if (newxpt)
+                       svc_add_new_temp_xprt(serv, newxpt);
        } else if (xprt->xpt_ops->xpo_has_wspace(xprt)) {
+               /* XPT_DATA|XPT_DEFERRED case: */
                dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n",
-                       rqstp, pool->sp_id, xprt,
+                       rqstp, rqstp->rq_pool->sp_id, xprt,
                        atomic_read(&xprt->xpt_ref.refcount));
                rqstp->rq_deferred = svc_deferred_dequeue(xprt);
                if (rqstp->rq_deferred)
@@ -736,10 +732,51 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
                rqstp->rq_reserved = serv->sv_max_mesg;
                atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
        }
+       /* clear XPT_BUSY: */
        svc_xprt_received(xprt);
+       return len;
+}
+
+/*
+ * Receive the next request on any transport.  This code is carefully
+ * organised not to touch any cachelines in the shared svc_serv
+ * structure, only cachelines in the local svc_pool.
+ */
+int svc_recv(struct svc_rqst *rqstp, long timeout)
+{
+       struct svc_xprt         *xprt = NULL;
+       struct svc_serv         *serv = rqstp->rq_server;
+       int                     len, err;
+
+       dprintk("svc: server %p waiting for data (to = %ld)\n",
+               rqstp, timeout);
+
+       if (rqstp->rq_xprt)
+               printk(KERN_ERR
+                       "svc_recv: service %p, transport not NULL!\n",
+                        rqstp);
+       if (waitqueue_active(&rqstp->rq_wait))
+               printk(KERN_ERR
+                       "svc_recv: service %p, wait queue active!\n",
+                        rqstp);
+
+       err = svc_alloc_arg(rqstp);
+       if (err)
+               return err;
+
+       try_to_freeze();
+       cond_resched();
+       if (signalled() || kthread_should_stop())
+               return -EINTR;
+
+       xprt = svc_get_next_xprt(rqstp, timeout);
+       if (IS_ERR(xprt))
+               return PTR_ERR(xprt);
+
+       len = svc_handle_xprt(rqstp, xprt);
 
        /* No data, incomplete (TCP) read, or accept() */
-       if (len == 0 || len == -EAGAIN)
+       if (len <= 0)
                goto out;
 
        clear_bit(XPT_OLD, &xprt->xpt_flags);
@@ -917,16 +954,18 @@ void svc_close_xprt(struct svc_xprt *xprt)
 }
 EXPORT_SYMBOL_GPL(svc_close_xprt);
 
-static void svc_close_list(struct list_head *xprt_list, struct net *net)
+static void svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net)
 {
        struct svc_xprt *xprt;
 
+       spin_lock(&serv->sv_lock);
        list_for_each_entry(xprt, xprt_list, xpt_list) {
                if (xprt->xpt_net != net)
                        continue;
                set_bit(XPT_CLOSE, &xprt->xpt_flags);
                set_bit(XPT_BUSY, &xprt->xpt_flags);
        }
+       spin_unlock(&serv->sv_lock);
 }
 
 static void svc_clear_pools(struct svc_serv *serv, struct net *net)
@@ -949,24 +988,28 @@ static void svc_clear_pools(struct svc_serv *serv, struct net *net)
        }
 }
 
-static void svc_clear_list(struct list_head *xprt_list, struct net *net)
+static void svc_clear_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net)
 {
        struct svc_xprt *xprt;
        struct svc_xprt *tmp;
+       LIST_HEAD(victims);
 
+       spin_lock(&serv->sv_lock);
        list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) {
                if (xprt->xpt_net != net)
                        continue;
-               svc_delete_xprt(xprt);
+               list_move(&xprt->xpt_list, &victims);
        }
-       list_for_each_entry(xprt, xprt_list, xpt_list)
-               BUG_ON(xprt->xpt_net == net);
+       spin_unlock(&serv->sv_lock);
+
+       list_for_each_entry_safe(xprt, tmp, &victims, xpt_list)
+               svc_delete_xprt(xprt);
 }
 
 void svc_close_net(struct svc_serv *serv, struct net *net)
 {
-       svc_close_list(&serv->sv_tempsocks, net);
-       svc_close_list(&serv->sv_permsocks, net);
+       svc_close_list(serv, &serv->sv_tempsocks, net);
+       svc_close_list(serv, &serv->sv_permsocks, net);
 
        svc_clear_pools(serv, net);
        /*
@@ -974,8 +1017,8 @@ void svc_close_net(struct svc_serv *serv, struct net *net)
         * svc_xprt_enqueue will not add new entries without taking the
         * sp_lock and checking XPT_BUSY.
         */
-       svc_clear_list(&serv->sv_tempsocks, net);
-       svc_clear_list(&serv->sv_permsocks, net);
+       svc_clear_list(serv, &serv->sv_tempsocks, net);
+       svc_clear_list(serv, &serv->sv_permsocks, net);
 }
 
 /*
index 998aa8c1807cd7cd548023d4ea2e80fedc9c2ca9..03827cef1fa783174409e23b2241bba903809e3a 100644 (file)
@@ -59,7 +59,7 @@
 
 
 static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *,
-                                        int *errp, int flags);
+                                        int flags);
 static void            svc_udp_data_ready(struct sock *, int);
 static int             svc_udp_recvfrom(struct svc_rqst *);
 static int             svc_udp_sendto(struct svc_rqst *);
@@ -305,57 +305,6 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
        return len;
 }
 
-/**
- * svc_sock_names - construct a list of listener names in a string
- * @serv: pointer to RPC service
- * @buf: pointer to a buffer to fill in with socket names
- * @buflen: size of the buffer to be filled
- * @toclose: pointer to '\0'-terminated C string containing the name
- *             of a listener to be closed
- *
- * Fills in @buf with a '\n'-separated list of names of listener
- * sockets.  If @toclose is not NULL, the socket named by @toclose
- * is closed, and is not included in the output list.
- *
- * Returns positive length of the socket name string, or a negative
- * errno value on error.
- */
-int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen,
-                  const char *toclose)
-{
-       struct svc_sock *svsk, *closesk = NULL;
-       int len = 0;
-
-       if (!serv)
-               return 0;
-
-       spin_lock_bh(&serv->sv_lock);
-       list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) {
-               int onelen = svc_one_sock_name(svsk, buf + len, buflen - len);
-               if (onelen < 0) {
-                       len = onelen;
-                       break;
-               }
-               if (toclose && strcmp(toclose, buf + len) == 0) {
-                       closesk = svsk;
-                       svc_xprt_get(&closesk->sk_xprt);
-               } else
-                       len += onelen;
-       }
-       spin_unlock_bh(&serv->sv_lock);
-
-       if (closesk) {
-               /* Should unregister with portmap, but you cannot
-                * unregister just one protocol...
-                */
-               svc_close_xprt(&closesk->sk_xprt);
-               svc_xprt_put(&closesk->sk_xprt);
-       } else if (toclose)
-               return -ENOENT;
-       return len;
-}
-EXPORT_SYMBOL_GPL(svc_sock_names);
-
 /*
  * Check input queue length
  */
@@ -598,11 +547,9 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
                        dprintk("svc: recvfrom returned error %d\n", -err);
                        set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
                }
-               return -EAGAIN;
+               return 0;
        }
        len = svc_addr_len(svc_addr(rqstp));
-       if (len == 0)
-               return -EAFNOSUPPORT;
        rqstp->rq_addrlen = len;
        if (skb->tstamp.tv64 == 0) {
                skb->tstamp = ktime_get_real();
@@ -620,10 +567,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
        if (!svc_udp_get_dest_address(rqstp, cmh)) {
                net_warn_ratelimited("svc: received unknown control message %d/%d; dropping RPC reply datagram\n",
                                     cmh->cmsg_level, cmh->cmsg_type);
-out_free:
-               trace_kfree_skb(skb, svc_udp_recvfrom);
-               skb_free_datagram_locked(svsk->sk_sk, skb);
-               return 0;
+               goto out_free;
        }
        rqstp->rq_daddrlen = svc_addr_len(svc_daddr(rqstp));
 
@@ -662,6 +606,10 @@ out_free:
                serv->sv_stats->netudpcnt++;
 
        return len;
+out_free:
+       trace_kfree_skb(skb, svc_udp_recvfrom);
+       skb_free_datagram_locked(svsk->sk_sk, skb);
+       return 0;
 }
 
 static int
@@ -900,8 +848,9 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
         */
        newsock->sk->sk_sndtimeo = HZ*30;
 
-       if (!(newsvsk = svc_setup_socket(serv, newsock, &err,
-                                (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY))))
+       newsvsk = svc_setup_socket(serv, newsock,
+                                (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY));
+       if (IS_ERR(newsvsk))
                goto failed;
        svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen);
        err = kernel_getsockname(newsock, sin, &slen);
@@ -1174,13 +1123,13 @@ error:
        if (len != -EAGAIN)
                goto err_other;
        dprintk("RPC: TCP recvfrom got EAGAIN\n");
-       return -EAGAIN;
+       return 0;
 err_other:
        printk(KERN_NOTICE "%s: recvfrom returned errno %d\n",
               svsk->sk_xprt.xpt_server->sv_name, -len);
        set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
 err_noclose:
-       return -EAGAIN; /* record not complete */
+       return 0;       /* record not complete */
 }
 
 /*
@@ -1383,29 +1332,29 @@ EXPORT_SYMBOL_GPL(svc_sock_update_bufs);
  */
 static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
                                                struct socket *sock,
-                                               int *errp, int flags)
+                                               int flags)
 {
        struct svc_sock *svsk;
        struct sock     *inet;
        int             pmap_register = !(flags & SVC_SOCK_ANONYMOUS);
+       int             err = 0;
 
        dprintk("svc: svc_setup_socket %p\n", sock);
-       if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) {
-               *errp = -ENOMEM;
-               return NULL;
-       }
+       svsk = kzalloc(sizeof(*svsk), GFP_KERNEL);
+       if (!svsk)
+               return ERR_PTR(-ENOMEM);
 
        inet = sock->sk;
 
        /* Register socket with portmapper */
-       if (*errp >= 0 && pmap_register)
-               *errp = svc_register(serv, sock_net(sock->sk), inet->sk_family,
+       if (pmap_register)
+               err = svc_register(serv, sock_net(sock->sk), inet->sk_family,
                                     inet->sk_protocol,
                                     ntohs(inet_sk(inet)->inet_sport));
 
-       if (*errp < 0) {
+       if (err < 0) {
                kfree(svsk);
-               return NULL;
+               return ERR_PTR(err);
        }
 
        inet->sk_user_data = svsk;
@@ -1450,42 +1399,38 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return,
        int err = 0;
        struct socket *so = sockfd_lookup(fd, &err);
        struct svc_sock *svsk = NULL;
+       struct sockaddr_storage addr;
+       struct sockaddr *sin = (struct sockaddr *)&addr;
+       int salen;
 
        if (!so)
                return err;
+       err = -EAFNOSUPPORT;
        if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6))
-               err =  -EAFNOSUPPORT;
-       else if (so->sk->sk_protocol != IPPROTO_TCP &&
+               goto out;
+       err =  -EPROTONOSUPPORT;
+       if (so->sk->sk_protocol != IPPROTO_TCP &&
            so->sk->sk_protocol != IPPROTO_UDP)
-               err =  -EPROTONOSUPPORT;
-       else if (so->state > SS_UNCONNECTED)
-               err = -EISCONN;
-       else {
-               if (!try_module_get(THIS_MODULE))
-                       err = -ENOENT;
-               else
-                       svsk = svc_setup_socket(serv, so, &err,
-                                               SVC_SOCK_DEFAULTS);
-               if (svsk) {
-                       struct sockaddr_storage addr;
-                       struct sockaddr *sin = (struct sockaddr *)&addr;
-                       int salen;
-                       if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0)
-                               svc_xprt_set_local(&svsk->sk_xprt, sin, salen);
-                       clear_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags);
-                       spin_lock_bh(&serv->sv_lock);
-                       list_add(&svsk->sk_xprt.xpt_list, &serv->sv_permsocks);
-                       spin_unlock_bh(&serv->sv_lock);
-                       svc_xprt_received(&svsk->sk_xprt);
-                       err = 0;
-               } else
-                       module_put(THIS_MODULE);
-       }
-       if (err) {
-               sockfd_put(so);
-               return err;
+               goto out;
+       err = -EISCONN;
+       if (so->state > SS_UNCONNECTED)
+               goto out;
+       err = -ENOENT;
+       if (!try_module_get(THIS_MODULE))
+               goto out;
+       svsk = svc_setup_socket(serv, so, SVC_SOCK_DEFAULTS);
+       if (IS_ERR(svsk)) {
+               module_put(THIS_MODULE);
+               err = PTR_ERR(svsk);
+               goto out;
        }
+       if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0)
+               svc_xprt_set_local(&svsk->sk_xprt, sin, salen);
+       svc_add_new_perm_xprt(serv, &svsk->sk_xprt);
        return svc_one_sock_name(svsk, name_return, len);
+out:
+       sockfd_put(so);
+       return err;
 }
 EXPORT_SYMBOL_GPL(svc_addsock);
 
@@ -1563,11 +1508,13 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
                        goto bummer;
        }
 
-       if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) {
-               svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen);
-               return (struct svc_xprt *)svsk;
+       svsk = svc_setup_socket(serv, sock, flags);
+       if (IS_ERR(svsk)) {
+               error = PTR_ERR(svsk);
+               goto bummer;
        }
-
+       svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen);
+       return (struct svc_xprt *)svsk;
 bummer:
        dprintk("svc: svc_create_socket error = %d\n", -error);
        sock_release(sock);
index 0afba1b4b65606437d141cb21a64e6d00f3855f4..08f50afd5f2a1d9dedc53ed1157d94be7e1e964d 100644 (file)
@@ -730,19 +730,24 @@ static unsigned int xdr_align_pages(struct xdr_stream *xdr, unsigned int len)
 
        if (xdr->nwords == 0)
                return 0;
-       if (nwords > xdr->nwords) {
-               nwords = xdr->nwords;
-               len = nwords << 2;
-       }
        /* Realign pages to current pointer position */
        iov  = buf->head;
-       if (iov->iov_len > cur)
+       if (iov->iov_len > cur) {
                xdr_shrink_bufhead(buf, iov->iov_len - cur);
+               xdr->nwords = XDR_QUADLEN(buf->len - cur);
+       }
 
-       /* Truncate page data and move it into the tail */
-       if (buf->page_len > len)
+       if (nwords > xdr->nwords) {
+               nwords = xdr->nwords;
+               len = nwords << 2;
+       }
+       if (buf->page_len <= len)
+               len = buf->page_len;
+       else if (nwords < xdr->nwords) {
+               /* Truncate page data and move it into the tail */
                xdr_shrink_pagelen(buf, buf->page_len - len);
-       xdr->nwords = XDR_QUADLEN(buf->len - cur);
+               xdr->nwords = XDR_QUADLEN(buf->len - cur);
+       }
        return len;
 }
 
index 5d7f61d7559c9753c9bff0f29b371b5e62b5f0d9..bd462a532acfa695906887db429896ae569eac26 100644 (file)
@@ -231,7 +231,7 @@ EXPORT_SYMBOL_GPL(xprt_reserve_xprt);
 static void xprt_clear_locked(struct rpc_xprt *xprt)
 {
        xprt->snd_task = NULL;
-       if (!test_bit(XPRT_CLOSE_WAIT, &xprt->state) || xprt->shutdown) {
+       if (!test_bit(XPRT_CLOSE_WAIT, &xprt->state)) {
                smp_mb__before_clear_bit();
                clear_bit(XPRT_LOCKED, &xprt->state);
                smp_mb__after_clear_bit();
@@ -504,9 +504,6 @@ EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space);
  */
 void xprt_write_space(struct rpc_xprt *xprt)
 {
-       if (unlikely(xprt->shutdown))
-               return;
-
        spin_lock_bh(&xprt->transport_lock);
        if (xprt->snd_task) {
                dprintk("RPC:       write space: waking waiting task on "
@@ -679,7 +676,7 @@ xprt_init_autodisconnect(unsigned long data)
        struct rpc_xprt *xprt = (struct rpc_xprt *)data;
 
        spin_lock(&xprt->transport_lock);
-       if (!list_empty(&xprt->recv) || xprt->shutdown)
+       if (!list_empty(&xprt->recv))
                goto out_abort;
        if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
                goto out_abort;
@@ -1262,7 +1259,6 @@ out:
 static void xprt_destroy(struct rpc_xprt *xprt)
 {
        dprintk("RPC:       destroying transport %p\n", xprt);
-       xprt->shutdown = 1;
        del_timer_sync(&xprt->timer);
 
        rpc_destroy_wait_queue(&xprt->binding);
index 73b428bef5986bd06b751bf45b3f3f7f6698fdd2..62e4f9bcc387182f829cc5c7d7559b0c16cfee34 100644 (file)
@@ -578,10 +578,6 @@ static void handle_connect_req(struct rdma_cm_id *new_cma_id, size_t client_ird)
        list_add_tail(&newxprt->sc_accept_q, &listen_xprt->sc_accept_q);
        spin_unlock_bh(&listen_xprt->sc_lock);
 
-       /*
-        * Can't use svc_xprt_received here because we are not on a
-        * rqstp thread
-       */
        set_bit(XPT_CONN, &listen_xprt->sc_xprt.xpt_flags);
        svc_xprt_enqueue(&listen_xprt->sc_xprt);
 }
index 5d9202dc7cb127f5158a2a6e275fa0656c18f0a6..c9aa7a35f3bf8332952573d0d04c22423980c7c2 100644 (file)
@@ -199,21 +199,15 @@ xprt_rdma_connect_worker(struct work_struct *work)
        struct rpc_xprt *xprt = &r_xprt->xprt;
        int rc = 0;
 
-       if (!xprt->shutdown) {
-               current->flags |= PF_FSTRANS;
-               xprt_clear_connected(xprt);
-
-               dprintk("RPC:       %s: %sconnect\n", __func__,
-                               r_xprt->rx_ep.rep_connected != 0 ? "re" : "");
-               rc = rpcrdma_ep_connect(&r_xprt->rx_ep, &r_xprt->rx_ia);
-               if (rc)
-                       goto out;
-       }
-       goto out_clear;
+       current->flags |= PF_FSTRANS;
+       xprt_clear_connected(xprt);
+
+       dprintk("RPC:       %s: %sconnect\n", __func__,
+                       r_xprt->rx_ep.rep_connected != 0 ? "re" : "");
+       rc = rpcrdma_ep_connect(&r_xprt->rx_ep, &r_xprt->rx_ia);
+       if (rc)
+               xprt_wake_pending_tasks(xprt, rc);
 
-out:
-       xprt_wake_pending_tasks(xprt, rc);
-out_clear:
        dprintk("RPC:       %s: exit\n", __func__);
        xprt_clear_connecting(xprt);
        current->flags &= ~PF_FSTRANS;
index a35b8e52e551d4b931110a78727604c8d6af8283..aaaadfbe36e9525a42a86e1f649bf66e59eb7274 100644 (file)
@@ -917,9 +917,6 @@ static void xs_local_data_ready(struct sock *sk, int len)
        if (skb == NULL)
                goto out;
 
-       if (xprt->shutdown)
-               goto dropit;
-
        repsize = skb->len - sizeof(rpc_fraghdr);
        if (repsize < 4) {
                dprintk("RPC:       impossible RPC reply size %d\n", repsize);
@@ -981,9 +978,6 @@ static void xs_udp_data_ready(struct sock *sk, int len)
        if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL)
                goto out;
 
-       if (xprt->shutdown)
-               goto dropit;
-
        repsize = skb->len - sizeof(struct udphdr);
        if (repsize < 4) {
                dprintk("RPC:       impossible RPC reply size %d!\n", repsize);
@@ -1025,6 +1019,16 @@ static void xs_udp_data_ready(struct sock *sk, int len)
        read_unlock_bh(&sk->sk_callback_lock);
 }
 
+/*
+ * Helper function to force a TCP close if the server is sending
+ * junk and/or it has put us in CLOSE_WAIT
+ */
+static void xs_tcp_force_close(struct rpc_xprt *xprt)
+{
+       set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
+       xprt_force_disconnect(xprt);
+}
+
 static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc)
 {
        struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
@@ -1051,7 +1055,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea
        /* Sanity check of the record length */
        if (unlikely(transport->tcp_reclen < 8)) {
                dprintk("RPC:       invalid TCP record fragment length\n");
-               xprt_force_disconnect(xprt);
+               xs_tcp_force_close(xprt);
                return;
        }
        dprintk("RPC:       reading TCP record fragment of length %d\n",
@@ -1132,7 +1136,7 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
                break;
        default:
                dprintk("RPC:       invalid request message type\n");
-               xprt_force_disconnect(&transport->xprt);
+               xs_tcp_force_close(&transport->xprt);
        }
        xs_tcp_check_fraghdr(transport);
 }
@@ -1402,9 +1406,6 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)
        read_lock_bh(&sk->sk_callback_lock);
        if (!(xprt = xprt_from_sock(sk)))
                goto out;
-       if (xprt->shutdown)
-               goto out;
-
        /* Any data means we had a useful conversation, so
         * the we don't need to delay the next reconnect
         */
@@ -1455,6 +1456,8 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt)
 static void xs_sock_mark_closed(struct rpc_xprt *xprt)
 {
        smp_mb__before_clear_bit();
+       clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
+       clear_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
        clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
        clear_bit(XPRT_CLOSING, &xprt->state);
        smp_mb__after_clear_bit();
@@ -1512,8 +1515,8 @@ static void xs_tcp_state_change(struct sock *sk)
                break;
        case TCP_CLOSE_WAIT:
                /* The server initiated a shutdown of the socket */
-               xprt_force_disconnect(xprt);
                xprt->connect_cookie++;
+               xs_tcp_force_close(xprt);
        case TCP_CLOSING:
                /*
                 * If the server closed down the connection, make sure that
@@ -1889,9 +1892,6 @@ static void xs_local_setup_socket(struct work_struct *work)
        struct socket *sock;
        int status = -EIO;
 
-       if (xprt->shutdown)
-               goto out;
-
        current->flags |= PF_FSTRANS;
 
        clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
@@ -2008,9 +2008,6 @@ static void xs_udp_setup_socket(struct work_struct *work)
        struct socket *sock = transport->sock;
        int status = -EIO;
 
-       if (xprt->shutdown)
-               goto out;
-
        current->flags |= PF_FSTRANS;
 
        /* Start by resetting any existing state */
@@ -2156,9 +2153,6 @@ static void xs_tcp_setup_socket(struct work_struct *work)
        struct rpc_xprt *xprt = &transport->xprt;
        int status = -EIO;
 
-       if (xprt->shutdown)
-               goto out;
-
        current->flags |= PF_FSTRANS;
 
        if (!sock) {
@@ -2199,8 +2193,7 @@ static void xs_tcp_setup_socket(struct work_struct *work)
                /* We're probably in TIME_WAIT. Get rid of existing socket,
                 * and retry
                 */
-               set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
-               xprt_force_disconnect(xprt);
+               xs_tcp_force_close(xprt);
                break;
        case -ECONNREFUSED:
        case -ECONNRESET:
@@ -2528,6 +2521,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,
+       .alloc_slot             = xprt_alloc_slot,
        .rpcbind                = xs_local_rpcbind,
        .buf_alloc              = bc_malloc,
        .buf_free               = bc_free,
index efa5d940e6324caa0aa120343043b89475502e74..3d13d3a3edfe821c9663de081d78045c96e69809 100644 (file)
@@ -9,7 +9,7 @@ include scripts/Kbuild.include
 
 #
 
-__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
+__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
 modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
 
 PHONY += $(modules)
index 08dce14f2dc862d78d30744e0e7cd7b4e915cc64..a1cb0222ebe642b6fd91093f2a01bd301b026e6e 100644 (file)
@@ -60,7 +60,7 @@ kernelsymfile := $(objtree)/Module.symvers
 modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
 
 # Step 1), find all modules listed in $(MODVERDIR)/
-__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
+__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
 modules   := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
 
 # Stop after building .o files if NOFINAL is set. Makes compile tests quicker
index 823e972149e5487fd09d974e9052c3a4d3d8214f..1a49d1c7ecfeb793a6bd116410f3c6449714eea5 100755 (executable)
@@ -95,6 +95,9 @@ coccinelle () {
        $SPATCH -D report  $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || \
        $SPATCH -D context $FLAGS -sp_file $COCCI $OPT $OPTIONS               || \
        $SPATCH -D org     $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || exit 1
+    elif [ "$MODE" = "rep+ctxt" ] ; then
+       $SPATCH -D report  $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff && \
+       $SPATCH -D context $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1
     else
        $SPATCH -D $MODE   $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1
     fi
index cbfd08c7d8c734152f5bcadfff38298bc9ceb828..15f076fdecbe073474e3eeeaf9e813a3fa77667e 100644 (file)
@@ -30,6 +30,13 @@ expression ptr;
 - if (IS_ERR(ptr)) return PTR_ERR(ptr); return 0;
 + return PTR_RET(ptr);
 
+@depends on patch@
+expression ptr;
+@@
+
+- (IS_ERR(ptr) ? PTR_ERR(ptr) : 0)
++ PTR_RET(ptr)
+
 @r1 depends on !patch@
 expression ptr;
 position p1;
@@ -44,6 +51,13 @@ position p2;
 
 * if@p2 (IS_ERR(ptr)) return PTR_ERR(ptr); return 0;
 
+@r3 depends on !patch@
+expression ptr;
+position p3;
+@@
+
+* IS_ERR@p3(ptr) ? PTR_ERR(ptr) : 0
+
 @script:python depends on org@
 p << r1.p1;
 @@
@@ -57,6 +71,12 @@ p << r2.p2;
 
 coccilib.org.print_todo(p[0], "WARNING: PTR_RET can be used")
 
+@script:python depends on org@
+p << r3.p3;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING: PTR_RET can be used")
+
 @script:python depends on report@
 p << r1.p1;
 @@
@@ -68,3 +88,9 @@ p << r2.p2;
 @@
 
 coccilib.report.print_report(p[0], "WARNING: PTR_RET can be used")
+
+@script:python depends on report@
+p << r3.p3;
+@@
+
+coccilib.report.print_report(p[0], "WARNING: PTR_RET can be used")
diff --git a/scripts/coccinelle/tests/odd_ptr_err.cocci b/scripts/coccinelle/tests/odd_ptr_err.cocci
new file mode 100644 (file)
index 0000000..e8dd8a6
--- /dev/null
@@ -0,0 +1,65 @@
+/// PTR_ERR should access the value just tested by IS_ERR
+//# There can be false positives in the patch case, where it is the call
+//# IS_ERR that is wrong.
+///
+// Confidence: High
+// Copyright: (C) 2012 Julia Lawall, INRIA.  GPLv2.
+// Copyright: (C) 2012 Gilles Muller, INRIA.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+@depends on patch@
+expression e,e1;
+@@
+
+(
+if (IS_ERR(e)) { ... PTR_ERR(e) ... }
+|
+if (IS_ERR(e=e1)) { ... PTR_ERR(e) ... }
+|
+if (IS_ERR(e))
+ { ...
+  PTR_ERR(
+-   e1
++   e
+  )
+   ... }
+)
+
+@r depends on !patch@
+expression e,e1;
+position p1,p2;
+@@
+
+(
+if (IS_ERR(e)) { ... PTR_ERR(e) ... }
+|
+if (IS_ERR(e=e1)) { ... PTR_ERR(e) ... }
+|
+*if (IS_ERR@p1(e))
+ { ...
+*  PTR_ERR@p2(e1)
+   ... }
+)
+
+@script:python depends on org@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+cocci.print_main("inconsistent IS_ERR and PTR_ERR",p1)
+cocci.print_secs("PTR_ERR",p2)
+
+@script:python depends on report@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+msg = "inconsistent IS_ERR and PTR_ERR, PTR_ERR on line %s" % (p2[0].line)
+coccilib.report.print_report(p1[0],msg)
index 77d53999ffb90f51bea3f0395be08e495e3b75b8..3091794e935488c797e73207e6d0b82a7dbf99b4 100644 (file)
@@ -76,11 +76,17 @@ PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig
 allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf
        $< --$@ $(Kconfig)
 
-PHONY += listnewconfig oldnoconfig savedefconfig defconfig
+PHONY += listnewconfig olddefconfig oldnoconfig savedefconfig defconfig
 
-listnewconfig oldnoconfig: $(obj)/conf
+listnewconfig olddefconfig: $(obj)/conf
        $< --$@ $(Kconfig)
 
+# oldnoconfig is an alias of olddefconfig, because people already are dependent
+# on its behavior(sets new symbols to their default value but not 'n') with the
+# counter-intuitive name.
+oldnoconfig: $(obj)/conf
+       $< --olddefconfig $(Kconfig)
+
 savedefconfig: $(obj)/conf
        $< --$@=defconfig $(Kconfig)
 
@@ -114,7 +120,7 @@ help:
        @echo  '  alldefconfig    - New config with all symbols set to default'
        @echo  '  randconfig      - New config with random answer to all options'
        @echo  '  listnewconfig   - List new options'
-       @echo  '  oldnoconfig     - Same as silentoldconfig but sets new symbols to their default value'
+       @echo  '  olddefconfig    - Same as silentoldconfig but sets new symbols to their default value'
 
 # lxdialog stuff
 check-lxdialog  := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
index 0dc4a2c779b119ec51e2eb5b3f17c5a4d02645fb..4da3b4adfad233cb97728b0e0278f8143919cee3 100644 (file)
@@ -32,7 +32,7 @@ enum input_mode {
        defconfig,
        savedefconfig,
        listnewconfig,
-       oldnoconfig,
+       olddefconfig,
 } input_mode = oldaskconfig;
 
 static int indent = 1;
@@ -365,7 +365,7 @@ static void conf(struct menu *menu)
                case P_MENU:
                        if ((input_mode == silentoldconfig ||
                             input_mode == listnewconfig ||
-                            input_mode == oldnoconfig) &&
+                            input_mode == olddefconfig) &&
                            rootEntry != menu) {
                                check_conf(menu);
                                return;
@@ -429,7 +429,7 @@ static void check_conf(struct menu *menu)
                                if (sym->name && !sym_is_choice_value(sym)) {
                                        printf("%s%s\n", CONFIG_, sym->name);
                                }
-                       } else if (input_mode != oldnoconfig) {
+                       } else if (input_mode != olddefconfig) {
                                if (!conf_cnt++)
                                        printf(_("*\n* Restart config...\n*\n"));
                                rootEntry = menu_get_parent_menu(menu);
@@ -454,7 +454,13 @@ static struct option long_opts[] = {
        {"alldefconfig",    no_argument,       NULL, alldefconfig},
        {"randconfig",      no_argument,       NULL, randconfig},
        {"listnewconfig",   no_argument,       NULL, listnewconfig},
-       {"oldnoconfig",     no_argument,       NULL, oldnoconfig},
+       {"olddefconfig",    no_argument,       NULL, olddefconfig},
+       /*
+        * oldnoconfig is an alias of olddefconfig, because people already
+        * are dependent on its behavior(sets new symbols to their default
+        * value but not 'n') with the counter-intuitive name.
+        */
+       {"oldnoconfig",     no_argument,       NULL, olddefconfig},
        {NULL, 0, NULL, 0}
 };
 
@@ -467,7 +473,8 @@ static void conf_usage(const char *progname)
        printf("  --oldaskconfig          Start a new configuration using a line-oriented program\n");
        printf("  --oldconfig             Update a configuration using a provided .config as base\n");
        printf("  --silentoldconfig       Same as oldconfig, but quietly, additionally update deps\n");
-       printf("  --oldnoconfig           Same as silentoldconfig but set new symbols to no\n");
+       printf("  --olddefconfig          Same as silentoldconfig but sets new symbols to their default value\n");
+       printf("  --oldnoconfig           An alias of olddefconfig\n");
        printf("  --defconfig <file>      New config with default defined in <file>\n");
        printf("  --savedefconfig <file>  Save the minimal current configuration to <file>\n");
        printf("  --allnoconfig           New config where all options are answered with no\n");
@@ -520,7 +527,7 @@ int main(int ac, char **av)
                case allmodconfig:
                case alldefconfig:
                case listnewconfig:
-               case oldnoconfig:
+               case olddefconfig:
                        break;
                case '?':
                        conf_usage(progname);
@@ -565,7 +572,7 @@ int main(int ac, char **av)
        case oldaskconfig:
        case oldconfig:
        case listnewconfig:
-       case oldnoconfig:
+       case olddefconfig:
                conf_read(NULL);
                break;
        case allnoconfig:
@@ -645,7 +652,7 @@ int main(int ac, char **av)
                /* fall through */
        case oldconfig:
        case listnewconfig:
-       case oldnoconfig:
+       case olddefconfig:
        case silentoldconfig:
                /* Update until a loop caused no more changes */
                do {
@@ -653,7 +660,7 @@ int main(int ac, char **av)
                        check_conf(&rootmenu);
                } while (conf_cnt &&
                         (input_mode != listnewconfig &&
-                         input_mode != oldnoconfig));
+                         input_mode != olddefconfig));
                break;
        }
 
index d4ecce8bc3a689daa2157e4f47e65e7c62192bd4..bd2e098955532a26a3935e44ad58283598cbf673 100644 (file)
@@ -12,6 +12,7 @@ extern "C" {
 
 #include <assert.h>
 #include <stdio.h>
+#include <sys/queue.h>
 #ifndef __cplusplus
 #include <stdbool.h>
 #endif
@@ -173,6 +174,16 @@ struct menu {
 #define MENU_CHANGED           0x0001
 #define MENU_ROOT              0x0002
 
+struct jump_key {
+       CIRCLEQ_ENTRY(jump_key) entries;
+       size_t offset;
+       struct menu *target;
+       int index;
+};
+CIRCLEQ_HEAD(jk_head, jump_key);
+
+#define JUMP_NB                        9
+
 extern struct file *file_list;
 extern struct file *current_file;
 struct file *lookup_file(const char *name);
index 47fe9c340f9a20b9b6bd9871d18d79ea9ddc7d1d..1d1c08537f1e59b2cab76bd88437489fcbea393b 100644 (file)
@@ -21,8 +21,10 @@ P(menu_get_root_menu,struct menu *,(struct menu *menu));
 P(menu_get_parent_menu,struct menu *,(struct menu *menu));
 P(menu_has_help,bool,(struct menu *menu));
 P(menu_get_help,const char *,(struct menu *menu));
-P(get_symbol_str, void, (struct gstr *r, struct symbol *sym));
-P(get_relations_str, struct gstr, (struct symbol **sym_arr));
+P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct jk_head
+                        *head));
+P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct jk_head
+                                  *head));
 P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
 
 /* symbol.c */
index b5211fce0d946ab90eaf1ba239f3b20b40039b11..ee17a5264d5b456c0672a77b06964bfc1ccd29d7 100644 (file)
@@ -144,6 +144,7 @@ struct dialog_info {
  */
 extern struct dialog_info dlg;
 extern char dialog_input_result[];
+extern int saved_x, saved_y;           /* Needed in signal handler in mconf.c */
 
 /*
  * Function prototypes
@@ -209,7 +210,13 @@ int first_alpha(const char *string, const char *exempt);
 int dialog_yesno(const char *title, const char *prompt, int height, int width);
 int dialog_msgbox(const char *title, const char *prompt, int height,
                  int width, int pause);
-int dialog_textbox(const char *title, const char *file, int height, int width);
+
+
+typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void
+                              *_data);
+int dialog_textbox(const char *title, char *tbuf, int initial_height,
+                  int initial_width, int *keys, int *_vscroll, int *_hscroll,
+                  update_text_fn update_text, void *data);
 int dialog_menu(const char *title, const char *prompt,
                const void *selected, int *s_scroll);
 int dialog_checklist(const char *title, const char *prompt, int height,
index 4e5de60a0c0d35765d1cfb8f67a06c852c892e8a..a48bb93e09073f05ea14786fea9370202f5039f9 100644 (file)
 #include "dialog.h"
 
 static void back_lines(int n);
-static void print_page(WINDOW * win, int height, int width);
-static void print_line(WINDOW * win, int row, int width);
+static void print_page(WINDOW *win, int height, int width, update_text_fn
+                      update_text, void *data);
+static void print_line(WINDOW *win, int row, int width);
 static char *get_line(void);
 static void print_position(WINDOW * win);
 
 static int hscroll;
 static int begin_reached, end_reached, page_length;
-static const char *buf;
-static const char *page;
+static char *buf;
+static char *page;
 
 /*
  * refresh window content
  */
 static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
-                                                         int cur_y, int cur_x)
+                            int cur_y, int cur_x, update_text_fn update_text,
+                            void *data)
 {
-       print_page(box, boxh, boxw);
+       print_page(box, boxh, boxw, update_text, data);
        print_position(dialog);
        wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
        wrefresh(dialog);
@@ -47,14 +49,18 @@ static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
 
 /*
  * Display text from a file in a dialog box.
+ *
+ * keys is a null-terminated array
+ * update_text() may not add or remove any '\n' or '\0' in tbuf
  */
-int dialog_textbox(const char *title, const char *tbuf,
-                  int initial_height, int initial_width)
+int dialog_textbox(const char *title, char *tbuf, int initial_height,
+                  int initial_width, int *keys, int *_vscroll, int *_hscroll,
+                  update_text_fn update_text, void *data)
 {
        int i, x, y, cur_x, cur_y, key = 0;
        int height, width, boxh, boxw;
-       int passed_end;
        WINDOW *dialog, *box;
+       bool done = false;
 
        begin_reached = 1;
        end_reached = 0;
@@ -63,6 +69,15 @@ int dialog_textbox(const char *title, const char *tbuf,
        buf = tbuf;
        page = buf;     /* page is pointer to start of page to be displayed */
 
+       if (_vscroll && *_vscroll) {
+               begin_reached = 0;
+
+               for (i = 0; i < *_vscroll; i++)
+                       get_line();
+       }
+       if (_hscroll)
+               hscroll = *_hscroll;
+
 do_resize:
        getmaxyx(stdscr, height, width);
        if (height < 8 || width < 8)
@@ -120,9 +135,10 @@ do_resize:
 
        /* Print first page of text */
        attr_clear(box, boxh, boxw, dlg.dialog.atr);
-       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
+       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text,
+                        data);
 
-       while ((key != KEY_ESC) && (key != '\n')) {
+       while (!done) {
                key = wgetch(dialog);
                switch (key) {
                case 'E':       /* Exit */
@@ -130,16 +146,17 @@ do_resize:
                case 'X':
                case 'x':
                case 'q':
-                       delwin(box);
-                       delwin(dialog);
-                       return 0;
+               case '\n':
+                       done = true;
+                       break;
                case 'g':       /* First page */
                case KEY_HOME:
                        if (!begin_reached) {
                                begin_reached = 1;
                                page = buf;
                                refresh_text_box(dialog, box, boxh, boxw,
-                                                cur_y, cur_x);
+                                                cur_y, cur_x, update_text,
+                                                data);
                        }
                        break;
                case 'G':       /* Last page */
@@ -149,45 +166,18 @@ do_resize:
                        /* point to last char in buf */
                        page = buf + strlen(buf);
                        back_lines(boxh);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case 'K':       /* Previous line */
                case 'k':
                case KEY_UP:
-                       if (!begin_reached) {
-                               back_lines(page_length + 1);
-
-                               /* We don't call print_page() here but use
-                                * scrolling to ensure faster screen update.
-                                * However, 'end_reached' and 'page_length'
-                                * should still be updated, and 'page' should
-                                * point to start of next page. This is done
-                                * by calling get_line() in the following
-                                * 'for' loop. */
-                               scrollok(box, TRUE);
-                               wscrl(box, -1); /* Scroll box region down one line */
-                               scrollok(box, FALSE);
-                               page_length = 0;
-                               passed_end = 0;
-                               for (i = 0; i < boxh; i++) {
-                                       if (!i) {
-                                               /* print first line of page */
-                                               print_line(box, 0, boxw);
-                                               wnoutrefresh(box);
-                                       } else
-                                               /* Called to update 'end_reached' and 'page' */
-                                               get_line();
-                                       if (!passed_end)
-                                               page_length++;
-                                       if (end_reached && !passed_end)
-                                               passed_end = 1;
-                               }
+                       if (begin_reached)
+                               break;
 
-                               print_position(dialog);
-                               wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
-                               wrefresh(dialog);
-                       }
+                       back_lines(page_length + 1);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case 'B':       /* Previous page */
                case 'b':
@@ -196,23 +186,18 @@ do_resize:
                        if (begin_reached)
                                break;
                        back_lines(page_length + boxh);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case 'J':       /* Next line */
                case 'j':
                case KEY_DOWN:
-                       if (!end_reached) {
-                               begin_reached = 0;
-                               scrollok(box, TRUE);
-                               scroll(box);    /* Scroll box region up one line */
-                               scrollok(box, FALSE);
-                               print_line(box, boxh - 1, boxw);
-                               wnoutrefresh(box);
-                               print_position(dialog);
-                               wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
-                               wrefresh(dialog);
-                       }
+                       if (end_reached)
+                               break;
+
+                       back_lines(page_length - 1);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case KEY_NPAGE: /* Next page */
                case ' ':
@@ -221,8 +206,8 @@ do_resize:
                                break;
 
                        begin_reached = 0;
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case '0':       /* Beginning of line */
                case 'H':       /* Scroll left */
@@ -237,8 +222,8 @@ do_resize:
                                hscroll--;
                        /* Reprint current page to scroll horizontally */
                        back_lines(page_length);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case 'L':       /* Scroll right */
                case 'l':
@@ -248,11 +233,12 @@ do_resize:
                        hscroll++;
                        /* Reprint current page to scroll horizontally */
                        back_lines(page_length);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case KEY_ESC:
-                       key = on_key_esc(dialog);
+                       if (on_key_esc(dialog) == KEY_ESC)
+                               done = true;
                        break;
                case KEY_RESIZE:
                        back_lines(height);
@@ -260,11 +246,31 @@ do_resize:
                        delwin(dialog);
                        on_key_resize();
                        goto do_resize;
+               default:
+                       for (i = 0; keys[i]; i++) {
+                               if (key == keys[i]) {
+                                       done = true;
+                                       break;
+                               }
+                       }
                }
        }
        delwin(box);
        delwin(dialog);
-       return key;             /* ESC pressed */
+       if (_vscroll) {
+               const char *s;
+
+               s = buf;
+               *_vscroll = 0;
+               back_lines(page_length);
+               while (s < page && (s = strchr(s, '\n'))) {
+                       (*_vscroll)++;
+                       s++;
+               }
+       }
+       if (_hscroll)
+               *_hscroll = hscroll;
+       return key;
 }
 
 /*
@@ -301,12 +307,23 @@ static void back_lines(int n)
 }
 
 /*
- * Print a new page of text. Called by dialog_textbox().
+ * Print a new page of text.
  */
-static void print_page(WINDOW * win, int height, int width)
+static void print_page(WINDOW *win, int height, int width, update_text_fn
+                      update_text, void *data)
 {
        int i, passed_end = 0;
 
+       if (update_text) {
+               char *end;
+
+               for (i = 0; i < height; i++)
+                       get_line();
+               end = page;
+               back_lines(height);
+               update_text(buf, page - buf, end - buf, data);
+       }
+
        page_length = 0;
        for (i = 0; i < height; i++) {
                print_line(win, i, width);
@@ -319,7 +336,7 @@ static void print_page(WINDOW * win, int height, int width)
 }
 
 /*
- * Print a new line of text. Called by dialog_textbox() and print_page().
+ * Print a new line of text.
  */
 static void print_line(WINDOW * win, int row, int width)
 {
@@ -357,10 +374,8 @@ static char *get_line(void)
        end_reached = 0;
        while (*page != '\n') {
                if (*page == '\0') {
-                       if (!end_reached) {
-                               end_reached = 1;
-                               break;
-                       }
+                       end_reached = 1;
+                       break;
                } else if (i < MAX_LEN)
                        line[i++] = *(page++);
                else {
@@ -373,7 +388,7 @@ static char *get_line(void)
        if (i <= MAX_LEN)
                line[i] = '\0';
        if (!end_reached)
-               page++;         /* move pass '\n' */
+               page++;         /* move past '\n' */
 
        return line;
 }
index f2375ad7ebc9bf07d306fc8de611f631b36cd7bf..109d53117d223682254502b51b6414d7404852e2 100644 (file)
@@ -23,6 +23,9 @@
 
 #include "dialog.h"
 
+/* Needed in signal handler in mconf.c */
+int saved_x, saved_y;
+
 struct dialog_info dlg;
 
 static void set_mono_theme(void)
@@ -273,6 +276,10 @@ int init_dialog(const char *backtitle)
        int height, width;
 
        initscr();              /* Init curses */
+
+       /* Get current cursor position for signal handler in mconf.c */
+       getyx(stdscr, saved_y, saved_x);
+
        getmaxyx(stdscr, height, width);
        if (height < 19 || width < 80) {
                endwin();
index f584a281bb4c94d240b135ba6943fe75a433b3ec..48f67448af7b67cf6c8df7394702a65767891992 100644 (file)
@@ -236,16 +236,19 @@ search_help[] = N_(
        "Result:\n"
        "-----------------------------------------------------------------\n"
        "Symbol: FOO [=m]\n"
+       "Type  : tristate\n"
        "Prompt: Foo bus is used to drive the bar HW\n"
-       "Defined at drivers/pci/Kconfig:47\n"
-       "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
-       "Location:\n"
-       "  -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
-       "    -> PCI support (PCI [=y])\n"
-       "      -> PCI access mode (<choice> [=y])\n"
-       "Selects: LIBCRC32\n"
-       "Selected by: BAR\n"
+       "  Defined at drivers/pci/Kconfig:47\n"
+       "  Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
+       "  Location:\n"
+       "    -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
+       "      -> PCI support (PCI [=y])\n"
+       "(1)     -> PCI access mode (<choice> [=y])\n"
+       "  Selects: LIBCRC32\n"
+       "  Selected by: BAR\n"
        "-----------------------------------------------------------------\n"
+       "o The line 'Type:' shows the type of the configuration option for\n"
+       "  this symbol (boolean, tristate, string, ...)\n"
        "o The line 'Prompt:' shows the text used in the menu structure for\n"
        "  this symbol\n"
        "o The 'Defined at' line tell at what file / line number the symbol\n"
@@ -254,8 +257,12 @@ search_help[] = N_(
        "  this symbol to be visible in the menu (selectable)\n"
        "o The 'Location:' lines tell where in the menu structure this symbol\n"
        "  is located\n"
-       "    A location followed by a [=y] indicate that this is a selectable\n"
-       "    menu item - and current value is displayed inside brackets.\n"
+       "    A location followed by a [=y] indicates that this is a\n"
+       "    selectable menu item - and the current value is displayed inside\n"
+       "    brackets.\n"
+       "    Press the key in the (#) prefix to jump directly to that\n"
+       "    location. You will be returned to the current search results\n"
+       "    after exiting this new menu.\n"
        "o The 'Selects:' line tell what symbol will be automatically\n"
        "  selected if this symbol is selected (y or m)\n"
        "o The 'Selected by' line tell what symbol has selected this symbol\n"
@@ -273,13 +280,15 @@ static struct menu *current_menu;
 static int child_count;
 static int single_menu_mode;
 static int show_all_options;
-static int saved_x, saved_y;
 
-static void conf(struct menu *menu);
+static void conf(struct menu *menu, struct menu *active_menu);
 static void conf_choice(struct menu *menu);
 static void conf_string(struct menu *menu);
 static void conf_load(void);
 static void conf_save(void);
+static int show_textbox_ext(const char *title, char *text, int r, int c,
+                           int *keys, int *vscroll, int *hscroll,
+                           update_text_fn update_text, void *data);
 static void show_textbox(const char *title, const char *text, int r, int c);
 static void show_helptext(const char *title, const char *text);
 static void show_help(struct menu *menu);
@@ -302,12 +311,47 @@ static void set_config_filename(const char *config_filename)
 }
 
 
+struct search_data {
+       struct jk_head *head;
+       struct menu **targets;
+       int *keys;
+};
+
+static void update_text(char *buf, size_t start, size_t end, void *_data)
+{
+       struct search_data *data = _data;
+       struct jump_key *pos;
+       int k = 0;
+
+       CIRCLEQ_FOREACH(pos, data->head, entries) {
+               if (pos->offset >= start && pos->offset < end) {
+                       char header[4];
+
+                       if (k < JUMP_NB) {
+                               int key = '0' + (pos->index % JUMP_NB) + 1;
+
+                               sprintf(header, "(%c)", key);
+                               data->keys[k] = key;
+                               data->targets[k] = pos->target;
+                               k++;
+                       } else {
+                               sprintf(header, "   ");
+                       }
+
+                       memcpy(buf + pos->offset, header, sizeof(header) - 1);
+               }
+       }
+       data->keys[k] = 0;
+}
+
 static void search_conf(void)
 {
        struct symbol **sym_arr;
        struct gstr res;
        char *dialog_input;
-       int dres;
+       int dres, vscroll = 0, hscroll = 0;
+       bool again;
+
 again:
        dialog_clear();
        dres = dialog_inputbox(_("Search Configuration Parameter"),
@@ -330,10 +374,30 @@ again:
                dialog_input += strlen(CONFIG_);
 
        sym_arr = sym_re_search(dialog_input);
-       res = get_relations_str(sym_arr);
+       do {
+               struct jk_head head = CIRCLEQ_HEAD_INITIALIZER(head);
+               struct menu *targets[JUMP_NB];
+               int keys[JUMP_NB + 1], i;
+               struct search_data data = {
+                       .head = &head,
+                       .targets = targets,
+                       .keys = keys,
+               };
+
+               res = get_relations_str(sym_arr, &head);
+               dres = show_textbox_ext(_("Search Results"), (char *)
+                                       str_get(&res), 0, 0, keys, &vscroll,
+                                       &hscroll, &update_text, (void *)
+                                       &data);
+               again = false;
+               for (i = 0; i < JUMP_NB && keys[i]; i++)
+                       if (dres == keys[i]) {
+                               conf(targets[i]->parent, targets[i]);
+                               again = true;
+                       }
+               str_free(&res);
+       } while (again);
        free(sym_arr);
-       show_textbox(_("Search Results"), str_get(&res), 0, 0);
-       str_free(&res);
 }
 
 static void build_conf(struct menu *menu)
@@ -514,12 +578,11 @@ conf_childs:
        indent -= doint;
 }
 
-static void conf(struct menu *menu)
+static void conf(struct menu *menu, struct menu *active_menu)
 {
        struct menu *submenu;
        const char *prompt = menu_get_prompt(menu);
        struct symbol *sym;
-       struct menu *active_menu = NULL;
        int res;
        int s_scroll = 0;
 
@@ -562,13 +625,13 @@ static void conf(struct menu *menu)
                                if (single_menu_mode)
                                        submenu->data = (void *) (long) !submenu->data;
                                else
-                                       conf(submenu);
+                                       conf(submenu, NULL);
                                break;
                        case 't':
                                if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
                                        conf_choice(submenu);
                                else if (submenu->prompt->type == P_MENU)
-                                       conf(submenu);
+                                       conf(submenu, NULL);
                                break;
                        case 's':
                                conf_string(submenu);
@@ -607,7 +670,7 @@ static void conf(struct menu *menu)
                        if (item_is_tag('t'))
                                sym_toggle_tristate_value(sym);
                        else if (item_is_tag('m'))
-                               conf(submenu);
+                               conf(submenu, NULL);
                        break;
                case 7:
                        search_conf();
@@ -619,10 +682,19 @@ static void conf(struct menu *menu)
        }
 }
 
-static void show_textbox(const char *title, const char *text, int r, int c)
+static int show_textbox_ext(const char *title, char *text, int r, int c, int
+                           *keys, int *vscroll, int *hscroll, update_text_fn
+                           update_text, void *data)
 {
        dialog_clear();
-       dialog_textbox(title, text, r, c);
+       return dialog_textbox(title, text, r, c, keys, vscroll, hscroll,
+                             update_text, data);
+}
+
+static void show_textbox(const char *title, const char *text, int r, int c)
+{
+       show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,
+                        NULL, NULL);
 }
 
 static void show_helptext(const char *title, const char *text)
@@ -862,9 +934,6 @@ int main(int ac, char **av)
                        single_menu_mode = 1;
        }
 
-       initscr();
-
-       getyx(stdscr, saved_y, saved_x);
        if (init_dialog(NULL)) {
                fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
                fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
@@ -873,7 +942,7 @@ int main(int ac, char **av)
 
        set_config_filename(conf_get_configname());
        do {
-               conf(&rootmenu);
+               conf(&rootmenu, NULL);
                res = handle_exit();
        } while (res == KEY_ESC);
 
index 8c2a97e60fafa701331949152261d162541482a1..a3cade659f89cb5f67828b797ae49b9311bf1d98 100644 (file)
@@ -507,10 +507,12 @@ const char *menu_get_help(struct menu *menu)
                return "";
 }
 
-static void get_prompt_str(struct gstr *r, struct property *prop)
+static void get_prompt_str(struct gstr *r, struct property *prop,
+                          struct jk_head *head)
 {
        int i, j;
-       struct menu *submenu[8], *menu;
+       struct menu *submenu[8], *menu, *location = NULL;
+       struct jump_key *jump;
 
        str_printf(r, _("Prompt: %s\n"), _(prop->text));
        str_printf(r, _("  Defined at %s:%d\n"), prop->menu->file->name,
@@ -521,13 +523,43 @@ static void get_prompt_str(struct gstr *r, struct property *prop)
                str_append(r, "\n");
        }
        menu = prop->menu->parent;
-       for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
+       for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
+               bool accessible = menu_is_visible(menu);
+
                submenu[i++] = menu;
+               if (location == NULL && accessible)
+                       location = menu;
+       }
+       if (head && location) {
+               jump = malloc(sizeof(struct jump_key));
+
+               if (menu_is_visible(prop->menu)) {
+                       /*
+                        * There is not enough room to put the hint at the
+                        * beginning of the "Prompt" line. Put the hint on the
+                        * last "Location" line even when it would belong on
+                        * the former.
+                        */
+                       jump->target = prop->menu;
+               } else
+                       jump->target = location;
+
+               if (CIRCLEQ_EMPTY(head))
+                       jump->index = 0;
+               else
+                       jump->index = CIRCLEQ_LAST(head)->index + 1;
+
+               CIRCLEQ_INSERT_TAIL(head, jump, entries);
+       }
+
        if (i > 0) {
                str_printf(r, _("  Location:\n"));
                for (j = 4; --i >= 0; j += 2) {
                        menu = submenu[i];
-                       str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu)));
+                       if (head && location && menu == location)
+                               jump->offset = r->len - 1;
+                       str_printf(r, "%*c-> %s", j, ' ',
+                                  _(menu_get_prompt(menu)));
                        if (menu->sym) {
                                str_printf(r, " (%s [=%s])", menu->sym->name ?
                                        menu->sym->name : _("<choice>"),
@@ -538,7 +570,10 @@ static void get_prompt_str(struct gstr *r, struct property *prop)
        }
 }
 
-void get_symbol_str(struct gstr *r, struct symbol *sym)
+/*
+ * head is optional and may be NULL
+ */
+void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head)
 {
        bool hit;
        struct property *prop;
@@ -557,7 +592,7 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
                }
        }
        for_all_prompts(sym, prop)
-               get_prompt_str(r, prop);
+               get_prompt_str(r, prop, head);
        hit = false;
        for_all_properties(sym, prop, P_SELECT) {
                if (!hit) {
@@ -577,14 +612,14 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
        str_append(r, "\n\n");
 }
 
-struct gstr get_relations_str(struct symbol **sym_arr)
+struct gstr get_relations_str(struct symbol **sym_arr, struct jk_head *head)
 {
        struct symbol *sym;
        struct gstr res = str_new();
        int i;
 
        for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
-               get_symbol_str(&res, sym);
+               get_symbol_str(&res, sym, head);
        if (!i)
                str_append(&res, _("No matches found.\n"));
        return res;
@@ -603,5 +638,5 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
        }
        str_printf(help, "%s\n", _(help_text));
        if (sym)
-               get_symbol_str(help, sym);
+               get_symbol_str(help, sym, NULL);
 }
index 1704a8562a5dc40ae09c23cd355958814b6976a8..87d4b15da951031896868789df7a992d21fcc73b 100644 (file)
@@ -721,7 +721,7 @@ again:
                dialog_input += strlen(CONFIG_);
 
        sym_arr = sym_re_search(dialog_input);
-       res = get_relations_str(sym_arr);
+       res = get_relations_str(sym_arr, NULL);
        free(sym_arr);
        show_scroll_win(main_window,
                        _("Search Results"), str_get(&res));
index 01e8a8e2260283d4551432406cb91d9b6e8e97cf..46e7aff80d1a8d1b2ea054d1febc0e8ce0404c35 100755 (executable)
@@ -6,6 +6,7 @@ use strict;
 ## Copyright (C) 2000, 1  Tim Waugh <twaugh@redhat.com>          ##
 ## Copyright (C) 2001  Simon Huggins                             ##
 ## Copyright (C) 2005-2012  Randy Dunlap                         ##
+## Copyright (C) 2012  Dan Luedtke                               ##
 ##                                                              ##
 ## #define enhancements by Armin Kuster <akuster@mvista.com>    ##
 ## Copyright (c) 2000 MontaVista Software, Inc.                         ##
@@ -35,6 +36,8 @@ use strict;
 #              Small fixes (like spaces vs. \s in regex)
 # -- Tim Jansen <tim@tjansen.de>
 
+# 25/07/2012 - Added support for HTML5
+# -- Dan Luedtke <mail@danrl.de>
 
 #
 # This will read a 'c' file and scan for embedded comments in the
@@ -44,12 +47,16 @@ use strict;
 # Note: This only supports 'c'.
 
 # usage:
-# kernel-doc [ -docbook | -html | -text | -man | -list ] [ -no-doc-sections ]
-#           [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
+# kernel-doc [ -docbook | -html | -html5 | -text | -man | -list ]
+#            [ -no-doc-sections ]
+#            [ -function funcname [ -function funcname ...] ]
+#            c file(s)s > outputfile
 # or
-#           [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
+#            [ -nofunction funcname [ -function funcname ...] ]
+#            c file(s)s > outputfile
 #
-#  Set output format using one of -docbook -html -text or -man.  Default is man.
+#  Set output format using one of -docbook -html -html5 -text or -man.
+#  Default is man.
 #  The -list format is for internal use by docproc.
 #
 #  -no-doc-sections
@@ -182,6 +189,14 @@ my $local_lt = "\\\\\\\\lt:";
 my $local_gt = "\\\\\\\\gt:";
 my $blankline_html = $local_lt . "p" . $local_gt;      # was "<p>"
 
+# html version 5
+my %highlights_html5 = ( $type_constant, "<span class=\"const\">\$1</span>",
+                       $type_func, "<span class=\"func\">\$1</span>",
+                       $type_struct_xml, "<span class=\"struct\">\$1</span>",
+                       $type_env, "<span class=\"env\">\$1</span>",
+                       $type_param, "<span class=\"param\">\$1</span>" );
+my $blankline_html5 = $local_lt . "br /" . $local_gt;
+
 # XML, docbook format
 my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
                        $type_constant, "<constant>\$1</constant>",
@@ -311,6 +326,10 @@ while ($ARGV[0] =~ m/^-(.*)/) {
        $output_mode = "html";
        %highlights = %highlights_html;
        $blankline = $blankline_html;
+    } elsif ($cmd eq "-html5") {
+       $output_mode = "html5";
+       %highlights = %highlights_html5;
+       $blankline = $blankline_html5;
     } elsif ($cmd eq "-man") {
        $output_mode = "man";
        %highlights = %highlights_man;
@@ -353,10 +372,11 @@ while ($ARGV[0] =~ m/^-(.*)/) {
 # continue execution near EOF;
 
 sub usage {
-    print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -list ]\n";
+    print "Usage: $0 [ -docbook | -html | -html5 | -text | -man | -list ]\n";
     print "         [ -no-doc-sections ]\n";
     print "         [ -function funcname [ -function funcname ...] ]\n";
     print "         [ -nofunction funcname [ -nofunction funcname ...] ]\n";
+    print "         [ -v ]\n";
     print "         c source file(s) > outputfile\n";
     print "         -v : verbose output, more warnings & other info listed\n";
     exit 1;
@@ -450,7 +470,8 @@ sub output_highlight {
 #      confess "output_highlight got called with no args?\n";
 #   }
 
-    if ($output_mode eq "html" || $output_mode eq "xml") {
+    if ($output_mode eq "html" || $output_mode eq "html5" ||
+       $output_mode eq "xml") {
        $contents = local_unescape($contents);
        # convert data read & converted thru xml_escape() into &xyz; format:
        $contents =~ s/\\\\\\/\&/g;
@@ -460,6 +481,11 @@ sub output_highlight {
     die $@ if $@;
 #   print STDERR "contents af:$contents\n";
 
+#   strip whitespaces when generating html5
+    if ($output_mode eq "html5") {
+       $contents =~ s/^\s+//;
+       $contents =~ s/\s+$//;
+    }
     foreach $line (split "\n", $contents) {
        if (! $output_preformatted) {
            $line =~ s/^\s*//;
@@ -480,7 +506,7 @@ sub output_highlight {
     }
 }
 
-#output sections in html
+# output sections in html
 sub output_section_html(%) {
     my %args = %{$_[0]};
     my $section;
@@ -640,6 +666,239 @@ sub output_blockhead_html(%) {
     print "<hr>\n";
 }
 
+# output sections in html5
+sub output_section_html5(%) {
+    my %args = %{$_[0]};
+    my $section;
+
+    foreach $section (@{$args{'sectionlist'}}) {
+       print "<section>\n";
+       print "<h1>$section</h1>\n";
+       print "<p>\n";
+       output_highlight($args{'sections'}{$section});
+       print "</p>\n";
+       print "</section>\n";
+    }
+}
+
+# output enum in html5
+sub output_enum_html5(%) {
+    my %args = %{$_[0]};
+    my ($parameter);
+    my $count;
+    my $html5id;
+
+    $html5id = $args{'enum'};
+    $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
+    print "<article class=\"enum\" id=\"enum:". $html5id . "\">";
+    print "<h1>enum " . $args{'enum'} . "</h1>\n";
+    print "<ol class=\"code\">\n";
+    print "<li>";
+    print "<span class=\"keyword\">enum</span> ";
+    print "<span class=\"identifier\">" . $args{'enum'} . "</span> {";
+    print "</li>\n";
+    $count = 0;
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       print "<li class=\"indent\">";
+       print "<span class=\"param\">" . $parameter . "</span>";
+       if ($count != $#{$args{'parameterlist'}}) {
+           $count++;
+           print ",";
+       }
+       print "</li>\n";
+    }
+    print "<li>};</li>\n";
+    print "</ol>\n";
+
+    print "<section>\n";
+    print "<h1>Constants</h1>\n";
+    print "<dl>\n";
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       print "<dt>" . $parameter . "</dt>\n";
+       print "<dd>";
+       output_highlight($args{'parameterdescs'}{$parameter});
+       print "</dd>\n";
+    }
+    print "</dl>\n";
+    print "</section>\n";
+    output_section_html5(@_);
+    print "</article>\n";
+}
+
+# output typedef in html5
+sub output_typedef_html5(%) {
+    my %args = %{$_[0]};
+    my ($parameter);
+    my $count;
+    my $html5id;
+
+    $html5id = $args{'typedef'};
+    $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
+    print "<article class=\"typedef\" id=\"typedef:" . $html5id . "\">\n";
+    print "<h1>typedef " . $args{'typedef'} . "</h1>\n";
+
+    print "<ol class=\"code\">\n";
+    print "<li>";
+    print "<span class=\"keyword\">typedef</span> ";
+    print "<span class=\"identifier\">" . $args{'typedef'} . "</span>";
+    print "</li>\n";
+    print "</ol>\n";
+    output_section_html5(@_);
+    print "</article>\n";
+}
+
+# output struct in html5
+sub output_struct_html5(%) {
+    my %args = %{$_[0]};
+    my ($parameter);
+    my $html5id;
+
+    $html5id = $args{'struct'};
+    $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
+    print "<article class=\"struct\" id=\"struct:" . $html5id . "\">\n";
+    print "<hgroup>\n";
+    print "<h1>" . $args{'type'} . " " . $args{'struct'} . "</h1>";
+    print "<h2>". $args{'purpose'} . "</h2>\n";
+    print "</hgroup>\n";
+    print "<ol class=\"code\">\n";
+    print "<li>";
+    print "<span class=\"type\">" . $args{'type'} . "</span> ";
+    print "<span class=\"identifier\">" . $args{'struct'} . "</span> {";
+    print "</li>\n";
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       print "<li class=\"indent\">";
+       if ($parameter =~ /^#/) {
+               print "<span class=\"param\">" . $parameter ."</span>\n";
+               print "</li>\n";
+               next;
+       }
+       my $parameter_name = $parameter;
+       $parameter_name =~ s/\[.*//;
+
+       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+       $type = $args{'parametertypes'}{$parameter};
+       if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+           # pointer-to-function
+           print "<span class=\"type\">$1</span> ";
+           print "<span class=\"param\">$parameter</span>";
+           print "<span class=\"type\">)</span> ";
+           print "(<span class=\"args\">$2</span>);";
+       } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
+           # bitfield
+           print "<span class=\"type\">$1</span> ";
+           print "<span class=\"param\">$parameter</span>";
+           print "<span class=\"bits\">$2</span>;";
+       } else {
+           print "<span class=\"type\">$type</span> ";
+           print "<span class=\"param\">$parameter</span>;";
+       }
+       print "</li>\n";
+    }
+    print "<li>};</li>\n";
+    print "</ol>\n";
+
+    print "<section>\n";
+    print "<h1>Members</h1>\n";
+    print "<dl>\n";
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       ($parameter =~ /^#/) && next;
+
+       my $parameter_name = $parameter;
+       $parameter_name =~ s/\[.*//;
+
+       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+       print "<dt>" . $parameter . "</dt>\n";
+       print "<dd>";
+       output_highlight($args{'parameterdescs'}{$parameter_name});
+       print "</dd>\n";
+    }
+    print "</dl>\n";
+    print "</section>\n";
+    output_section_html5(@_);
+    print "</article>\n";
+}
+
+# output function in html5
+sub output_function_html5(%) {
+    my %args = %{$_[0]};
+    my ($parameter, $section);
+    my $count;
+    my $html5id;
+
+    $html5id = $args{'function'};
+    $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
+    print "<article class=\"function\" id=\"func:". $html5id . "\">\n";
+    print "<hgroup>\n";
+    print "<h1>" . $args{'function'} . "</h1>";
+    print "<h2>" . $args{'purpose'} . "</h2>\n";
+    print "</hgroup>\n";
+    print "<ol class=\"code\">\n";
+    print "<li>";
+    print "<span class=\"type\">" . $args{'functiontype'} . "</span> ";
+    print "<span class=\"identifier\">" . $args{'function'} . "</span> (";
+    print "</li>";
+    $count = 0;
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       print "<li class=\"indent\">";
+       $type = $args{'parametertypes'}{$parameter};
+       if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+           # pointer-to-function
+           print "<span class=\"type\">$1</span> ";
+           print "<span class=\"param\">$parameter</span>";
+           print "<span class=\"type\">)</span> ";
+           print "(<span class=\"args\">$2</span>)";
+       } else {
+           print "<span class=\"type\">$type</span> ";
+           print "<span class=\"param\">$parameter</span>";
+       }
+       if ($count != $#{$args{'parameterlist'}}) {
+           $count++;
+           print ",";
+       }
+       print "</li>\n";
+    }
+    print "<li>)</li>\n";
+    print "</ol>\n";
+
+    print "<section>\n";
+    print "<h1>Arguments</h1>\n";
+    print "<p>\n";
+    print "<dl>\n";
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       my $parameter_name = $parameter;
+       $parameter_name =~ s/\[.*//;
+
+       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+       print "<dt>" . $parameter . "</dt>\n";
+       print "<dd>";
+       output_highlight($args{'parameterdescs'}{$parameter_name});
+       print "</dd>\n";
+    }
+    print "</dl>\n";
+    print "</section>\n";
+    output_section_html5(@_);
+    print "</article>\n";
+}
+
+# output DOC: block header in html5
+sub output_blockhead_html5(%) {
+    my %args = %{$_[0]};
+    my ($parameter, $section);
+    my $count;
+    my $html5id;
+
+    foreach $section (@{$args{'sectionlist'}}) {
+       $html5id = $section;
+       $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
+       print "<article class=\"doc\" id=\"doc:". $html5id . "\">\n";
+       print "<h1>$section</h1>\n";
+       print "<p>\n";
+       output_highlight($args{'sections'}{$section});
+       print "</p>\n";
+    }
+    print "</article>\n";
+}
+
 sub output_section_xml(%) {
     my %args = %{$_[0]};
     my $section;
index 00f7512a217f390ae0673e83fedc76750f0fa22c..0d93856a03f4be18a80d85c1c119e362ebd0aa5c 100644 (file)
@@ -821,6 +821,7 @@ static const char *section_white_list[] =
        ".debug*",
        ".zdebug*",             /* Compressed debug sections. */
        ".GCC-command-line",    /* mn10300 */
+       ".GCC.command.line",    /* record-gcc-switches, non mn10300 */
        ".mdebug*",        /* alpha, score, mips etc. */
        ".pdr",            /* alpha, score, mips etc. */
        ".stab*",
index d0d748e72915b2e3217d493c08359739fb6fbf64..62d8234f87876c30f3c78138db7edbeb0685f8c5 100644 (file)
@@ -28,15 +28,15 @@ case "${1}" in
                file_ext=""
                ;;
        targz-pkg)
-               compress="gzip -c9"
+               compress="gzip"
                file_ext=".gz"
                ;;
        tarbz2-pkg)
-               compress="bzip2 -c9"
+               compress="bzip2"
                file_ext=".bz2"
                ;;
        tarxz-pkg)
-               compress="xz -c9"
+               compress="xz"
                file_ext=".xz"
                ;;
        *)
index cff8faad73d15dab529f71943e5c5544b2ad9217..79fdafb0d26325acb65d8e2b31f814770b826a07 100755 (executable)
@@ -154,7 +154,9 @@ exuberant()
        --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/'  \
        --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \
        --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \
-       --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'
+       --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'                \
+       --regex-c='/PCI_OP_READ\(([a-z]*[a-z]).*[1-4]\)/pci_bus_read_config_\1/' \
+       --regex-c='/PCI_OP_WRITE\(([a-z]*[a-z]).*[1-4]\)/pci_bus_write_config_\1/'
 
        all_kconfigs | xargs $1 -a                              \
        --langdef=kconfig --language-force=kconfig              \
@@ -197,7 +199,9 @@ emacs()
        --regex='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \
        --regex='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \
        --regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \
-       --regex='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'
+       --regex='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'            \
+       --regex='/PCI_OP_READ\(([a-z]*[a-z]).*[1-4]\)/pci_bus_read_config_\1/' \
+       --regex='/PCI_OP_WRITE\(([a-z]*[a-z]).*[1-4]\)/pci_bus_write_config_\1/'
 
        all_kconfigs | xargs $1 -a                              \
        --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/'
index a40aac677c722b15dd30b89cc57c518d8764b020..b14a30c234b885199fd6f8dac080a343255a7d1f 100644 (file)
@@ -74,8 +74,8 @@ static int cap_sb_statfs(struct dentry *dentry)
        return 0;
 }
 
-static int cap_sb_mount(char *dev_name, struct path *path, char *type,
-                       unsigned long flags, void *data)
+static int cap_sb_mount(const char *dev_name, struct path *path,
+                       const char *type, unsigned long flags, void *data)
 {
        return 0;
 }
index 3724029d0f6dd4407a46ff7e4fff23e05f47d445..8dcd4ae10a5fba06086ed31998c78c77ec32469c 100644 (file)
@@ -276,8 +276,8 @@ int security_sb_statfs(struct dentry *dentry)
        return security_ops->sb_statfs(dentry);
 }
 
-int security_sb_mount(char *dev_name, struct path *path,
-                       char *type, unsigned long flags, void *data)
+int security_sb_mount(const char *dev_name, struct path *path,
+                       const char *type, unsigned long flags, void *data)
 {
        return security_ops->sb_mount(dev_name, path, type, flags, data);
 }
index 651d8456611a87c4a8b77141574a81b992b80f53..24ab4148547c2ba925042126ca9350a25a9969f8 100644 (file)
@@ -2452,9 +2452,9 @@ static int selinux_sb_statfs(struct dentry *dentry)
        return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
 }
 
-static int selinux_mount(char *dev_name,
+static int selinux_mount(const char *dev_name,
                         struct path *path,
-                        char *type,
+                        const char *type,
                         unsigned long flags,
                         void *data)
 {
index 2874c73167831f6f72cdb8aefffbf29c3aa0f7a2..38be92ce901eb8bd32ce756b502979f41eb1d75c 100644 (file)
@@ -408,8 +408,8 @@ static int smack_sb_statfs(struct dentry *dentry)
  * Returns 0 if current can write the floor of the filesystem
  * being mounted on, an error code otherwise.
  */
-static int smack_sb_mount(char *dev_name, struct path *path,
-                         char *type, unsigned long flags, void *data)
+static int smack_sb_mount(const char *dev_name, struct path *path,
+                         const char *type, unsigned long flags, void *data)
 {
        struct superblock_smack *sbp = path->dentry->d_sb->s_security;
        struct smk_audit_info ad;
index af010b62d544207dd93502a4dd66179684dbc7e5..d4f166bc35085f9c83efd640ebdbc010740fb38f 100644 (file)
@@ -970,7 +970,7 @@ int tomoyo_init_request_info(struct tomoyo_request_info *r,
                             const u8 index);
 int tomoyo_mkdev_perm(const u8 operation, struct path *path,
                      const unsigned int mode, unsigned int dev);
-int tomoyo_mount_permission(char *dev_name, struct path *path,
+int tomoyo_mount_permission(const char *dev_name, struct path *path,
                            const char *type, unsigned long flags,
                            void *data_page);
 int tomoyo_open_control(const u8 type, struct file *file);
index fe00cdfd026775b5b3d1c2f32154288cef5a2c17..390c646013cb290df2fa61728b79fef56ab31019 100644 (file)
@@ -71,7 +71,8 @@ static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r,
  *
  * Caller holds tomoyo_read_lock().
  */
-static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
+static int tomoyo_mount_acl(struct tomoyo_request_info *r,
+                           const char *dev_name,
                            struct path *dir, const char *type,
                            unsigned long flags)
 {
@@ -183,7 +184,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
  *
  * Returns 0 on success, negative value otherwise.
  */
-int tomoyo_mount_permission(char *dev_name, struct path *path,
+int tomoyo_mount_permission(const char *dev_name, struct path *path,
                            const char *type, unsigned long flags,
                            void *data_page)
 {
index d88eb3a046ed87fed289a4689e74aab68e969e2f..a2ee362546ab8804cc6d098c8c03c8f7fab55069 100644 (file)
@@ -408,8 +408,8 @@ static int tomoyo_path_chroot(struct path *path)
  *
  * Returns 0 on success, negative value otherwise.
  */
-static int tomoyo_sb_mount(char *dev_name, struct path *path,
-                          char *type, unsigned long flags, void *data)
+static int tomoyo_sb_mount(const char *dev_name, struct path *path,
+                          const char *type, unsigned long flags, void *data)
 {
        return tomoyo_mount_permission(dev_name, path, type, flags, data);
 }
index 24c430f721d4b07f0aed96eaa2713271273c5e8b..672af8b56542ddf8e04639dca07959dcb1d1ac79 100644 (file)
@@ -1482,9 +1482,9 @@ vnc_mute_spkr(wavnc_info *devc)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&nw_gpio_lock, flags);
+       raw_spin_lock_irqsave(&nw_gpio_lock, flags);
        nw_cpld_modify(CPLD_UNMUTE, devc->spkr_mute_state ? 0 : CPLD_UNMUTE);
-       spin_unlock_irqrestore(&nw_gpio_lock, flags);
+       raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
 }
 
 static void
index c0ab72cbeed1288da505468e27e42b3dca984b3f..70d4848b5cd0ad25ce272877f9c759ed010dfc58 100644 (file)
@@ -5168,6 +5168,8 @@ EXPORT_SYMBOL_HDA(snd_hda_resume);
  */
 void *snd_array_new(struct snd_array *array)
 {
+       if (snd_BUG_ON(!array->elem_size))
+               return NULL;
        if (array->used >= array->alloced) {
                int num = array->alloced + array->alloc_align;
                int size = (num + 1) * array->elem_size;
index f09ff6c14041794bbd3d56e5d59a17410dddf037..6833835a218b9f581a58c5c0b3fe6aa36d8df51d 100644 (file)
@@ -554,7 +554,6 @@ enum {
 #define AZX_DCAPS_BUFSIZE      (1 << 21)       /* no buffer size alignment */
 #define AZX_DCAPS_ALIGN_BUFSIZE        (1 << 22)       /* buffer size alignment */
 #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23)   /* BDLE in 4k boundary */
-#define AZX_DCAPS_POSFIX_COMBO  (1 << 24)      /* Use COMBO as default */
 #define AZX_DCAPS_COUNT_LPIB_DELAY  (1 << 25)  /* Take LPIB as delay */
 
 /* quirks for ATI SB / AMD Hudson */
@@ -2858,10 +2857,6 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
                snd_printd(SFX "Using LPIB position fix\n");
                return POS_FIX_LPIB;
        }
-       if (chip->driver_caps & AZX_DCAPS_POSFIX_COMBO) {
-               snd_printd(SFX "Using COMBO position fix\n");
-               return POS_FIX_COMBO;
-       }
        return POS_FIX_AUTO;
 }
 
index fcfc9f0a056b82fcbe9b7deafbef3b2c9516f6c4..61a71131711c734556249b17fc61fc51f1218c1a 100644 (file)
@@ -897,7 +897,7 @@ static int build_digital_input(struct hda_codec *codec)
  * HP/SPK/SPDIF
  */
 
-static void cs_automute(struct hda_codec *codec)
+static void cs_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl)
 {
        struct cs_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
@@ -973,7 +973,7 @@ static void cs_automute(struct hda_codec *codec)
  * Switch max 3 inputs of a single ADC (nid 3)
 */
 
-static void cs_automic(struct hda_codec *codec)
+static void cs_automic(struct hda_codec *codec, struct hda_jack_tbl *tbl)
 {
        struct cs_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
@@ -1035,7 +1035,7 @@ static void init_output(struct hda_codec *codec)
                if (!cfg->speaker_outs)
                        continue;
                if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
-                       snd_hda_jack_detect_enable(codec, nid, HP_EVENT);
+                       snd_hda_jack_detect_enable_callback(codec, nid, HP_EVENT, cs_automute);
                        spec->hp_detect = 1;
                }
        }
@@ -1046,7 +1046,7 @@ static void init_output(struct hda_codec *codec)
 
        /* SPDIF is enabled on presence detect for CS421x */
        if (spec->hp_detect || spec->spdif_detect)
-               cs_automute(codec);
+               cs_automute(codec, NULL);
 }
 
 static void init_input(struct hda_codec *codec)
@@ -1070,13 +1070,13 @@ static void init_input(struct hda_codec *codec)
                                    AC_VERB_SET_AMP_GAIN_MUTE,
                                    AMP_IN_MUTE(spec->adc_idx[i]));
                if (spec->mic_detect && spec->automic_idx == i)
-                       snd_hda_jack_detect_enable(codec, pin, MIC_EVENT);
+                       snd_hda_jack_detect_enable_callback(codec, pin, MIC_EVENT, cs_automic);
        }
        /* CS420x has multiple ADC, CS421x has single ADC */
        if (spec->vendor_nid == CS420X_VENDOR_NID) {
                change_cur_input(codec, spec->cur_input, 1);
                if (spec->mic_detect)
-                       cs_automic(codec);
+                       cs_automic(codec, NULL);
 
                coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */
                if (is_active_pin(codec, CS_DMIC2_PIN_NID))
@@ -1089,7 +1089,7 @@ static void init_input(struct hda_codec *codec)
                cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
        } else {
                if (spec->mic_detect)
-                       cs_automic(codec);
+                       cs_automic(codec, NULL);
                else  {
                        spec->cur_adc = spec->adc_nid[spec->cur_input];
                        cs_update_input_select(codec);
@@ -1243,28 +1243,16 @@ static void cs_free(struct hda_codec *codec)
        struct cs_spec *spec = codec->spec;
        kfree(spec->capture_bind[0]);
        kfree(spec->capture_bind[1]);
+       snd_hda_gen_free(&spec->gen);
        kfree(codec->spec);
 }
 
-static void cs_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-       switch (snd_hda_jack_get_action(codec, res >> 26)) {
-       case HP_EVENT:
-               cs_automute(codec);
-               break;
-       case MIC_EVENT:
-               cs_automic(codec);
-               break;
-       }
-       snd_hda_jack_report_sync(codec);
-}
-
 static const struct hda_codec_ops cs_patch_ops = {
        .build_controls = cs_build_controls,
        .build_pcms = cs_build_pcms,
        .init = cs_init,
        .free = cs_free,
-       .unsol_event = cs_unsol_event,
+       .unsol_event = snd_hda_jack_unsol_event,
 };
 
 static int cs_parse_auto_config(struct hda_codec *codec)
@@ -1439,6 +1427,7 @@ static int patch_cs420x(struct hda_codec *codec)
        if (!spec)
                return -ENOMEM;
        codec->spec = spec;
+       snd_hda_gen_init(&spec->gen);
 
        spec->vendor_nid = CS420X_VENDOR_NID;
 
@@ -1457,7 +1446,7 @@ static int patch_cs420x(struct hda_codec *codec)
        return 0;
 
  error:
-       kfree(codec->spec);
+       cs_free(codec);
        codec->spec = NULL;
        return err;
 }
@@ -1674,7 +1663,7 @@ static void init_cs421x_digital(struct hda_codec *codec)
                if (!cfg->speaker_outs)
                        continue;
                if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
-                       snd_hda_jack_detect_enable(codec, nid, SPDIF_EVENT);
+                       snd_hda_jack_detect_enable_callback(codec, nid, SPDIF_EVENT, cs_automute);
                        spec->spdif_detect = 1;
                }
        }
@@ -1889,21 +1878,6 @@ static int cs421x_build_controls(struct hda_codec *codec)
        return 0;
 }
 
-static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-       switch (snd_hda_jack_get_action(codec, res >> 26)) {
-       case HP_EVENT:
-       case SPDIF_EVENT:
-               cs_automute(codec);
-               break;
-
-       case MIC_EVENT:
-               cs_automic(codec);
-               break;
-       }
-       snd_hda_jack_report_sync(codec);
-}
-
 static int parse_cs421x_input(struct hda_codec *codec)
 {
        struct cs_spec *spec = codec->spec;
@@ -1977,7 +1951,7 @@ static struct hda_codec_ops cs421x_patch_ops = {
        .build_pcms = cs_build_pcms,
        .init = cs421x_init,
        .free = cs_free,
-       .unsol_event = cs421x_unsol_event,
+       .unsol_event = snd_hda_jack_unsol_event,
 #ifdef CONFIG_PM
        .suspend = cs421x_suspend,
 #endif
@@ -1992,6 +1966,7 @@ static int patch_cs4210(struct hda_codec *codec)
        if (!spec)
                return -ENOMEM;
        codec->spec = spec;
+       snd_hda_gen_init(&spec->gen);
 
        spec->vendor_nid = CS4210_VENDOR_NID;
 
@@ -2017,7 +1992,7 @@ static int patch_cs4210(struct hda_codec *codec)
        return 0;
 
  error:
-       kfree(codec->spec);
+       cs_free(codec);
        codec->spec = NULL;
        return err;
 }
@@ -2031,6 +2006,7 @@ static int patch_cs4213(struct hda_codec *codec)
        if (!spec)
                return -ENOMEM;
        codec->spec = spec;
+       snd_hda_gen_init(&spec->gen);
 
        spec->vendor_nid = CS4213_VENDOR_NID;
 
@@ -2042,7 +2018,7 @@ static int patch_cs4213(struct hda_codec *codec)
        return 0;
 
  error:
-       kfree(codec->spec);
+       cs_free(codec);
        codec->spec = NULL;
        return err;
 }
index 8568aee56e2daaef1c77a8d19df4227af57eccc3..8253b4eeb6a1bea0687675e8ac66ca41b9a84758 100644 (file)
@@ -611,6 +611,8 @@ static void alc_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack
 {
        struct alc_spec *spec = codec->spec;
 
+       if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
+               return;
        /* check LO jack only when it's different from HP */
        if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
                return;
@@ -4245,6 +4247,7 @@ static void alc_auto_init_std(struct hda_codec *codec)
        ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
 
 static const struct snd_pci_quirk beep_white_list[] = {
+       SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1),
        SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
        SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
        SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
index fe163547f906cae4f6d1d1ea88ee7a7a1b599951..770013ff556f6be0500b14039a8e60df2fa74b2a 100644 (file)
@@ -104,6 +104,7 @@ enum {
        STAC_92HD83XXX_HP_LED,
        STAC_92HD83XXX_HP_INV_LED,
        STAC_92HD83XXX_HP_MIC_LED,
+       STAC_92HD83XXX_HEADSET_JACK,
        STAC_92HD83XXX_MODELS
 };
 
@@ -204,6 +205,7 @@ struct sigmatel_spec {
        unsigned int check_volume_offset:1;
        unsigned int auto_mic:1;
        unsigned int linear_tone_beep:1;
+       unsigned int headset_jack:1; /* 4-pin headset jack (hp + mono mic) */
 
        /* gpio lines */
        unsigned int eapd_mask;
@@ -1684,6 +1686,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
        [STAC_92HD83XXX_HP_LED] = "hp-led",
        [STAC_92HD83XXX_HP_INV_LED] = "hp-inv-led",
        [STAC_92HD83XXX_HP_MIC_LED] = "hp-mic-led",
+       [STAC_92HD83XXX_HEADSET_JACK] = "headset-jack",
 };
 
 static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
@@ -1694,6 +1697,24 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
                      "DFI LanParty", STAC_92HD83XXX_REF),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
                      "unknown Dell", STAC_DELL_S14),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0532,
+                     "Dell Latitude E6230", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0533,
+                     "Dell Latitude E6330", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0534,
+                     "Dell Latitude E6430", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0535,
+                     "Dell Latitude E6530", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x053c,
+                     "Dell Latitude E5430", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x053d,
+                     "Dell Latitude E5530", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0549,
+                     "Dell Latitude E5430", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x057d,
+                     "Dell Latitude E6430s", STAC_92HD83XXX_HEADSET_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0584,
+                     "Dell Latitude E6430U", STAC_92HD83XXX_HEADSET_JACK),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x1028,
                      "Dell Vostro 3500", STAC_DELL_VOSTRO_3500),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656,
@@ -2855,6 +2876,9 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec,
        char name[22];
 
        if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) {
+               if (spec->headset_jack && snd_hda_get_input_pin_attr(def_conf)
+                       != INPUT_PIN_ATTR_DOCK)
+                       return 0;
                if (snd_hda_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD
                        && nid == spec->line_switch)
                        control = STAC_CTL_WIDGET_IO_SWITCH;
@@ -5626,6 +5650,9 @@ again:
        case STAC_92HD83XXX_HP_MIC_LED:
                spec->mic_mute_led_gpio = 0x08; /* GPIO3 */
                break;
+       case STAC_92HD83XXX_HEADSET_JACK:
+               spec->headset_jack = 1;
+               break;
        }
 
        if (find_mute_led_cfg(codec, default_polarity))
index 5a45a912aedcc22ef543a57229fcfa26880c51b7..72a2f60b087c8ba066b52e5aaf4cda500227471f 100644 (file)
@@ -118,6 +118,8 @@ enum {
 };
 
 struct via_spec {
+       struct hda_gen_spec gen;
+
        /* codec parameterization */
        const struct snd_kcontrol_new *mixers[6];
        unsigned int num_mixers;
@@ -246,6 +248,7 @@ static struct via_spec * via_new_spec(struct hda_codec *codec)
        /* VT1708BCE & VT1708S are almost same */
        if (spec->codec_type == VT1708BCE)
                spec->codec_type = VT1708S;
+       snd_hda_gen_init(&spec->gen);
        return spec;
 }
 
@@ -299,7 +302,6 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
 
 #define VIA_JACK_EVENT         0x20
 #define VIA_HP_EVENT           0x01
-#define VIA_GPIO_EVENT         0x02
 #define VIA_LINE_EVENT         0x03
 
 enum {
@@ -1628,6 +1630,7 @@ static void via_free(struct hda_codec *codec)
        vt1708_stop_hp_work(spec);
        kfree(spec->bind_cap_vol);
        kfree(spec->bind_cap_sw);
+       snd_hda_gen_free(&spec->gen);
        kfree(spec);
 }
 
@@ -1685,69 +1688,6 @@ static void via_hp_automute(struct hda_codec *codec)
        via_line_automute(codec, present);
 }
 
-static void via_gpio_control(struct hda_codec *codec)
-{
-       unsigned int gpio_data;
-       unsigned int vol_counter;
-       unsigned int vol;
-       unsigned int master_vol;
-
-       struct via_spec *spec = codec->spec;
-
-       gpio_data = snd_hda_codec_read(codec, codec->afg, 0,
-                                      AC_VERB_GET_GPIO_DATA, 0) & 0x03;
-
-       vol_counter = (snd_hda_codec_read(codec, codec->afg, 0,
-                                         0xF84, 0) & 0x3F0000) >> 16;
-
-       vol = vol_counter & 0x1F;
-       master_vol = snd_hda_codec_read(codec, 0x1A, 0,
-                                       AC_VERB_GET_AMP_GAIN_MUTE,
-                                       AC_AMP_GET_INPUT);
-
-       if (gpio_data == 0x02) {
-               /* unmute line out */
-               snd_hda_set_pin_ctl(codec, spec->autocfg.line_out_pins[0],
-                                   PIN_OUT);
-               if (vol_counter & 0x20) {
-                       /* decrease volume */
-                       if (vol > master_vol)
-                               vol = master_vol;
-                       snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT,
-                                                0, HDA_AMP_VOLMASK,
-                                                master_vol-vol);
-               } else {
-                       /* increase volume */
-                       snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT, 0,
-                                        HDA_AMP_VOLMASK,
-                                        ((master_vol+vol) > 0x2A) ? 0x2A :
-                                         (master_vol+vol));
-               }
-       } else if (!(gpio_data & 0x02)) {
-               /* mute line out */
-               snd_hda_set_pin_ctl(codec, spec->autocfg.line_out_pins[0], 0);
-       }
-}
-
-/* unsolicited event for jack sensing */
-static void via_unsol_event(struct hda_codec *codec,
-                                 unsigned int res)
-{
-       res >>= 26;
-       res = snd_hda_jack_get_action(codec, res);
-
-       if (res & VIA_JACK_EVENT)
-               set_widgets_power_state(codec);
-
-       res &= ~VIA_JACK_EVENT;
-
-       if (res == VIA_HP_EVENT || res == VIA_LINE_EVENT)
-               via_hp_automute(codec);
-       else if (res == VIA_GPIO_EVENT)
-               via_gpio_control(codec);
-       snd_hda_jack_report_sync(codec);
-}
-
 #ifdef CONFIG_PM
 static int via_suspend(struct hda_codec *codec)
 {
@@ -1783,7 +1723,7 @@ static const struct hda_codec_ops via_patch_ops = {
        .build_pcms = via_build_pcms,
        .init = via_init,
        .free = via_free,
-       .unsol_event = via_unsol_event,
+       .unsol_event = snd_hda_jack_unsol_event,
 #ifdef CONFIG_PM
        .suspend = via_suspend,
        .check_power_status = via_check_power_status,
@@ -2761,6 +2701,17 @@ static void via_auto_init_dig_in(struct hda_codec *codec)
        snd_hda_set_pin_ctl(codec, spec->autocfg.dig_in_pin, PIN_IN);
 }
 
+static void via_jack_output_event(struct hda_codec *codec, struct hda_jack_tbl *tbl)
+{
+       set_widgets_power_state(codec);
+       via_hp_automute(codec);
+}
+
+static void via_jack_powerstate_event(struct hda_codec *codec, struct hda_jack_tbl *tbl)
+{
+       set_widgets_power_state(codec);
+}
+
 /* initialize the unsolicited events */
 static void via_auto_init_unsol_event(struct hda_codec *codec)
 {
@@ -2768,26 +2719,31 @@ static void via_auto_init_unsol_event(struct hda_codec *codec)
        struct auto_pin_cfg *cfg = &spec->autocfg;
        unsigned int ev;
        int i;
+       hda_jack_callback cb;
 
        if (cfg->hp_pins[0] && is_jack_detectable(codec, cfg->hp_pins[0]))
-               snd_hda_jack_detect_enable(codec, cfg->hp_pins[0],
-                                          VIA_HP_EVENT | VIA_JACK_EVENT);
+               snd_hda_jack_detect_enable_callback(codec, cfg->hp_pins[0],
+                                                   VIA_HP_EVENT | VIA_JACK_EVENT,
+                                                   via_jack_output_event);
 
        if (cfg->speaker_pins[0])
                ev = VIA_LINE_EVENT;
        else
                ev = 0;
+       cb = ev ? via_jack_output_event : via_jack_powerstate_event;
+
        for (i = 0; i < cfg->line_outs; i++) {
                if (cfg->line_out_pins[i] &&
                    is_jack_detectable(codec, cfg->line_out_pins[i]))
-                       snd_hda_jack_detect_enable(codec, cfg->line_out_pins[i],
-                                                  ev | VIA_JACK_EVENT);
+                       snd_hda_jack_detect_enable_callback(codec, cfg->line_out_pins[i],
+                                                           ev | VIA_JACK_EVENT, cb);
        }
 
        for (i = 0; i < cfg->num_inputs; i++) {
                if (is_jack_detectable(codec, cfg->inputs[i].pin))
-                       snd_hda_jack_detect_enable(codec, cfg->inputs[i].pin,
-                                                  VIA_JACK_EVENT);
+                       snd_hda_jack_detect_enable_callback(codec, cfg->inputs[i].pin,
+                                                           VIA_JACK_EVENT,
+                                                           via_jack_powerstate_event);
        }
 }
 
index d73ac9bc427298f0f35ddf3cea7245b201f55709..88d8cebbb244ade66eb43db91be9d9b5cf9669d5 100644 (file)
@@ -2780,6 +2780,52 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 
        }
 },
+{
+       /* Tascam US122 MKII - playback-only support */
+       .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor = 0x0644,
+       .idProduct = 0x8021,
+       .bInterfaceClass = USB_CLASS_AUDIO,
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .vendor_name = "TASCAM",
+               .product_name = "US122 MKII",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 2,
+                                       .iface = 1,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+                                       .endpoint = 0x02,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC,
+                                       .rates = SNDRV_PCM_RATE_44100 |
+                                                SNDRV_PCM_RATE_48000 |
+                                                SNDRV_PCM_RATE_88200 |
+                                                SNDRV_PCM_RATE_96000,
+                                       .rate_min = 44100,
+                                       .rate_max = 96000,
+                                       .nr_rates = 4,
+                                       .rate_table = (unsigned int[]) {
+                                               44100, 48000, 88200, 96000
+                                       }
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 
 /* Microsoft XboxLive Headset/Xbox Communicator */
 {
index 86258c2a2c23d94a8714e327a771b20f00a8461f..247264502fb799cd3bddb9e43b003aad3ed45417 100644 (file)
@@ -45,6 +45,8 @@ include config/utilities.mak
 #
 # Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf
 # backtrace post unwind.
+#
+# Define NO_BACKTRACE if you do not want stack backtrace debug feature
 
 $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
        @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
@@ -185,7 +187,7 @@ strip-libs = $(filter-out -l%,$(1))
 PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
 PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py
 
-$(OUTPUT)python/perf.so: $(PYRF_OBJS) $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
+$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
        $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
          --quiet build_ext; \
        mkdir -p $(OUTPUT)python && \
@@ -268,6 +270,7 @@ LIB_H += util/include/linux/magic.h
 LIB_H += util/include/linux/poison.h
 LIB_H += util/include/linux/prefetch.h
 LIB_H += util/include/linux/rbtree.h
+LIB_H += util/include/linux/rbtree_augmented.h
 LIB_H += util/include/linux/string.h
 LIB_H += util/include/linux/types.h
 LIB_H += util/include/linux/linkage.h
@@ -446,20 +449,6 @@ BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
 
 PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT)
 
-# Files needed for the python binding, perf.so
-# pyrf is just an internal name needed for all those wrappers.
-# This has to be in sync with what is in the 'sources' variable in
-# tools/perf/util/setup.py
-
-PYRF_OBJS += $(OUTPUT)util/cpumap.o
-PYRF_OBJS += $(OUTPUT)util/ctype.o
-PYRF_OBJS += $(OUTPUT)util/evlist.o
-PYRF_OBJS += $(OUTPUT)util/evsel.o
-PYRF_OBJS += $(OUTPUT)util/python.o
-PYRF_OBJS += $(OUTPUT)util/thread_map.o
-PYRF_OBJS += $(OUTPUT)util/util.o
-PYRF_OBJS += $(OUTPUT)util/xyarray.o
-
 #
 # Platform specific tweaks
 #
@@ -486,7 +475,13 @@ ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
                NO_DWARF := 1
                NO_DEMANGLE := 1
        endif
-endif
+else
+       FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
+       ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y)
+               msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
+               NO_DWARF := 1
+       endif # Dwarf support
+endif # SOURCE_LIBELF
 endif # NO_LIBELF
 
 ifndef NO_LIBUNWIND
@@ -511,8 +506,6 @@ ifneq ($(OUTPUT),)
 endif
 
 ifdef NO_LIBELF
-BASIC_CFLAGS += -DNO_LIBELF_SUPPORT
-
 EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
 
 # Remove ELF/DWARF dependent codes
@@ -527,17 +520,12 @@ BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
 LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
 
 else # NO_LIBELF
+BASIC_CFLAGS += -DLIBELF_SUPPORT
 
-ifneq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y)
-       BASIC_CFLAGS += -DLIBELF_NO_MMAP
+ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y)
+       BASIC_CFLAGS += -DLIBELF_MMAP
 endif
 
-FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
-ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y)
-       msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
-       NO_DWARF := 1
-endif # Dwarf support
-
 ifndef NO_DWARF
 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
        msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
@@ -550,38 +538,33 @@ endif # PERF_HAVE_DWARF_REGS
 endif # NO_DWARF
 endif # NO_LIBELF
 
-ifdef NO_LIBUNWIND
-       BASIC_CFLAGS += -DNO_LIBUNWIND_SUPPORT
-else
+ifndef NO_LIBUNWIND
+       BASIC_CFLAGS += -DLIBUNWIND_SUPPORT
        EXTLIBS += $(LIBUNWIND_LIBS)
        BASIC_CFLAGS := $(LIBUNWIND_CFLAGS) $(BASIC_CFLAGS)
        BASIC_LDFLAGS := $(LIBUNWIND_LDFLAGS) $(BASIC_LDFLAGS)
        LIB_OBJS += $(OUTPUT)util/unwind.o
 endif
 
-ifdef NO_LIBAUDIT
-       BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT
-else
+ifndef NO_LIBAUDIT
        FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit
        ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT)),y)
                msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev);
-               BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT
        else
+               BASIC_CFLAGS += -DLIBAUDIT_SUPPORT
                BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
                EXTLIBS += -laudit
        endif
 endif
 
-ifdef NO_NEWT
-       BASIC_CFLAGS += -DNO_NEWT_SUPPORT
-else
+ifndef NO_NEWT
        FLAGS_NEWT=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lnewt
        ifneq ($(call try-cc,$(SOURCE_NEWT),$(FLAGS_NEWT)),y)
                msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev);
-               BASIC_CFLAGS += -DNO_NEWT_SUPPORT
        else
                # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
                BASIC_CFLAGS += -I/usr/include/slang
+               BASIC_CFLAGS += -DNEWT_SUPPORT
                EXTLIBS += -lnewt -lslang
                LIB_OBJS += $(OUTPUT)ui/setup.o
                LIB_OBJS += $(OUTPUT)ui/browser.o
@@ -603,17 +586,15 @@ else
        endif
 endif
 
-ifdef NO_GTK2
-       BASIC_CFLAGS += -DNO_GTK2_SUPPORT
-else
+ifndef NO_GTK2
        FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
        ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2)),y)
                msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
-               BASIC_CFLAGS += -DNO_GTK2_SUPPORT
        else
                ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y)
                        BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR
                endif
+               BASIC_CFLAGS += -DGTK2_SUPPORT
                BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null)
                EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null)
                LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
@@ -621,7 +602,7 @@ else
                LIB_OBJS += $(OUTPUT)ui/gtk/util.o
                LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
                # Make sure that it'd be included only once.
-               ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),)
+               ifeq ($(findstring -DNEWT_SUPPORT,$(BASIC_CFLAGS)),)
                        LIB_OBJS += $(OUTPUT)ui/setup.o
                        LIB_OBJS += $(OUTPUT)ui/util.o
                endif
@@ -762,23 +743,18 @@ ifeq ($(NO_PERF_REGS),0)
        ifeq ($(ARCH),x86)
                LIB_H += arch/x86/include/perf_regs.h
        endif
-else
-       BASIC_CFLAGS += -DNO_PERF_REGS
+       BASIC_CFLAGS += -DHAVE_PERF_REGS
 endif
 
-ifdef NO_STRLCPY
-       BASIC_CFLAGS += -DNO_STRLCPY
-else
-       ifneq ($(call try-cc,$(SOURCE_STRLCPY),),y)
-               BASIC_CFLAGS += -DNO_STRLCPY
+ifndef NO_STRLCPY
+       ifeq ($(call try-cc,$(SOURCE_STRLCPY),),y)
+               BASIC_CFLAGS += -DHAVE_STRLCPY
        endif
 endif
 
-ifdef NO_BACKTRACE
-       BASIC_CFLAGS += -DNO_BACKTRACE
-else
-       ifneq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
-               BASIC_CFLAGS += -DNO_BACKTRACE
+ifndef NO_BACKTRACE
+       ifeq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
+               BASIC_CFLAGS += -DBACKTRACE_SUPPORT
        endif
 endif
 
@@ -906,7 +882,7 @@ $(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
        $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
 
 $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
+       $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
 
 $(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
        $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-redundant-decls $<
index 1958fa539d0f8085f64e897c448ba2ac59eef956..56e6a12aab59b42d4cffbc67858824af818f5fff 100644 (file)
@@ -1,23 +1,59 @@
 # perf completion
 
+function_exists()
+{
+       declare -F $1 > /dev/null
+       return $?
+}
+
+function_exists __ltrim_colon_completions ||
+__ltrim_colon_completions()
+{
+       if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
+               # Remove colon-word prefix from COMPREPLY items
+               local colon_word=${1%${1##*:}}
+               local i=${#COMPREPLY[*]}
+               while [[ $((--i)) -ge 0 ]]; do
+                       COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
+               done
+       fi
+}
+
 have perf &&
 _perf()
 {
-       local cur cmd
+       local cur prev cmd
 
        COMPREPLY=()
-       _get_comp_words_by_ref cur prev
+       if function_exists _get_comp_words_by_ref; then
+               _get_comp_words_by_ref -n : cur prev
+       else
+               cur=$(_get_cword :)
+               prev=${COMP_WORDS[COMP_CWORD-1]}
+       fi
 
        cmd=${COMP_WORDS[0]}
 
-       # List perf subcommands
+       # List perf subcommands or long options
        if [ $COMP_CWORD -eq 1 ]; then
-               cmds=$($cmd --list-cmds)
-               COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
+               if [[ $cur == --* ]]; then
+                       COMPREPLY=( $( compgen -W '--help --version \
+                       --exec-path --html-path --paginate --no-pager \
+                       --perf-dir --work-tree --debugfs-dir' -- "$cur" ) )
+               else
+                       cmds=$($cmd --list-cmds)
+                       COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
+               fi
        # List possible events for -e option
        elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then
-               cmds=$($cmd list --raw-dump)
-               COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
+               evts=$($cmd list --raw-dump)
+               COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) )
+               __ltrim_colon_completions $cur
+       # List long option names
+       elif [[ $cur == --* ]];  then
+               subcmd=${COMP_WORDS[1]}
+               opts=$($cmd $subcmd --list-opts)
+               COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) )
        # Fall down to list regular files
        else
                _filedir
index 83654557e108bf5c09e5b113aa49c5f759082a7d..d37e077f4b147727aba0b3bee7bf080dccdd1678 100644 (file)
 #include "util/strlist.h"
 #include "util/symbol.h"
 
-static char const *add_name_list_str, *remove_name_list_str;
-
-static const char * const buildid_cache_usage[] = {
-       "perf buildid-cache [<options>]",
-       NULL
-};
-
-static const struct option buildid_cache_options[] = {
-       OPT_STRING('a', "add", &add_name_list_str,
-                  "file list", "file(s) to add"),
-       OPT_STRING('r', "remove", &remove_name_list_str, "file list",
-                   "file(s) to remove"),
-       OPT_INCR('v', "verbose", &verbose, "be more verbose"),
-       OPT_END()
-};
-
 static int build_id_cache__add_file(const char *filename, const char *debugdir)
 {
        char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -51,8 +35,8 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir)
        return err;
 }
 
-static int build_id_cache__remove_file(const char *filename __maybe_unused,
-                                      const char *debugdir __maybe_unused)
+static int build_id_cache__remove_file(const char *filename,
+                                      const char *debugdir)
 {
        u8 build_id[BUILD_ID_SIZE];
        char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -73,11 +57,34 @@ static int build_id_cache__remove_file(const char *filename __maybe_unused,
        return err;
 }
 
-static int __cmd_buildid_cache(void)
+int cmd_buildid_cache(int argc, const char **argv,
+                     const char *prefix __maybe_unused)
 {
        struct strlist *list;
        struct str_node *pos;
        char debugdir[PATH_MAX];
+       char const *add_name_list_str = NULL,
+                  *remove_name_list_str = NULL;
+       const struct option buildid_cache_options[] = {
+       OPT_STRING('a', "add", &add_name_list_str,
+                  "file list", "file(s) to add"),
+       OPT_STRING('r', "remove", &remove_name_list_str, "file list",
+                   "file(s) to remove"),
+       OPT_INCR('v', "verbose", &verbose, "be more verbose"),
+       OPT_END()
+       };
+       const char * const buildid_cache_usage[] = {
+               "perf buildid-cache [<options>]",
+               NULL
+       };
+
+       argc = parse_options(argc, argv, buildid_cache_options,
+                            buildid_cache_usage, 0);
+
+       if (symbol__init() < 0)
+               return -1;
+
+       setup_pager();
 
        snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
 
@@ -119,16 +126,3 @@ static int __cmd_buildid_cache(void)
 
        return 0;
 }
-
-int cmd_buildid_cache(int argc, const char **argv,
-                     const char *prefix __maybe_unused)
-{
-       argc = parse_options(argc, argv, buildid_cache_options,
-                            buildid_cache_usage, 0);
-
-       if (symbol__init() < 0)
-               return -1;
-
-       setup_pager();
-       return __cmd_buildid_cache();
-}
index 1159feeebb1955c0e5c16739dd1d856cd13e29c7..a0e94fffa03ec123255f37738389d36229ac4c39 100644 (file)
 #include "util/session.h"
 #include "util/symbol.h"
 
-static const char *input_name;
-static bool force;
-static bool show_kernel;
-static bool with_hits;
-
-static const char * const buildid_list_usage[] = {
-       "perf buildid-list [<options>]",
-       NULL
-};
-
-static const struct option options[] = {
-       OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"),
-       OPT_STRING('i', "input", &input_name, "file",
-                   "input file name"),
-       OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
-       OPT_BOOLEAN('k', "kernel", &show_kernel, "Show current kernel build id"),
-       OPT_INCR('v', "verbose", &verbose,
-                   "be more verbose"),
-       OPT_END()
-};
-
 static int sysfs__fprintf_build_id(FILE *fp)
 {
        u8 kallsyms_build_id[BUILD_ID_SIZE];
@@ -65,7 +44,8 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
        return fprintf(fp, "%s\n", sbuild_id);
 }
 
-static int perf_session__list_build_ids(void)
+static int perf_session__list_build_ids(const char *input_name,
+                                       bool force, bool with_hits)
 {
        struct perf_session *session;
 
@@ -95,18 +75,31 @@ out:
        return 0;
 }
 
-static int __cmd_buildid_list(void)
-{
-       if (show_kernel)
-               return sysfs__fprintf_build_id(stdout);
-
-       return perf_session__list_build_ids();
-}
-
 int cmd_buildid_list(int argc, const char **argv,
                     const char *prefix __maybe_unused)
 {
+       bool show_kernel = false;
+       bool with_hits = false;
+       bool force = false;
+       const char *input_name = NULL;
+       const struct option options[] = {
+       OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"),
+       OPT_STRING('i', "input", &input_name, "file", "input file name"),
+       OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
+       OPT_BOOLEAN('k', "kernel", &show_kernel, "Show current kernel build id"),
+       OPT_INCR('v', "verbose", &verbose, "be more verbose"),
+       OPT_END()
+       };
+       const char * const buildid_list_usage[] = {
+               "perf buildid-list [<options>]",
+               NULL
+       };
+
        argc = parse_options(argc, argv, options, buildid_list_usage, 0);
        setup_pager();
-       return __cmd_buildid_list();
+
+       if (show_kernel)
+               return sysfs__fprintf_build_id(stdout);
+
+       return perf_session__list_build_ids(input_name, force, with_hits);
 }
index 761f4197a9e264e8fb7c1cc4f6665589d951c169..a0b531c14b974f24cbbd2727a879c59c69415e06 100644 (file)
@@ -70,8 +70,8 @@ static struct perf_tool tool = {
        .ordering_requires_timestamps = true,
 };
 
-static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
-                                                   struct hist_entry *he)
+static void insert_hist_entry_by_name(struct rb_root *root,
+                                     struct hist_entry *he)
 {
        struct rb_node **p = &root->rb_node;
        struct rb_node *parent = NULL;
@@ -90,7 +90,7 @@ static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
        rb_insert_color(&he->rb_node, root);
 }
 
-static void hists__resort_entries(struct hists *self)
+static void hists__name_resort(struct hists *self, bool sort)
 {
        unsigned long position = 1;
        struct rb_root tmp = RB_ROOT;
@@ -100,12 +100,16 @@ static void hists__resort_entries(struct hists *self)
                struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node);
 
                next = rb_next(&n->rb_node);
-               rb_erase(&n->rb_node, &self->entries);
                n->position = position++;
-               perf_session__insert_hist_entry_by_name(&tmp, n);
+
+               if (sort) {
+                       rb_erase(&n->rb_node, &self->entries);
+                       insert_hist_entry_by_name(&tmp, n);
+               }
        }
 
-       self->entries = tmp;
+       if (sort)
+               self->entries = tmp;
 }
 
 static struct hist_entry *hists__find_entry(struct hists *self,
@@ -121,7 +125,7 @@ static struct hist_entry *hists__find_entry(struct hists *self,
                        n = n->rb_left;
                else if (cmp > 0)
                        n = n->rb_right;
-               else 
+               else
                        return iter;
        }
 
@@ -150,6 +154,24 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
        return NULL;
 }
 
+static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name)
+{
+       struct perf_evsel *evsel;
+
+       list_for_each_entry(evsel, &evlist->entries, node) {
+               struct hists *hists = &evsel->hists;
+
+               hists__output_resort(hists);
+
+               /*
+                * The hists__name_resort only sets possition
+                * if name is false.
+                */
+               if (name || ((!name) && show_displacement))
+                       hists__name_resort(hists, name);
+       }
+}
+
 static int __cmd_diff(void)
 {
        int ret, i;
@@ -176,15 +198,8 @@ static int __cmd_diff(void)
        evlist_old = older->evlist;
        evlist_new = newer->evlist;
 
-       list_for_each_entry(evsel, &evlist_new->entries, node)
-               hists__output_resort(&evsel->hists);
-
-       list_for_each_entry(evsel, &evlist_old->entries, node) {
-               hists__output_resort(&evsel->hists);
-
-               if (show_displacement)
-                       hists__resort_entries(&evsel->hists);
-       }
+       perf_evlist__resort_hists(evlist_old, true);
+       perf_evlist__resort_hists(evlist_new, false);
 
        list_for_each_entry(evsel, &evlist_new->entries, node) {
                struct perf_evsel *evsel_old;
@@ -199,8 +214,7 @@ static int __cmd_diff(void)
                first = false;
 
                hists__match(&evsel_old->hists, &evsel->hists);
-               hists__fprintf(&evsel->hists, &evsel_old->hists,
-                              show_displacement, true, 0, 0, stdout);
+               hists__fprintf(&evsel->hists, true, 0, 0, stdout);
        }
 
 out_delete:
@@ -242,6 +256,21 @@ static const struct option options[] = {
        OPT_END()
 };
 
+static void ui_init(void)
+{
+       perf_hpp__init();
+
+       /* No overhead column. */
+       perf_hpp__column_enable(PERF_HPP__OVERHEAD, false);
+
+       /* Display baseline/delta/displacement columns. */
+       perf_hpp__column_enable(PERF_HPP__BASELINE, true);
+       perf_hpp__column_enable(PERF_HPP__DELTA, true);
+
+       if (show_displacement)
+               perf_hpp__column_enable(PERF_HPP__DISPL, true);
+}
+
 int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        sort_order = diff__default_sort_order;
@@ -264,7 +293,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
        if (symbol__init() < 0)
                return -1;
 
-       perf_hpp__init(true, show_displacement);
+       ui_init();
+
        setup_sorting(diff_usage, options);
        setup_pager();
 
index 1fb164164fd0b7340f6ac3f7b7a86607cdc039e2..997afb82691b8afe71660169484bc4473bd39793 100644 (file)
@@ -108,23 +108,20 @@ static int __cmd_evlist(const char *input_name, struct perf_attr_details *detail
        return 0;
 }
 
-static const char * const evlist_usage[] = {
-       "perf evlist [<options>]",
-       NULL
-};
-
 int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        struct perf_attr_details details = { .verbose = false, };
        const char *input_name = NULL;
        const struct option options[] = {
-               OPT_STRING('i', "input", &input_name, "file",
-                           "Input file name"),
-               OPT_BOOLEAN('F', "freq", &details.freq,
-                           "Show the sample frequency"),
-               OPT_BOOLEAN('v', "verbose", &details.verbose,
-                           "Show all event attr details"),
-               OPT_END()
+       OPT_STRING('i', "input", &input_name, "file", "Input file name"),
+       OPT_BOOLEAN('F', "freq", &details.freq, "Show the sample frequency"),
+       OPT_BOOLEAN('v', "verbose", &details.verbose,
+                   "Show all event attr details"),
+       OPT_END()
+       };
+       const char * const evlist_usage[] = {
+               "perf evlist [<options>]",
+               NULL
        };
 
        argc = parse_options(argc, argv, options, evlist_usage, 0);
index 25c8b942ff8577a9aa7cc5967536474021ebd33b..411ee5664e98e1e765bf992f379c16ec30569585 100644 (file)
@@ -30,23 +30,6 @@ enum help_format {
        HELP_FORMAT_WEB,
 };
 
-static bool show_all = false;
-static enum help_format help_format = HELP_FORMAT_NONE;
-static struct option builtin_help_options[] = {
-       OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
-       OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
-       OPT_SET_UINT('w', "web", &help_format, "show manual in web browser",
-                       HELP_FORMAT_WEB),
-       OPT_SET_UINT('i', "info", &help_format, "show info page",
-                       HELP_FORMAT_INFO),
-       OPT_END(),
-};
-
-static const char * const builtin_help_usage[] = {
-       "perf help [--all] [--man|--web|--info] [command]",
-       NULL
-};
-
 static enum help_format parse_help_format(const char *format)
 {
        if (!strcmp(format, "man"))
@@ -258,11 +241,13 @@ static int add_man_viewer_info(const char *var, const char *value)
 
 static int perf_help_config(const char *var, const char *value, void *cb)
 {
+       enum help_format *help_formatp = cb;
+
        if (!strcmp(var, "help.format")) {
                if (!value)
                        return config_error_nonbool(var);
-               help_format = parse_help_format(value);
-               if (help_format == HELP_FORMAT_NONE)
+               *help_formatp = parse_help_format(value);
+               if (*help_formatp == HELP_FORMAT_NONE)
                        return -1;
                return 0;
        }
@@ -428,12 +413,27 @@ static int show_html_page(const char *perf_cmd)
 
 int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
 {
+       bool show_all = false;
+       enum help_format help_format = HELP_FORMAT_NONE;
+       struct option builtin_help_options[] = {
+       OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
+       OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
+       OPT_SET_UINT('w', "web", &help_format, "show manual in web browser",
+                       HELP_FORMAT_WEB),
+       OPT_SET_UINT('i', "info", &help_format, "show info page",
+                       HELP_FORMAT_INFO),
+       OPT_END(),
+       };
+       const char * const builtin_help_usage[] = {
+               "perf help [--all] [--man|--web|--info] [command]",
+               NULL
+       };
        const char *alias;
        int rc = 0;
 
        load_command_list("perf-", &main_cmds, &other_cmds);
 
-       perf_config(perf_help_config, NULL);
+       perf_config(perf_help_config, &help_format);
 
        argc = parse_options(argc, argv, builtin_help_options,
                        builtin_help_usage, 0);
index 1eaa6617c8142ca62840c805fff0a79cf28d216b..4688bea95c12e4d3dedfb1d12180848aaa8fd725 100644 (file)
 
 #include "util/parse-options.h"
 
-static char            const *input_name = "-";
-static bool            inject_build_ids;
+struct perf_inject {
+       struct perf_tool tool;
+       bool             build_ids;
+};
 
 static int perf_event__repipe_synth(struct perf_tool *tool __maybe_unused,
                                    union perf_event *event,
@@ -194,7 +196,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
                                 * account this as unresolved.
                                 */
                        } else {
-#ifndef NO_LIBELF_SUPPORT
+#ifdef LIBELF_SUPPORT
                                pr_warning("no symbols found in %s, maybe "
                                           "install a debug package?\n",
                                           al.map->dso->long_name);
@@ -208,22 +210,6 @@ repipe:
        return 0;
 }
 
-struct perf_tool perf_inject = {
-       .sample         = perf_event__repipe_sample,
-       .mmap           = perf_event__repipe,
-       .comm           = perf_event__repipe,
-       .fork           = perf_event__repipe,
-       .exit           = perf_event__repipe,
-       .lost           = perf_event__repipe,
-       .read           = perf_event__repipe_sample,
-       .throttle       = perf_event__repipe,
-       .unthrottle     = perf_event__repipe,
-       .attr           = perf_event__repipe_attr,
-       .event_type     = perf_event__repipe_event_type_synth,
-       .tracing_data   = perf_event__repipe_tracing_data_synth,
-       .build_id       = perf_event__repipe_op2_synth,
-};
-
 extern volatile int session_done;
 
 static void sig_handler(int sig __maybe_unused)
@@ -231,56 +217,72 @@ static void sig_handler(int sig __maybe_unused)
        session_done = 1;
 }
 
-static int __cmd_inject(void)
+static int __cmd_inject(struct perf_inject *inject)
 {
        struct perf_session *session;
        int ret = -EINVAL;
 
        signal(SIGINT, sig_handler);
 
-       if (inject_build_ids) {
-               perf_inject.sample       = perf_event__inject_buildid;
-               perf_inject.mmap         = perf_event__repipe_mmap;
-               perf_inject.fork         = perf_event__repipe_task;
-               perf_inject.tracing_data = perf_event__repipe_tracing_data;
+       if (inject->build_ids) {
+               inject->tool.sample       = perf_event__inject_buildid;
+               inject->tool.mmap         = perf_event__repipe_mmap;
+               inject->tool.fork         = perf_event__repipe_task;
+               inject->tool.tracing_data = perf_event__repipe_tracing_data;
        }
 
-       session = perf_session__new(input_name, O_RDONLY, false, true, &perf_inject);
+       session = perf_session__new("-", O_RDONLY, false, true, &inject->tool);
        if (session == NULL)
                return -ENOMEM;
 
-       ret = perf_session__process_events(session, &perf_inject);
+       ret = perf_session__process_events(session, &inject->tool);
 
        perf_session__delete(session);
 
        return ret;
 }
 
-static const char * const report_usage[] = {
-       "perf inject [<options>]",
-       NULL
-};
-
-static const struct option options[] = {
-       OPT_BOOLEAN('b', "build-ids", &inject_build_ids,
-                   "Inject build-ids into the output stream"),
-       OPT_INCR('v', "verbose", &verbose,
-                "be more verbose (show build ids, etc)"),
-       OPT_END()
-};
-
 int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
 {
-       argc = parse_options(argc, argv, options, report_usage, 0);
+       struct perf_inject inject = {
+               .tool = {
+                       .sample         = perf_event__repipe_sample,
+                       .mmap           = perf_event__repipe,
+                       .comm           = perf_event__repipe,
+                       .fork           = perf_event__repipe,
+                       .exit           = perf_event__repipe,
+                       .lost           = perf_event__repipe,
+                       .read           = perf_event__repipe_sample,
+                       .throttle       = perf_event__repipe,
+                       .unthrottle     = perf_event__repipe,
+                       .attr           = perf_event__repipe_attr,
+                       .event_type     = perf_event__repipe_event_type_synth,
+                       .tracing_data   = perf_event__repipe_tracing_data_synth,
+                       .build_id       = perf_event__repipe_op2_synth,
+               },
+       };
+       const struct option options[] = {
+               OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
+                           "Inject build-ids into the output stream"),
+               OPT_INCR('v', "verbose", &verbose,
+                        "be more verbose (show build ids, etc)"),
+               OPT_END()
+       };
+       const char * const inject_usage[] = {
+               "perf inject [<options>]",
+               NULL
+       };
+
+       argc = parse_options(argc, argv, options, inject_usage, 0);
 
        /*
         * Any (unrecognized) arguments left?
         */
        if (argc)
-               usage_with_options(report_usage, options);
+               usage_with_options(inject_usage, options);
 
        if (symbol__init() < 0)
                return -1;
 
-       return __cmd_inject();
+       return __cmd_inject(&inject);
 }
index bc912c68f49a56aa92ad26a27dc8cc34b2566fa2..14bf82f6365950e275cd00823f1ecfb8c815c494 100644 (file)
@@ -21,8 +21,6 @@
 struct alloc_stat;
 typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);
 
-static const char              *input_name;
-
 static int                     alloc_flag;
 static int                     caller_flag;
 
@@ -31,8 +29,6 @@ static int                    caller_lines = -1;
 
 static bool                    raw_ip;
 
-static char                    default_sort_order[] = "frag,hit,bytes";
-
 static int                     *cpunode_map;
 static int                     max_cpu_num;
 
@@ -481,7 +477,7 @@ static void sort_result(void)
        __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort);
 }
 
-static int __cmd_kmem(void)
+static int __cmd_kmem(const char *input_name)
 {
        int err = -EINVAL;
        struct perf_session *session;
@@ -520,11 +516,6 @@ out_delete:
        return err;
 }
 
-static const char * const kmem_usage[] = {
-       "perf kmem [<options>] {record|stat}",
-       NULL
-};
-
 static int ptr_cmp(struct alloc_stat *l, struct alloc_stat *r)
 {
        if (l->ptr < r->ptr)
@@ -720,41 +711,17 @@ static int parse_line_opt(const struct option *opt __maybe_unused,
        return 0;
 }
 
-static const struct option kmem_options[] = {
-       OPT_STRING('i', "input", &input_name, "file",
-                  "input file name"),
-       OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
-                          "show per-callsite statistics",
-                          parse_caller_opt),
-       OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
-                          "show per-allocation statistics",
-                          parse_alloc_opt),
-       OPT_CALLBACK('s', "sort", NULL, "key[,key2...]",
-                    "sort by keys: ptr, call_site, bytes, hit, pingpong, frag",
-                    parse_sort_opt),
-       OPT_CALLBACK('l', "line", NULL, "num",
-                    "show n lines",
-                    parse_line_opt),
-       OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
-       OPT_END()
-};
-
-static const char *record_args[] = {
-       "record",
-       "-a",
-       "-R",
-       "-f",
-       "-c", "1",
+static int __cmd_record(int argc, const char **argv)
+{
+       const char * const record_args[] = {
+       "record", "-a", "-R", "-f", "-c", "1",
        "-e", "kmem:kmalloc",
        "-e", "kmem:kmalloc_node",
        "-e", "kmem:kfree",
        "-e", "kmem:kmem_cache_alloc",
        "-e", "kmem:kmem_cache_alloc_node",
        "-e", "kmem:kmem_cache_free",
-};
-
-static int __cmd_record(int argc, const char **argv)
-{
+       };
        unsigned int rec_argc, i, j;
        const char **rec_argv;
 
@@ -775,6 +742,25 @@ static int __cmd_record(int argc, const char **argv)
 
 int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
 {
+       const char * const default_sort_order = "frag,hit,bytes";
+       const char *input_name = NULL;
+       const struct option kmem_options[] = {
+       OPT_STRING('i', "input", &input_name, "file", "input file name"),
+       OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
+                          "show per-callsite statistics", parse_caller_opt),
+       OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
+                          "show per-allocation statistics", parse_alloc_opt),
+       OPT_CALLBACK('s', "sort", NULL, "key[,key2...]",
+                    "sort by keys: ptr, call_site, bytes, hit, pingpong, frag",
+                    parse_sort_opt),
+       OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt),
+       OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
+       OPT_END()
+       };
+       const char * const kmem_usage[] = {
+               "perf kmem [<options>] {record|stat}",
+               NULL
+       };
        argc = parse_options(argc, argv, kmem_options, kmem_usage, 0);
 
        if (!argc)
@@ -793,7 +779,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
                if (list_empty(&alloc_sort))
                        setup_sorting(&alloc_sort, default_sort_order);
 
-               return __cmd_kmem();
+               return __cmd_kmem(input_name);
        } else
                usage_with_options(kmem_usage, kmem_options);
 
index a28c9cad9048f1198541d9c7c04d64e2373b6f7b..260abc535b5b428e817ebaa5a4354fbe67a947e1 100644 (file)
@@ -32,16 +32,76 @@ struct event_key {
        int info;
 };
 
+struct kvm_event_stats {
+       u64 time;
+       struct stats stats;
+};
+
+struct kvm_event {
+       struct list_head hash_entry;
+       struct rb_node rb;
+
+       struct event_key key;
+
+       struct kvm_event_stats total;
+
+       #define DEFAULT_VCPU_NUM 8
+       int max_vcpu;
+       struct kvm_event_stats *vcpu;
+};
+
+typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int);
+
+struct kvm_event_key {
+       const char *name;
+       key_cmp_fun key;
+};
+
+
+struct perf_kvm;
+
 struct kvm_events_ops {
        bool (*is_begin_event)(struct perf_evsel *evsel,
                               struct perf_sample *sample,
                               struct event_key *key);
        bool (*is_end_event)(struct perf_evsel *evsel,
                             struct perf_sample *sample, struct event_key *key);
-       void (*decode_key)(struct event_key *key, char decode[20]);
+       void (*decode_key)(struct perf_kvm *kvm, struct event_key *key,
+                          char decode[20]);
        const char *name;
 };
 
+struct exit_reasons_table {
+       unsigned long exit_code;
+       const char *reason;
+};
+
+#define EVENTS_BITS            12
+#define EVENTS_CACHE_SIZE      (1UL << EVENTS_BITS)
+
+struct perf_kvm {
+       struct perf_tool    tool;
+       struct perf_session *session;
+
+       const char *file_name;
+       const char *report_event;
+       const char *sort_key;
+       int trace_vcpu;
+
+       struct exit_reasons_table *exit_reasons;
+       int exit_reasons_size;
+       const char *exit_reasons_isa;
+
+       struct kvm_events_ops *events_ops;
+       key_cmp_fun compare;
+       struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
+       u64 total_time;
+       u64 total_count;
+
+       struct rb_root result;
+};
+
+
 static void exit_event_get_key(struct perf_evsel *evsel,
                               struct perf_sample *sample,
                               struct event_key *key)
@@ -78,45 +138,35 @@ static bool exit_event_end(struct perf_evsel *evsel,
        return kvm_entry_event(evsel);
 }
 
-struct exit_reasons_table {
-       unsigned long exit_code;
-       const char *reason;
-};
-
-struct exit_reasons_table vmx_exit_reasons[] = {
+static struct exit_reasons_table vmx_exit_reasons[] = {
        VMX_EXIT_REASONS
 };
 
-struct exit_reasons_table svm_exit_reasons[] = {
+static struct exit_reasons_table svm_exit_reasons[] = {
        SVM_EXIT_REASONS
 };
 
-static int cpu_isa;
-
-static const char *get_exit_reason(u64 exit_code)
+static const char *get_exit_reason(struct perf_kvm *kvm, u64 exit_code)
 {
-       int table_size = ARRAY_SIZE(svm_exit_reasons);
-       struct exit_reasons_table *table = svm_exit_reasons;
-
-       if (cpu_isa == 1) {
-               table = vmx_exit_reasons;
-               table_size = ARRAY_SIZE(vmx_exit_reasons);
-       }
+       int i = kvm->exit_reasons_size;
+       struct exit_reasons_table *tbl = kvm->exit_reasons;
 
-       while (table_size--) {
-               if (table->exit_code == exit_code)
-                       return table->reason;
-               table++;
+       while (i--) {
+               if (tbl->exit_code == exit_code)
+                       return tbl->reason;
+               tbl++;
        }
 
        pr_err("unknown kvm exit code:%lld on %s\n",
-               (unsigned long long)exit_code, cpu_isa ? "VMX" : "SVM");
+               (unsigned long long)exit_code, kvm->exit_reasons_isa);
        return "UNKNOWN";
 }
 
-static void exit_event_decode_key(struct event_key *key, char decode[20])
+static void exit_event_decode_key(struct perf_kvm *kvm,
+                                 struct event_key *key,
+                                 char decode[20])
 {
-       const char *exit_reason = get_exit_reason(key->key);
+       const char *exit_reason = get_exit_reason(kvm, key->key);
 
        scnprintf(decode, 20, "%s", exit_reason);
 }
@@ -128,11 +178,11 @@ static struct kvm_events_ops exit_events = {
        .name = "VM-EXIT"
 };
 
-    /*
    * For the mmio events, we treat:
    * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
    * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...).
    */
+/*
+ * For the mmio events, we treat:
+ * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
+ * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...).
+ */
 static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample,
                               struct event_key *key)
 {
@@ -178,7 +228,9 @@ static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample,
        return false;
 }
 
-static void mmio_event_decode_key(struct event_key *key, char decode[20])
+static void mmio_event_decode_key(struct perf_kvm *kvm __maybe_unused,
+                                 struct event_key *key,
+                                 char decode[20])
 {
        scnprintf(decode, 20, "%#lx:%s", (unsigned long)key->key,
                                key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R");
@@ -219,7 +271,9 @@ static bool ioport_event_end(struct perf_evsel *evsel,
        return kvm_entry_event(evsel);
 }
 
-static void ioport_event_decode_key(struct event_key *key, char decode[20])
+static void ioport_event_decode_key(struct perf_kvm *kvm __maybe_unused,
+                                   struct event_key *key,
+                                   char decode[20])
 {
        scnprintf(decode, 20, "%#llx:%s", (unsigned long long)key->key,
                                key->info ? "POUT" : "PIN");
@@ -232,64 +286,37 @@ static struct kvm_events_ops ioport_events = {
        .name = "IO Port Access"
 };
 
-static const char *report_event = "vmexit";
-struct kvm_events_ops *events_ops;
-
-static bool register_kvm_events_ops(void)
+static bool register_kvm_events_ops(struct perf_kvm *kvm)
 {
        bool ret = true;
 
-       if (!strcmp(report_event, "vmexit"))
-               events_ops = &exit_events;
-       else if (!strcmp(report_event, "mmio"))
-               events_ops = &mmio_events;
-       else if (!strcmp(report_event, "ioport"))
-               events_ops = &ioport_events;
+       if (!strcmp(kvm->report_event, "vmexit"))
+               kvm->events_ops = &exit_events;
+       else if (!strcmp(kvm->report_event, "mmio"))
+               kvm->events_ops = &mmio_events;
+       else if (!strcmp(kvm->report_event, "ioport"))
+               kvm->events_ops = &ioport_events;
        else {
-               pr_err("Unknown report event:%s\n", report_event);
+               pr_err("Unknown report event:%s\n", kvm->report_event);
                ret = false;
        }
 
        return ret;
 }
 
-struct kvm_event_stats {
-       u64 time;
-       struct stats stats;
-};
-
-struct kvm_event {
-       struct list_head hash_entry;
-       struct rb_node rb;
-
-       struct event_key key;
-
-       struct kvm_event_stats total;
-
-       #define DEFAULT_VCPU_NUM 8
-       int max_vcpu;
-       struct kvm_event_stats *vcpu;
-};
-
 struct vcpu_event_record {
        int vcpu_id;
        u64 start_time;
        struct kvm_event *last_event;
 };
 
-#define EVENTS_BITS                    12
-#define EVENTS_CACHE_SIZE      (1UL << EVENTS_BITS)
-
-static u64 total_time;
-static u64 total_count;
-static struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
 
-static void init_kvm_event_record(void)
+static void init_kvm_event_record(struct perf_kvm *kvm)
 {
        int i;
 
        for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++)
-               INIT_LIST_HEAD(&kvm_events_cache[i]);
+               INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
 }
 
 static int kvm_events_hash_fn(u64 key)
@@ -333,14 +360,15 @@ static struct kvm_event *kvm_alloc_init_event(struct event_key *key)
        return event;
 }
 
-static struct kvm_event *find_create_kvm_event(struct event_key *key)
+static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm,
+                                              struct event_key *key)
 {
        struct kvm_event *event;
        struct list_head *head;
 
        BUG_ON(key->key == INVALID_KEY);
 
-       head = &kvm_events_cache[kvm_events_hash_fn(key->key)];
+       head = &kvm->kvm_events_cache[kvm_events_hash_fn(key->key)];
        list_for_each_entry(event, head, hash_entry)
                if (event->key.key == key->key && event->key.info == key->info)
                        return event;
@@ -353,13 +381,14 @@ static struct kvm_event *find_create_kvm_event(struct event_key *key)
        return event;
 }
 
-static bool handle_begin_event(struct vcpu_event_record *vcpu_record,
+static bool handle_begin_event(struct perf_kvm *kvm,
+                              struct vcpu_event_record *vcpu_record,
                               struct event_key *key, u64 timestamp)
 {
        struct kvm_event *event = NULL;
 
        if (key->key != INVALID_KEY)
-               event = find_create_kvm_event(key);
+               event = find_create_kvm_event(kvm, key);
 
        vcpu_record->last_event = event;
        vcpu_record->start_time = timestamp;
@@ -396,8 +425,10 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
        return true;
 }
 
-static bool handle_end_event(struct vcpu_event_record *vcpu_record,
-                            struct event_key *key, u64 timestamp)
+static bool handle_end_event(struct perf_kvm *kvm,
+                            struct vcpu_event_record *vcpu_record,
+                            struct event_key *key,
+                            u64 timestamp)
 {
        struct kvm_event *event;
        u64 time_begin, time_diff;
@@ -419,7 +450,7 @@ static bool handle_end_event(struct vcpu_event_record *vcpu_record,
                return true;
 
        if (!event)
-               event = find_create_kvm_event(key);
+               event = find_create_kvm_event(kvm, key);
 
        if (!event)
                return false;
@@ -455,7 +486,9 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
        return thread->priv;
 }
 
-static bool handle_kvm_event(struct thread *thread, struct perf_evsel *evsel,
+static bool handle_kvm_event(struct perf_kvm *kvm,
+                            struct thread *thread,
+                            struct perf_evsel *evsel,
                             struct perf_sample *sample)
 {
        struct vcpu_event_record *vcpu_record;
@@ -465,22 +498,15 @@ static bool handle_kvm_event(struct thread *thread, struct perf_evsel *evsel,
        if (!vcpu_record)
                return true;
 
-       if (events_ops->is_begin_event(evsel, sample, &key))
-               return handle_begin_event(vcpu_record, &key, sample->time);
+       if (kvm->events_ops->is_begin_event(evsel, sample, &key))
+               return handle_begin_event(kvm, vcpu_record, &key, sample->time);
 
-       if (events_ops->is_end_event(evsel, sample, &key))
-               return handle_end_event(vcpu_record, &key, sample->time);
+       if (kvm->events_ops->is_end_event(evsel, sample, &key))
+               return handle_end_event(kvm, vcpu_record, &key, sample->time);
 
        return true;
 }
 
-typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int);
-struct kvm_event_key {
-       const char *name;
-       key_cmp_fun key;
-};
-
-static int trace_vcpu = -1;
 #define GET_EVENT_KEY(func, field)                                     \
 static u64 get_event_ ##func(struct kvm_event *event, int vcpu)                \
 {                                                                      \
@@ -515,29 +541,25 @@ static struct kvm_event_key keys[] = {
        { NULL, NULL }
 };
 
-static const char *sort_key = "sample";
-static key_cmp_fun compare;
-
-static bool select_key(void)
+static bool select_key(struct perf_kvm *kvm)
 {
        int i;
 
        for (i = 0; keys[i].name; i++) {
-               if (!strcmp(keys[i].name, sort_key)) {
-                       compare = keys[i].key;
+               if (!strcmp(keys[i].name, kvm->sort_key)) {
+                       kvm->compare = keys[i].key;
                        return true;
                }
        }
 
-       pr_err("Unknown compare key:%s\n", sort_key);
+       pr_err("Unknown compare key:%s\n", kvm->sort_key);
        return false;
 }
 
-static struct rb_root result;
-static void insert_to_result(struct kvm_event *event, key_cmp_fun bigger,
-                            int vcpu)
+static void insert_to_result(struct rb_root *result, struct kvm_event *event,
+                            key_cmp_fun bigger, int vcpu)
 {
-       struct rb_node **rb = &result.rb_node;
+       struct rb_node **rb = &result->rb_node;
        struct rb_node *parent = NULL;
        struct kvm_event *p;
 
@@ -552,13 +574,15 @@ static void insert_to_result(struct kvm_event *event, key_cmp_fun bigger,
        }
 
        rb_link_node(&event->rb, parent, rb);
-       rb_insert_color(&event->rb, &result);
+       rb_insert_color(&event->rb, result);
 }
 
-static void update_total_count(struct kvm_event *event, int vcpu)
+static void update_total_count(struct perf_kvm *kvm, struct kvm_event *event)
 {
-       total_count += get_event_count(event, vcpu);
-       total_time += get_event_time(event, vcpu);
+       int vcpu = kvm->trace_vcpu;
+
+       kvm->total_count += get_event_count(event, vcpu);
+       kvm->total_time += get_event_time(event, vcpu);
 }
 
 static bool event_is_valid(struct kvm_event *event, int vcpu)
@@ -566,28 +590,30 @@ static bool event_is_valid(struct kvm_event *event, int vcpu)
        return !!get_event_count(event, vcpu);
 }
 
-static void sort_result(int vcpu)
+static void sort_result(struct perf_kvm *kvm)
 {
        unsigned int i;
+       int vcpu = kvm->trace_vcpu;
        struct kvm_event *event;
 
        for (i = 0; i < EVENTS_CACHE_SIZE; i++)
-               list_for_each_entry(event, &kvm_events_cache[i], hash_entry)
+               list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry)
                        if (event_is_valid(event, vcpu)) {
-                               update_total_count(event, vcpu);
-                               insert_to_result(event, compare, vcpu);
+                               update_total_count(kvm, event);
+                               insert_to_result(&kvm->result, event,
+                                                kvm->compare, vcpu);
                        }
 }
 
 /* returns left most element of result, and erase it */
-static struct kvm_event *pop_from_result(void)
+static struct kvm_event *pop_from_result(struct rb_root *result)
 {
-       struct rb_node *node = rb_first(&result);
+       struct rb_node *node = rb_first(result);
 
        if (!node)
                return NULL;
 
-       rb_erase(node, &result);
+       rb_erase(node, result);
        return container_of(node, struct kvm_event, rb);
 }
 
@@ -601,14 +627,15 @@ static void print_vcpu_info(int vcpu)
                pr_info("VCPU %d:\n\n", vcpu);
 }
 
-static void print_result(int vcpu)
+static void print_result(struct perf_kvm *kvm)
 {
        char decode[20];
        struct kvm_event *event;
+       int vcpu = kvm->trace_vcpu;
 
        pr_info("\n\n");
        print_vcpu_info(vcpu);
-       pr_info("%20s ", events_ops->name);
+       pr_info("%20s ", kvm->events_ops->name);
        pr_info("%10s ", "Samples");
        pr_info("%9s ", "Samples%");
 
@@ -616,33 +643,34 @@ static void print_result(int vcpu)
        pr_info("%16s ", "Avg time");
        pr_info("\n\n");
 
-       while ((event = pop_from_result())) {
+       while ((event = pop_from_result(&kvm->result))) {
                u64 ecount, etime;
 
                ecount = get_event_count(event, vcpu);
                etime = get_event_time(event, vcpu);
 
-               events_ops->decode_key(&event->key, decode);
+               kvm->events_ops->decode_key(kvm, &event->key, decode);
                pr_info("%20s ", decode);
                pr_info("%10llu ", (unsigned long long)ecount);
-               pr_info("%8.2f%% ", (double)ecount / total_count * 100);
-               pr_info("%8.2f%% ", (double)etime / total_time * 100);
+               pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
+               pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
                pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3,
                        kvm_event_rel_stddev(vcpu, event));
                pr_info("\n");
        }
 
        pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n",
-               (unsigned long long)total_count, total_time / 1e3);
+               (unsigned long long)kvm->total_count, kvm->total_time / 1e3);
 }
 
-static int process_sample_event(struct perf_tool *tool __maybe_unused,
+static int process_sample_event(struct perf_tool *tool,
                                union perf_event *event,
                                struct perf_sample *sample,
                                struct perf_evsel *evsel,
                                struct machine *machine)
 {
        struct thread *thread = machine__findnew_thread(machine, sample->tid);
+       struct perf_kvm *kvm = container_of(tool, struct perf_kvm, tool);
 
        if (thread == NULL) {
                pr_debug("problem processing %d event, skipping it.\n",
@@ -650,18 +678,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
                return -1;
        }
 
-       if (!handle_kvm_event(thread, evsel, sample))
+       if (!handle_kvm_event(kvm, thread, evsel, sample))
                return -1;
 
        return 0;
 }
 
-static struct perf_tool eops = {
-       .sample                 = process_sample_event,
-       .comm                   = perf_event__process_comm,
-       .ordered_samples        = true,
-};
-
 static int get_cpu_isa(struct perf_session *session)
 {
        char *cpuid = session->header.env.cpuid;
@@ -679,34 +701,43 @@ static int get_cpu_isa(struct perf_session *session)
        return isa;
 }
 
-static const char *file_name;
-
-static int read_events(void)
+static int read_events(struct perf_kvm *kvm)
 {
-       struct perf_session *kvm_session;
        int ret;
 
-       kvm_session = perf_session__new(file_name, O_RDONLY, 0, false, &eops);
-       if (!kvm_session) {
+       struct perf_tool eops = {
+               .sample                 = process_sample_event,
+               .comm                   = perf_event__process_comm,
+               .ordered_samples        = true,
+       };
+
+       kvm->tool = eops;
+       kvm->session = perf_session__new(kvm->file_name, O_RDONLY, 0, false,
+                                        &kvm->tool);
+       if (!kvm->session) {
                pr_err("Initializing perf session failed\n");
                return -EINVAL;
        }
 
-       if (!perf_session__has_traces(kvm_session, "kvm record"))
+       if (!perf_session__has_traces(kvm->session, "kvm record"))
                return -EINVAL;
 
        /*
         * Do not use 'isa' recorded in kvm_exit tracepoint since it is not
         * traced in the old kernel.
         */
-       ret = get_cpu_isa(kvm_session);
+       ret = get_cpu_isa(kvm->session);
 
        if (ret < 0)
                return ret;
 
-       cpu_isa = ret;
+       if (ret == 1) {
+               kvm->exit_reasons = vmx_exit_reasons;
+               kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons);
+               kvm->exit_reasons_isa = "VMX";
+       }
 
-       return perf_session__process_events(kvm_session, &eops);
+       return perf_session__process_events(kvm->session, &kvm->tool);
 }
 
 static bool verify_vcpu(int vcpu)
@@ -719,28 +750,30 @@ static bool verify_vcpu(int vcpu)
        return true;
 }
 
-static int kvm_events_report_vcpu(int vcpu)
+static int kvm_events_report_vcpu(struct perf_kvm *kvm)
 {
        int ret = -EINVAL;
+       int vcpu = kvm->trace_vcpu;
 
        if (!verify_vcpu(vcpu))
                goto exit;
 
-       if (!select_key())
+       if (!select_key(kvm))
                goto exit;
 
-       if (!register_kvm_events_ops())
+       if (!register_kvm_events_ops(kvm))
                goto exit;
 
-       init_kvm_event_record();
+       init_kvm_event_record(kvm);
        setup_pager();
 
-       ret = read_events();
+       ret = read_events(kvm);
        if (ret)
                goto exit;
 
-       sort_result(vcpu);
-       print_result(vcpu);
+       sort_result(kvm);
+       print_result(kvm);
+
 exit:
        return ret;
 }
@@ -765,7 +798,7 @@ static const char * const record_args[] = {
                _p;                     \
        })
 
-static int kvm_events_record(int argc, const char **argv)
+static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv)
 {
        unsigned int rec_argc, i, j;
        const char **rec_argv;
@@ -780,7 +813,7 @@ static int kvm_events_record(int argc, const char **argv)
                rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);
 
        rec_argv[i++] = STRDUP_FAIL_EXIT("-o");
-       rec_argv[i++] = STRDUP_FAIL_EXIT(file_name);
+       rec_argv[i++] = STRDUP_FAIL_EXIT(kvm->file_name);
 
        for (j = 1; j < (unsigned int)argc; j++, i++)
                rec_argv[i] = argv[j];
@@ -788,24 +821,24 @@ static int kvm_events_record(int argc, const char **argv)
        return cmd_record(i, rec_argv, NULL);
 }
 
-static const char * const kvm_events_report_usage[] = {
-       "perf kvm stat report [<options>]",
-       NULL
-};
+static int kvm_events_report(struct perf_kvm *kvm, int argc, const char **argv)
+{
+       const struct option kvm_events_report_options[] = {
+               OPT_STRING(0, "event", &kvm->report_event, "report event",
+                           "event for reporting: vmexit, mmio, ioport"),
+               OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu,
+                           "vcpu id to report"),
+               OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
+                           "key for sorting: sample(sort by samples number)"
+                           " time (sort by avg time)"),
+               OPT_END()
+       };
 
-static const struct option kvm_events_report_options[] = {
-       OPT_STRING(0, "event", &report_event, "report event",
-                   "event for reporting: vmexit, mmio, ioport"),
-       OPT_INTEGER(0, "vcpu", &trace_vcpu,
-                   "vcpu id to report"),
-       OPT_STRING('k', "key", &sort_key, "sort-key",
-                   "key for sorting: sample(sort by samples number)"
-                   " time (sort by avg time)"),
-       OPT_END()
-};
+       const char * const kvm_events_report_usage[] = {
+               "perf kvm stat report [<options>]",
+               NULL
+       };
 
-static int kvm_events_report(int argc, const char **argv)
-{
        symbol__init();
 
        if (argc) {
@@ -817,7 +850,7 @@ static int kvm_events_report(int argc, const char **argv)
                                           kvm_events_report_options);
        }
 
-       return kvm_events_report_vcpu(trace_vcpu);
+       return kvm_events_report_vcpu(kvm);
 }
 
 static void print_kvm_stat_usage(void)
@@ -831,7 +864,7 @@ static void print_kvm_stat_usage(void)
        printf("\nOtherwise, it is the alias of 'perf stat':\n");
 }
 
-static int kvm_cmd_stat(int argc, const char **argv)
+static int kvm_cmd_stat(struct perf_kvm *kvm, int argc, const char **argv)
 {
        if (argc == 1) {
                print_kvm_stat_usage();
@@ -839,44 +872,16 @@ static int kvm_cmd_stat(int argc, const char **argv)
        }
 
        if (!strncmp(argv[1], "rec", 3))
-               return kvm_events_record(argc - 1, argv + 1);
+               return kvm_events_record(kvm, argc - 1, argv + 1);
 
        if (!strncmp(argv[1], "rep", 3))
-               return kvm_events_report(argc - 1 , argv + 1);
+               return kvm_events_report(kvm, argc - 1 , argv + 1);
 
 perf_stat:
        return cmd_stat(argc, argv, NULL);
 }
 
-static char                    name_buffer[256];
-
-static const char * const kvm_usage[] = {
-       "perf kvm [<options>] {top|record|report|diff|buildid-list|stat}",
-       NULL
-};
-
-static const struct option kvm_options[] = {
-       OPT_STRING('i', "input", &file_name, "file",
-                  "Input file name"),
-       OPT_STRING('o', "output", &file_name, "file",
-                  "Output file name"),
-       OPT_BOOLEAN(0, "guest", &perf_guest,
-                   "Collect guest os data"),
-       OPT_BOOLEAN(0, "host", &perf_host,
-                   "Collect host os data"),
-       OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
-                  "guest mount directory under which every guest os"
-                  " instance has a subdir"),
-       OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,
-                  "file", "file saving guest os vmlinux"),
-       OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,
-                  "file", "file saving guest os /proc/kallsyms"),
-       OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
-                  "file", "file saving guest os /proc/modules"),
-       OPT_END()
-};
-
-static int __cmd_record(int argc, const char **argv)
+static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv)
 {
        int rec_argc, i = 0, j;
        const char **rec_argv;
@@ -885,7 +890,7 @@ static int __cmd_record(int argc, const char **argv)
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
        rec_argv[i++] = strdup("record");
        rec_argv[i++] = strdup("-o");
-       rec_argv[i++] = strdup(file_name);
+       rec_argv[i++] = strdup(kvm->file_name);
        for (j = 1; j < argc; j++, i++)
                rec_argv[i] = argv[j];
 
@@ -894,7 +899,7 @@ static int __cmd_record(int argc, const char **argv)
        return cmd_record(i, rec_argv, NULL);
 }
 
-static int __cmd_report(int argc, const char **argv)
+static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv)
 {
        int rec_argc, i = 0, j;
        const char **rec_argv;
@@ -903,7 +908,7 @@ static int __cmd_report(int argc, const char **argv)
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
        rec_argv[i++] = strdup("report");
        rec_argv[i++] = strdup("-i");
-       rec_argv[i++] = strdup(file_name);
+       rec_argv[i++] = strdup(kvm->file_name);
        for (j = 1; j < argc; j++, i++)
                rec_argv[i] = argv[j];
 
@@ -912,7 +917,7 @@ static int __cmd_report(int argc, const char **argv)
        return cmd_report(i, rec_argv, NULL);
 }
 
-static int __cmd_buildid_list(int argc, const char **argv)
+static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv)
 {
        int rec_argc, i = 0, j;
        const char **rec_argv;
@@ -921,7 +926,7 @@ static int __cmd_buildid_list(int argc, const char **argv)
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
        rec_argv[i++] = strdup("buildid-list");
        rec_argv[i++] = strdup("-i");
-       rec_argv[i++] = strdup(file_name);
+       rec_argv[i++] = strdup(kvm->file_name);
        for (j = 1; j < argc; j++, i++)
                rec_argv[i] = argv[j];
 
@@ -932,6 +937,43 @@ static int __cmd_buildid_list(int argc, const char **argv)
 
 int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
 {
+       struct perf_kvm kvm = {
+               .trace_vcpu     = -1,
+               .report_event   = "vmexit",
+               .sort_key       = "sample",
+
+               .exit_reasons = svm_exit_reasons,
+               .exit_reasons_size = ARRAY_SIZE(svm_exit_reasons),
+               .exit_reasons_isa = "SVM",
+       };
+
+       const struct option kvm_options[] = {
+               OPT_STRING('i', "input", &kvm.file_name, "file",
+                          "Input file name"),
+               OPT_STRING('o', "output", &kvm.file_name, "file",
+                          "Output file name"),
+               OPT_BOOLEAN(0, "guest", &perf_guest,
+                           "Collect guest os data"),
+               OPT_BOOLEAN(0, "host", &perf_host,
+                           "Collect host os data"),
+               OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
+                          "guest mount directory under which every guest os"
+                          " instance has a subdir"),
+               OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,
+                          "file", "file saving guest os vmlinux"),
+               OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,
+                          "file", "file saving guest os /proc/kallsyms"),
+               OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
+                          "file", "file saving guest os /proc/modules"),
+               OPT_END()
+       };
+
+
+       const char * const kvm_usage[] = {
+               "perf kvm [<options>] {top|record|report|diff|buildid-list|stat}",
+               NULL
+       };
+
        perf_host  = 0;
        perf_guest = 1;
 
@@ -943,28 +985,32 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
        if (!perf_host)
                perf_guest = 1;
 
-       if (!file_name) {
+       if (!kvm.file_name) {
                if (perf_host && !perf_guest)
-                       sprintf(name_buffer, "perf.data.host");
+                       kvm.file_name = strdup("perf.data.host");
                else if (!perf_host && perf_guest)
-                       sprintf(name_buffer, "perf.data.guest");
+                       kvm.file_name = strdup("perf.data.guest");
                else
-                       sprintf(name_buffer, "perf.data.kvm");
-               file_name = name_buffer;
+                       kvm.file_name = strdup("perf.data.kvm");
+
+               if (!kvm.file_name) {
+                       pr_err("Failed to allocate memory for filename\n");
+                       return -ENOMEM;
+               }
        }
 
        if (!strncmp(argv[0], "rec", 3))
-               return __cmd_record(argc, argv);
+               return __cmd_record(&kvm, argc, argv);
        else if (!strncmp(argv[0], "rep", 3))
-               return __cmd_report(argc, argv);
+               return __cmd_report(&kvm, argc, argv);
        else if (!strncmp(argv[0], "diff", 4))
                return cmd_diff(argc, argv, NULL);
        else if (!strncmp(argv[0], "top", 3))
                return cmd_top(argc, argv, NULL);
        else if (!strncmp(argv[0], "buildid-list", 12))
-               return __cmd_buildid_list(argc, argv);
+               return __cmd_buildid_list(&kvm, argc, argv);
        else if (!strncmp(argv[0], "stat", 4))
-               return kvm_cmd_stat(argc, argv);
+               return kvm_cmd_stat(&kvm, argc, argv);
        else
                usage_with_options(kvm_usage, kvm_options);
 
index 7d6e09949880a812c7e43cfe97a8700ce0ce799e..6f5f328157aa623f34cbd1c112a3b218d5c0b9c1 100644 (file)
@@ -823,12 +823,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
        return 0;
 }
 
-static struct perf_tool eops = {
-       .sample                 = process_sample_event,
-       .comm                   = perf_event__process_comm,
-       .ordered_samples        = true,
-};
-
 static const struct perf_evsel_str_handler lock_tracepoints[] = {
        { "lock:lock_acquire",   perf_evsel__process_lock_acquire,   }, /* CONFIG_LOCKDEP */
        { "lock:lock_acquired",  perf_evsel__process_lock_acquired,  }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
@@ -838,6 +832,11 @@ static const struct perf_evsel_str_handler lock_tracepoints[] = {
 
 static int read_events(void)
 {
+       struct perf_tool eops = {
+               .sample          = process_sample_event,
+               .comm            = perf_event__process_comm,
+               .ordered_samples = true,
+       };
        session = perf_session__new(input_name, O_RDONLY, 0, false, &eops);
        if (!session) {
                pr_err("Initializing perf session failed\n");
@@ -878,53 +877,11 @@ static int __cmd_report(void)
        return 0;
 }
 
-static const char * const report_usage[] = {
-       "perf lock report [<options>]",
-       NULL
-};
-
-static const struct option report_options[] = {
-       OPT_STRING('k', "key", &sort_key, "acquired",
-                   "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"),
-       /* TODO: type */
-       OPT_END()
-};
-
-static const char * const info_usage[] = {
-       "perf lock info [<options>]",
-       NULL
-};
-
-static const struct option info_options[] = {
-       OPT_BOOLEAN('t', "threads", &info_threads,
-                   "dump thread list in perf.data"),
-       OPT_BOOLEAN('m', "map", &info_map,
-                   "map of lock instances (address:name table)"),
-       OPT_END()
-};
-
-static const char * const lock_usage[] = {
-       "perf lock [<options>] {record|report|script|info}",
-       NULL
-};
-
-static const struct option lock_options[] = {
-       OPT_STRING('i', "input", &input_name, "file", "input file name"),
-       OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"),
-       OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"),
-       OPT_END()
-};
-
-static const char *record_args[] = {
-       "record",
-       "-R",
-       "-f",
-       "-m", "1024",
-       "-c", "1",
-};
-
 static int __cmd_record(int argc, const char **argv)
 {
+       const char *record_args[] = {
+               "record", "-R", "-f", "-m", "1024", "-c", "1",
+       };
        unsigned int rec_argc, i, j;
        const char **rec_argv;
 
@@ -963,6 +920,37 @@ static int __cmd_record(int argc, const char **argv)
 
 int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
 {
+       const struct option info_options[] = {
+       OPT_BOOLEAN('t', "threads", &info_threads,
+                   "dump thread list in perf.data"),
+       OPT_BOOLEAN('m', "map", &info_map,
+                   "map of lock instances (address:name table)"),
+       OPT_END()
+       };
+       const struct option lock_options[] = {
+       OPT_STRING('i', "input", &input_name, "file", "input file name"),
+       OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"),
+       OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"),
+       OPT_END()
+       };
+       const struct option report_options[] = {
+       OPT_STRING('k', "key", &sort_key, "acquired",
+                   "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"),
+       /* TODO: type */
+       OPT_END()
+       };
+       const char * const info_usage[] = {
+               "perf lock info [<options>]",
+               NULL
+       };
+       const char * const lock_usage[] = {
+               "perf lock [<options>] {record|report|script|info}",
+               NULL
+       };
+       const char * const report_usage[] = {
+               "perf lock report [<options>]",
+               NULL
+       };
        unsigned int i;
        int rc = 0;
 
index 118aa89465737cbe7db4cf61b485eb7c5fd3af4f..de38a034b129e62b91ad73d2564fe5b5e7617b7f 100644 (file)
@@ -250,19 +250,20 @@ static int opt_set_filter(const struct option *opt __maybe_unused,
        return 0;
 }
 
-static const char * const probe_usage[] = {
-       "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
-       "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
-       "perf probe [<options>] --del '[GROUP:]EVENT' ...",
-       "perf probe --list",
+int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
+{
+       const char * const probe_usage[] = {
+               "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
+               "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
+               "perf probe [<options>] --del '[GROUP:]EVENT' ...",
+               "perf probe --list",
 #ifdef DWARF_SUPPORT
-       "perf probe [<options>] --line 'LINEDESC'",
-       "perf probe [<options>] --vars 'PROBEPOINT'",
+               "perf probe [<options>] --line 'LINEDESC'",
+               "perf probe [<options>] --vars 'PROBEPOINT'",
 #endif
-       NULL
+               NULL
 };
-
-static const struct option options[] = {
+       const struct option options[] = {
        OPT_INCR('v', "verbose", &verbose,
                    "be more verbose (show parsed arguments, etc)"),
        OPT_BOOLEAN('l', "list", &params.list_events,
@@ -325,10 +326,7 @@ static const struct option options[] = {
        OPT_CALLBACK('x', "exec", NULL, "executable|path",
                        "target executable name or path", opt_set_target),
        OPT_END()
-};
-
-int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
-{
+       };
        int ret;
 
        argc = parse_options(argc, argv, options, probe_usage,
index f14cb5fdb91fb0b3a9c0894367c98570b15f85e6..e9231659754d97ae25d0688c4144d19bffbb1bcd 100644 (file)
 #include <sched.h>
 #include <sys/mman.h>
 
-#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
-
-#ifdef NO_LIBUNWIND_SUPPORT
-static char callchain_help[] = CALLCHAIN_HELP "[fp]";
-#else
-static unsigned long default_stack_dump_size = 8192;
-static char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
-#endif
-
 enum write_mode_t {
        WRITE_FORCE,
        WRITE_APPEND
@@ -800,7 +791,7 @@ error:
        return ret;
 }
 
-#ifndef NO_LIBUNWIND_SUPPORT
+#ifdef LIBUNWIND_SUPPORT
 static int get_stack_size(char *str, unsigned long *_size)
 {
        char *endptr;
@@ -826,7 +817,7 @@ static int get_stack_size(char *str, unsigned long *_size)
               max_size, str);
        return -1;
 }
-#endif /* !NO_LIBUNWIND_SUPPORT */
+#endif /* LIBUNWIND_SUPPORT */
 
 static int
 parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
@@ -865,9 +856,11 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
                                       "needed for -g fp\n");
                        break;
 
-#ifndef NO_LIBUNWIND_SUPPORT
+#ifdef LIBUNWIND_SUPPORT
                /* Dwarf style */
                } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
+                       const unsigned long default_stack_dump_size = 8192;
+
                        ret = 0;
                        rec->opts.call_graph = CALLCHAIN_DWARF;
                        rec->opts.stack_dump_size = default_stack_dump_size;
@@ -883,7 +876,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
                        if (!ret)
                                pr_debug("callchain: stack dump size %d\n",
                                         rec->opts.stack_dump_size);
-#endif /* !NO_LIBUNWIND_SUPPORT */
+#endif /* LIBUNWIND_SUPPORT */
                } else {
                        pr_err("callchain: Unknown -g option "
                               "value: %s\n", arg);
@@ -930,6 +923,14 @@ static struct perf_record record = {
        .file_new   = true,
 };
 
+#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
+
+#ifdef LIBUNWIND_SUPPORT
+static const char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
+#else
+static const char callchain_help[] = CALLCHAIN_HELP "[fp]";
+#endif
+
 /*
  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
  * with it and switch to use the library functions in perf_evlist that came
index 1da243dfbc3e7005ea9a64c195571f7ef1504c19..a61725d89d3ee4188dbe7c4b542c6e1f3685d506 100644 (file)
@@ -320,7 +320,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
                const char *evname = perf_evsel__name(pos);
 
                hists__fprintf_nr_sample_events(hists, evname, stdout);
-               hists__fprintf(hists, NULL, false, true, 0, 0, stdout);
+               hists__fprintf(hists, true, 0, 0, stdout);
                fprintf(stdout, "\n\n");
        }
 
@@ -691,7 +691,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
                setup_browser(true);
        else {
                use_browser = 0;
-               perf_hpp__init(false, false);
+               perf_hpp__init();
        }
 
        setup_sorting(report_usage, options);
index 9b9e32eaa8051da3a5cf562e38abe372a1afb6ee..3488ead3b60ce80707493e93f821945bad8a6455 100644 (file)
@@ -1426,7 +1426,7 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
                                                 struct perf_evsel *evsel,
                                                 struct machine *machine)
 {
-       struct thread *thread = machine__findnew_thread(machine, sample->pid);
+       struct thread *thread = machine__findnew_thread(machine, sample->tid);
        int err = 0;
 
        if (thread == NULL) {
index 1be843aa1546ed1df603119e3cec193d04cf0673..fb9625083a2ed6d9d4bd25b94bc306895f18d6fc 100644 (file)
@@ -24,7 +24,6 @@ static u64                    last_timestamp;
 static u64                     nr_unordered;
 extern const struct option     record_options[];
 static bool                    no_callchain;
-static bool                    show_full_info;
 static bool                    system_wide;
 static const char              *cpu_list;
 static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -473,8 +472,6 @@ static int cleanup_scripting(void)
        return scripting_ops->stop_script();
 }
 
-static const char *input_name;
-
 static int process_sample_event(struct perf_tool *tool __maybe_unused,
                                union perf_event *event,
                                struct perf_sample *sample,
@@ -1156,20 +1153,40 @@ out:
        return n_args;
 }
 
-static const char * const script_usage[] = {
-       "perf script [<options>]",
-       "perf script [<options>] record <script> [<record-options>] <command>",
-       "perf script [<options>] report <script> [script-args]",
-       "perf script [<options>] <script> [<record-options>] <command>",
-       "perf script [<options>] <top-script> [script-args]",
-       NULL
-};
+static int have_cmd(int argc, const char **argv)
+{
+       char **__argv = malloc(sizeof(const char *) * argc);
+
+       if (!__argv) {
+               pr_err("malloc failed\n");
+               return -1;
+       }
+
+       memcpy(__argv, argv, sizeof(const char *) * argc);
+       argc = parse_options(argc, (const char **)__argv, record_options,
+                            NULL, PARSE_OPT_STOP_AT_NON_OPTION);
+       free(__argv);
 
-static const struct option options[] = {
+       system_wide = (argc == 0);
+
+       return 0;
+}
+
+int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
+{
+       bool show_full_info = false;
+       const char *input_name = NULL;
+       char *rec_script_path = NULL;
+       char *rep_script_path = NULL;
+       struct perf_session *session;
+       char *script_path = NULL;
+       const char **__argv;
+       int i, j, err;
+       const struct option options[] = {
        OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
                    "dump raw trace in ASCII"),
        OPT_INCR('v', "verbose", &verbose,
-                   "be more verbose (show symbol address, etc)"),
+                "be more verbose (show symbol address, etc)"),
        OPT_BOOLEAN('L', "Latency", &latency_format,
                    "show latency attributes (irqs/preemption disabled, etc)"),
        OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts",
@@ -1179,8 +1196,7 @@ static const struct option options[] = {
                     parse_scriptname),
        OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
                   "generate perf-script.xx script in specified language"),
-       OPT_STRING('i', "input", &input_name, "file",
-                   "input file name"),
+       OPT_STRING('i', "input", &input_name, "file", "input file name"),
        OPT_BOOLEAN('d', "debug-mode", &debug_mode,
                   "do various checks like samples ordering and lost events"),
        OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
@@ -1195,10 +1211,9 @@ static const struct option options[] = {
                     "comma separated output fields prepend with 'type:'. "
                     "Valid types: hw,sw,trace,raw. "
                     "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
-                    "addr,symoff",
-                    parse_output_fields),
+                    "addr,symoff", parse_output_fields),
        OPT_BOOLEAN('a', "all-cpus", &system_wide,
-                    "system-wide collection from all CPUs"),
+                   "system-wide collection from all CPUs"),
        OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
                   "only consider these symbols"),
        OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
@@ -1208,37 +1223,16 @@ static const struct option options[] = {
                    "display extended information from perf.data file"),
        OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
                    "Show the path of [kernel.kallsyms]"),
-
        OPT_END()
-};
-
-static int have_cmd(int argc, const char **argv)
-{
-       char **__argv = malloc(sizeof(const char *) * argc);
-
-       if (!__argv) {
-               pr_err("malloc failed\n");
-               return -1;
-       }
-
-       memcpy(__argv, argv, sizeof(const char *) * argc);
-       argc = parse_options(argc, (const char **)__argv, record_options,
-                            NULL, PARSE_OPT_STOP_AT_NON_OPTION);
-       free(__argv);
-
-       system_wide = (argc == 0);
-
-       return 0;
-}
-
-int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
-{
-       char *rec_script_path = NULL;
-       char *rep_script_path = NULL;
-       struct perf_session *session;
-       char *script_path = NULL;
-       const char **__argv;
-       int i, j, err;
+       };
+       const char * const script_usage[] = {
+               "perf script [<options>]",
+               "perf script [<options>] record <script> [<record-options>] <command>",
+               "perf script [<options>] report <script> [script-args]",
+               "perf script [<options>] <script> [<record-options>] <command>",
+               "perf script [<options>] <top-script> [script-args]",
+               NULL
+       };
 
        setup_scripting();
 
index e8cd4d81b06e583a4e73f02a3bf92e8a60e411eb..93b9011fa3e27a5cc61dc6e96a962cf63cd2b5f2 100644 (file)
 #define CNTR_NOT_SUPPORTED     "<not supported>"
 #define CNTR_NOT_COUNTED       "<not counted>"
 
-static struct perf_event_attr default_attrs[] = {
-
-  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK             },
-  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES       },
-  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS         },
-  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS            },
-
-  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES             },
-  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND        },
-  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
-  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS           },
-  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS    },
-  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES          },
-
-};
-
-/*
- * Detailed stats (-d), covering the L1 and last level data caches:
- */
-static struct perf_event_attr detailed_attrs[] = {
-
-  { .type = PERF_TYPE_HW_CACHE,
-    .config =
-        PERF_COUNT_HW_CACHE_L1D                <<  0  |
-       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
-       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
-
-  { .type = PERF_TYPE_HW_CACHE,
-    .config =
-        PERF_COUNT_HW_CACHE_L1D                <<  0  |
-       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
-       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
-
-  { .type = PERF_TYPE_HW_CACHE,
-    .config =
-        PERF_COUNT_HW_CACHE_LL                 <<  0  |
-       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
-       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
-
-  { .type = PERF_TYPE_HW_CACHE,
-    .config =
-        PERF_COUNT_HW_CACHE_LL                 <<  0  |
-       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
-       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
-};
-
-/*
- * Very detailed stats (-d -d), covering the instruction cache and the TLB caches:
- */
-static struct perf_event_attr very_detailed_attrs[] = {
-
-  { .type = PERF_TYPE_HW_CACHE,
-    .config =
-        PERF_COUNT_HW_CACHE_L1I                <<  0  |
-       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
-       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
-
-  { .type = PERF_TYPE_HW_CACHE,
-    .config =
-        PERF_COUNT_HW_CACHE_L1I                <<  0  |
-       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
-       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
-
-  { .type = PERF_TYPE_HW_CACHE,
-    .config =
-        PERF_COUNT_HW_CACHE_DTLB               <<  0  |
-       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
-       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
-
-  { .type = PERF_TYPE_HW_CACHE,
-    .config =
-        PERF_COUNT_HW_CACHE_DTLB               <<  0  |
-       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
-       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
-
-  { .type = PERF_TYPE_HW_CACHE,
-    .config =
-        PERF_COUNT_HW_CACHE_ITLB               <<  0  |
-       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
-       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
-
-  { .type = PERF_TYPE_HW_CACHE,
-    .config =
-        PERF_COUNT_HW_CACHE_ITLB               <<  0  |
-       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
-       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
-
-};
-
-/*
- * Very, very detailed stats (-d -d -d), adding prefetch events:
- */
-static struct perf_event_attr very_very_detailed_attrs[] = {
-
-  { .type = PERF_TYPE_HW_CACHE,
-    .config =
-        PERF_COUNT_HW_CACHE_L1D                <<  0  |
-       (PERF_COUNT_HW_CACHE_OP_PREFETCH        <<  8) |
-       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
-
-  { .type = PERF_TYPE_HW_CACHE,
-    .config =
-        PERF_COUNT_HW_CACHE_L1D                <<  0  |
-       (PERF_COUNT_HW_CACHE_OP_PREFETCH        <<  8) |
-       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
-};
-
-
-
 static struct perf_evlist      *evsel_list;
 
 static struct perf_target      target = {
        .uid    = UINT_MAX,
 };
 
-static int                     run_idx                         =  0;
 static int                     run_count                       =  1;
 static bool                    no_inherit                      = false;
 static bool                    scale                           =  true;
@@ -187,15 +77,12 @@ static bool                        no_aggr                         = false;
 static pid_t                   child_pid                       = -1;
 static bool                    null_run                        =  false;
 static int                     detailed_run                    =  0;
-static bool                    sync_run                        =  false;
 static bool                    big_num                         =  true;
 static int                     big_num_opt                     =  -1;
 static const char              *csv_sep                        = NULL;
 static bool                    csv_output                      = false;
 static bool                    group                           = false;
-static const char              *output_name                    = NULL;
 static FILE                    *output                         = NULL;
-static int                     output_fd;
 
 static volatile int done = 0;
 
@@ -1028,11 +915,6 @@ static void sig_atexit(void)
        kill(getpid(), signr);
 }
 
-static const char * const stat_usage[] = {
-       "perf stat [<options>] [<command>]",
-       NULL
-};
-
 static int stat__set_big_num(const struct option *opt __maybe_unused,
                             const char *s __maybe_unused, int unset)
 {
@@ -1040,62 +922,119 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
        return 0;
 }
 
-static bool append_file;
-
-static const struct option options[] = {
-       OPT_CALLBACK('e', "event", &evsel_list, "event",
-                    "event selector. use 'perf list' to list available events",
-                    parse_events_option),
-       OPT_CALLBACK(0, "filter", &evsel_list, "filter",
-                    "event filter", parse_filter),
-       OPT_BOOLEAN('i', "no-inherit", &no_inherit,
-                   "child tasks do not inherit counters"),
-       OPT_STRING('p', "pid", &target.pid, "pid",
-                  "stat events on existing process id"),
-       OPT_STRING('t', "tid", &target.tid, "tid",
-                  "stat events on existing thread id"),
-       OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
-                   "system-wide collection from all CPUs"),
-       OPT_BOOLEAN('g', "group", &group,
-                   "put the counters into a counter group"),
-       OPT_BOOLEAN('c', "scale", &scale,
-                   "scale/normalize counters"),
-       OPT_INCR('v', "verbose", &verbose,
-                   "be more verbose (show counter open errors, etc)"),
-       OPT_INTEGER('r', "repeat", &run_count,
-                   "repeat command and print average + stddev (max: 100)"),
-       OPT_BOOLEAN('n', "null", &null_run,
-                   "null run - dont start any counters"),
-       OPT_INCR('d', "detailed", &detailed_run,
-                   "detailed run - start a lot of events"),
-       OPT_BOOLEAN('S', "sync", &sync_run,
-                   "call sync() before starting a run"),
-       OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 
-                          "print large numbers with thousands\' separators",
-                          stat__set_big_num),
-       OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
-                   "list of cpus to monitor in system-wide"),
-       OPT_BOOLEAN('A', "no-aggr", &no_aggr,
-                   "disable CPU count aggregation"),
-       OPT_STRING('x', "field-separator", &csv_sep, "separator",
-                  "print counts with custom separator"),
-       OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
-                    "monitor event in cgroup name only",
-                    parse_cgroups),
-       OPT_STRING('o', "output", &output_name, "file",
-                   "output file name"),
-       OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
-       OPT_INTEGER(0, "log-fd", &output_fd,
-                   "log output to fd, instead of stderr"),
-       OPT_END()
-};
-
 /*
  * Add default attributes, if there were no attributes specified or
  * if -d/--detailed, -d -d or -d -d -d is used:
  */
 static int add_default_attributes(void)
 {
+       struct perf_event_attr default_attrs[] = {
+
+  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK             },
+  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES       },
+  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS         },
+  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS            },
+
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES             },
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND        },
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS           },
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS    },
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES          },
+
+};
+
+/*
+ * Detailed stats (-d), covering the L1 and last level data caches:
+ */
+       struct perf_event_attr detailed_attrs[] = {
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_L1D                <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_L1D                <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_LL                 <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_LL                 <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
+};
+
+/*
+ * Very detailed stats (-d -d), covering the instruction cache and the TLB caches:
+ */
+       struct perf_event_attr very_detailed_attrs[] = {
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_L1I                <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_L1I                <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_DTLB               <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_DTLB               <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_ITLB               <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_ITLB               <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_READ            <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
+
+};
+
+/*
+ * Very, very detailed stats (-d -d -d), adding prefetch events:
+ */
+       struct perf_event_attr very_very_detailed_attrs[] = {
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_L1D                <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_PREFETCH        <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_ACCESS      << 16)                          },
+
+  { .type = PERF_TYPE_HW_CACHE,
+    .config =
+        PERF_COUNT_HW_CACHE_L1D                <<  0  |
+       (PERF_COUNT_HW_CACHE_OP_PREFETCH        <<  8) |
+       (PERF_COUNT_HW_CACHE_RESULT_MISS        << 16)                          },
+};
+
        /* Set attrs if no event is selected and !null_run: */
        if (null_run)
                return 0;
@@ -1130,8 +1069,59 @@ static int add_default_attributes(void)
 
 int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 {
+       bool append_file = false,
+            sync_run = false;
+       int output_fd = 0;
+       const char *output_name = NULL;
+       const struct option options[] = {
+       OPT_CALLBACK('e', "event", &evsel_list, "event",
+                    "event selector. use 'perf list' to list available events",
+                    parse_events_option),
+       OPT_CALLBACK(0, "filter", &evsel_list, "filter",
+                    "event filter", parse_filter),
+       OPT_BOOLEAN('i', "no-inherit", &no_inherit,
+                   "child tasks do not inherit counters"),
+       OPT_STRING('p', "pid", &target.pid, "pid",
+                  "stat events on existing process id"),
+       OPT_STRING('t', "tid", &target.tid, "tid",
+                  "stat events on existing thread id"),
+       OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
+                   "system-wide collection from all CPUs"),
+       OPT_BOOLEAN('g', "group", &group,
+                   "put the counters into a counter group"),
+       OPT_BOOLEAN('c', "scale", &scale, "scale/normalize counters"),
+       OPT_INCR('v', "verbose", &verbose,
+                   "be more verbose (show counter open errors, etc)"),
+       OPT_INTEGER('r', "repeat", &run_count,
+                   "repeat command and print average + stddev (max: 100)"),
+       OPT_BOOLEAN('n', "null", &null_run,
+                   "null run - dont start any counters"),
+       OPT_INCR('d', "detailed", &detailed_run,
+                   "detailed run - start a lot of events"),
+       OPT_BOOLEAN('S', "sync", &sync_run,
+                   "call sync() before starting a run"),
+       OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 
+                          "print large numbers with thousands\' separators",
+                          stat__set_big_num),
+       OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
+                   "list of cpus to monitor in system-wide"),
+       OPT_BOOLEAN('A', "no-aggr", &no_aggr, "disable CPU count aggregation"),
+       OPT_STRING('x', "field-separator", &csv_sep, "separator",
+                  "print counts with custom separator"),
+       OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
+                    "monitor event in cgroup name only", parse_cgroups),
+       OPT_STRING('o', "output", &output_name, "file", "output file name"),
+       OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
+       OPT_INTEGER(0, "log-fd", &output_fd,
+                   "log output to fd, instead of stderr"),
+       OPT_END()
+       };
+       const char * const stat_usage[] = {
+               "perf stat [<options>] [<command>]",
+               NULL
+       };
        struct perf_evsel *pos;
-       int status = -ENOMEM;
+       int status = -ENOMEM, run_idx;
        const char *mode;
 
        setlocale(LC_ALL, "");
index b1a8a3b841ccfbb7bfb895eec914533a07f75563..f251b613b2f3e89dd345cb7fdc231d10c96b340e 100644 (file)
@@ -38,9 +38,6 @@
 #define PWR_EVENT_EXIT -1
 
 
-static const char      *input_name;
-static const char      *output_name = "output.svg";
-
 static unsigned int    numcpus;
 static u64             min_freq;       /* Lowest CPU frequency seen */
 static u64             max_freq;       /* Highest CPU frequency seen */
@@ -968,16 +965,15 @@ static void write_svg_file(const char *filename)
        svg_close();
 }
 
-static struct perf_tool perf_timechart = {
-       .comm                   = process_comm_event,
-       .fork                   = process_fork_event,
-       .exit                   = process_exit_event,
-       .sample                 = process_sample_event,
-       .ordered_samples        = true,
-};
-
-static int __cmd_timechart(void)
+static int __cmd_timechart(const char *input_name, const char *output_name)
 {
+       struct perf_tool perf_timechart = {
+               .comm            = process_comm_event,
+               .fork            = process_fork_event,
+               .exit            = process_exit_event,
+               .sample          = process_sample_event,
+               .ordered_samples = true,
+       };
        struct perf_session *session = perf_session__new(input_name, O_RDONLY,
                                                         0, false, &perf_timechart);
        int ret = -EINVAL;
@@ -1005,40 +1001,25 @@ out_delete:
        return ret;
 }
 
-static const char * const timechart_usage[] = {
-       "perf timechart [<options>] {record}",
-       NULL
-};
-
-#ifdef SUPPORT_OLD_POWER_EVENTS
-static const char * const record_old_args[] = {
-       "record",
-       "-a",
-       "-R",
-       "-f",
-       "-c", "1",
-       "-e", "power:power_start",
-       "-e", "power:power_end",
-       "-e", "power:power_frequency",
-       "-e", "sched:sched_wakeup",
-       "-e", "sched:sched_switch",
-};
-#endif
-
-static const char * const record_new_args[] = {
-       "record",
-       "-a",
-       "-R",
-       "-f",
-       "-c", "1",
-       "-e", "power:cpu_frequency",
-       "-e", "power:cpu_idle",
-       "-e", "sched:sched_wakeup",
-       "-e", "sched:sched_switch",
-};
-
 static int __cmd_record(int argc, const char **argv)
 {
+#ifdef SUPPORT_OLD_POWER_EVENTS
+       const char * const record_old_args[] = {
+               "record", "-a", "-R", "-f", "-c", "1",
+               "-e", "power:power_start",
+               "-e", "power:power_end",
+               "-e", "power:power_frequency",
+               "-e", "sched:sched_wakeup",
+               "-e", "sched:sched_switch",
+       };
+#endif
+       const char * const record_new_args[] = {
+               "record", "-a", "-R", "-f", "-c", "1",
+               "-e", "power:cpu_frequency",
+               "-e", "power:cpu_idle",
+               "-e", "sched:sched_wakeup",
+               "-e", "sched:sched_switch",
+       };
        unsigned int rec_argc, i, j;
        const char **rec_argv;
        const char * const *record_args = record_new_args;
@@ -1077,27 +1058,28 @@ parse_process(const struct option *opt __maybe_unused, const char *arg,
        return 0;
 }
 
-static const struct option options[] = {
-       OPT_STRING('i', "input", &input_name, "file",
-                   "input file name"),
-       OPT_STRING('o', "output", &output_name, "file",
-                   "output file name"),
-       OPT_INTEGER('w', "width", &svg_page_width,
-                   "page width"),
-       OPT_BOOLEAN('P', "power-only", &power_only,
-                   "output power data only"),
+int cmd_timechart(int argc, const char **argv,
+                 const char *prefix __maybe_unused)
+{
+       const char *input_name;
+       const char *output_name = "output.svg";
+       const struct option options[] = {
+       OPT_STRING('i', "input", &input_name, "file", "input file name"),
+       OPT_STRING('o', "output", &output_name, "file", "output file name"),
+       OPT_INTEGER('w', "width", &svg_page_width, "page width"),
+       OPT_BOOLEAN('P', "power-only", &power_only, "output power data only"),
        OPT_CALLBACK('p', "process", NULL, "process",
                      "process selector. Pass a pid or process name.",
                       parse_process),
        OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
                    "Look for files with symbols relative to this directory"),
        OPT_END()
-};
-
+       };
+       const char * const timechart_usage[] = {
+               "perf timechart [<options>] {record}",
+               NULL
+       };
 
-int cmd_timechart(int argc, const char **argv,
-                 const char *prefix __maybe_unused)
-{
        argc = parse_options(argc, argv, options, timechart_usage,
                        PARSE_OPT_STOP_AT_NON_OPTION);
 
@@ -1110,5 +1092,5 @@ int cmd_timechart(int argc, const char **argv,
 
        setup_pager();
 
-       return __cmd_timechart();
+       return __cmd_timechart(input_name, output_name);
 }
index e434a16bb5ac51b031af8e44d9ef6c88152e8f87..ff6db8086805e68caa29e2b232ae0d271dc7b47a 100644 (file)
@@ -316,7 +316,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
        hists__output_recalc_col_len(&top->sym_evsel->hists,
                                     top->winsize.ws_row - 3);
        putchar('\n');
-       hists__fprintf(&top->sym_evsel->hists, NULL, false, false,
+       hists__fprintf(&top->sym_evsel->hists, false,
                       top->winsize.ws_row - 4 - printed, win_width, stdout);
 }
 
@@ -1159,11 +1159,6 @@ setup:
        return 0;
 }
 
-static const char * const top_usage[] = {
-       "perf top [<options>]",
-       NULL
-};
-
 int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        struct perf_evsel *pos;
@@ -1250,6 +1245,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"),
        OPT_END()
        };
+       const char * const top_usage[] = {
+               "perf top [<options>]",
+               NULL
+       };
 
        top.evlist = perf_evlist__new(NULL, NULL);
        if (top.evlist == NULL)
index 8f113dab8bf1371bf508e138cb32993007a4cc68..dec8ced61fb00c2bc7114346db3edaf0f7dd89b7 100644 (file)
@@ -114,10 +114,85 @@ static size_t syscall__fprintf_args(struct syscall *sc, unsigned long *args, FIL
        return printed;
 }
 
+typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
+                                 struct perf_sample *sample);
+
+static struct syscall *trace__syscall_info(struct trace *trace,
+                                          struct perf_evsel *evsel,
+                                          struct perf_sample *sample)
+{
+       int id = perf_evsel__intval(evsel, sample, "id");
+
+       if (id < 0) {
+               printf("Invalid syscall %d id, skipping...\n", id);
+               return NULL;
+       }
+
+       if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
+           trace__read_syscall_info(trace, id))
+               goto out_cant_read;
+
+       if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
+               goto out_cant_read;
+
+       return &trace->syscalls.table[id];
+
+out_cant_read:
+       printf("Problems reading syscall %d information\n", id);
+       return NULL;
+}
+
+static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
+                           struct perf_sample *sample)
+{
+       void *args;
+       struct syscall *sc = trace__syscall_info(trace, evsel, sample);
+
+       if (sc == NULL)
+               return -1;
+
+       args = perf_evsel__rawptr(evsel, sample, "args");
+       if (args == NULL) {
+               printf("Problems reading syscall arguments\n");
+               return -1;
+       }
+
+       printf("%s(", sc->name);
+       syscall__fprintf_args(sc, args, stdout);
+
+       return 0;
+}
+
+static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
+                          struct perf_sample *sample)
+{
+       int ret;
+       struct syscall *sc = trace__syscall_info(trace, evsel, sample);
+
+       if (sc == NULL)
+               return -1;
+
+       ret = perf_evsel__intval(evsel, sample, "ret");
+
+       if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
+               char bf[256];
+               const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
+                          *e = audit_errno_to_name(-ret);
+
+               printf(") = -1 %s %s", e, emsg);
+       } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
+               printf(") = 0 Timeout");
+       else
+               printf(") = %d", ret);
+
+       putchar('\n');
+       return 0;
+}
+
 static int trace__run(struct trace *trace)
 {
        struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
-       struct perf_evsel *evsel, *evsel_enter, *evsel_exit;
+       struct perf_evsel *evsel;
        int err = -1, i, nr_events = 0, before;
 
        if (evlist == NULL) {
@@ -125,22 +200,12 @@ static int trace__run(struct trace *trace)
                goto out;
        }
 
-       evsel_enter = perf_evsel__newtp("raw_syscalls", "sys_enter", 0);
-       if (evsel_enter == NULL) {
-               printf("Couldn't read the raw_syscalls:sys_enter tracepoint information!\n");
-               goto out_delete_evlist;
-       }
-
-       perf_evlist__add(evlist, evsel_enter);
-
-       evsel_exit = perf_evsel__newtp("raw_syscalls", "sys_exit", 1);
-       if (evsel_exit == NULL) {
-               printf("Couldn't read the raw_syscalls:sys_exit tracepoint information!\n");
+       if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
+           perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
+               printf("Couldn't read the raw_syscalls tracepoints information!\n");
                goto out_delete_evlist;
        }
 
-       perf_evlist__add(evlist, evsel_exit);
-
        err = perf_evlist__create_maps(evlist, &trace->opts.target);
        if (err < 0) {
                printf("Problems parsing the target to trace, check your options!\n");
@@ -170,9 +235,8 @@ again:
 
                while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
                        const u32 type = event->header.type;
-                       struct syscall *sc;
+                       tracepoint_handler handler;
                        struct perf_sample sample;
-                       int id;
 
                        ++nr_events;
 
@@ -200,45 +264,11 @@ again:
                                continue;
                        }
 
-                       id = perf_evsel__intval(evsel, &sample, "id");
-                       if (id < 0) {
-                               printf("Invalid syscall %d id, skipping...\n", id);
-                               continue;
-                       }
-
-                       if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
-                           trace__read_syscall_info(trace, id))
-                               continue;
-
-                       if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
-                               continue;
-
-                       sc = &trace->syscalls.table[id];
-
                        if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
                                printf("%d ", sample.tid);
 
-                       if (evsel == evsel_enter) {
-                               void *args = perf_evsel__rawptr(evsel, &sample, "args");
-
-                               printf("%s(", sc->name);
-                               syscall__fprintf_args(sc, args, stdout);
-                       } else if (evsel == evsel_exit) {
-                               int ret = perf_evsel__intval(evsel, &sample, "ret");
-
-                               if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
-                                       char bf[256];
-                                       const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
-                                                  *e = audit_errno_to_name(-ret);
-
-                                       printf(") = -1 %s %s", e, emsg);
-                               } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
-                                       printf(") = 0 Timeout");
-                               else
-                                       printf(") = %d", ret);
-
-                               putchar('\n');
-                       }
+                       handler = evsel->handler.func;
+                       handler(trace, evsel, &sample);
                }
        }
 
index fc2f770e3027e5f10939df7b17f3f805ce2f2107..6d50eb0b425196aea150f699cd97ae09b8840ab8 100644 (file)
@@ -48,14 +48,14 @@ static struct cmd_struct commands[] = {
        { "version",    cmd_version,    0 },
        { "script",     cmd_script,     0 },
        { "sched",      cmd_sched,      0 },
-#ifndef NO_LIBELF_SUPPORT
+#ifdef LIBELF_SUPPORT
        { "probe",      cmd_probe,      0 },
 #endif
        { "kmem",       cmd_kmem,       0 },
        { "lock",       cmd_lock,       0 },
        { "kvm",        cmd_kvm,        0 },
        { "test",       cmd_test,       0 },
-#ifndef NO_LIBAUDIT_SUPPORT
+#ifdef LIBAUDIT_SUPPORT
        { "trace",      cmd_trace,      0 },
 #endif
        { "inject",     cmd_inject,     0 },
index a21f40bebbaced57a7862fb67dec5753f6249497..0568536ecf674fd3ce7e1b397e900a9fd515edcf 100644 (file)
@@ -569,7 +569,8 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
 static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp,     \
                                             struct hist_entry *he)     \
 {                                                                      \
-       double percent = 100.0 * he->_field / hpp->total_period;        \
+       struct hists *hists = he->hists;                                \
+       double percent = 100.0 * he->stat._field / hists->stats.total_period; \
        *(double *)hpp->ptr = percent;                                  \
        return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent);      \
 }
@@ -584,7 +585,7 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)
 
 void hist_browser__init_hpp(void)
 {
-       perf_hpp__init(false, false);
+       perf_hpp__init();
 
        perf_hpp__format[PERF_HPP__OVERHEAD].color =
                                hist_browser__hpp_color_overhead;
@@ -624,7 +625,6 @@ static int hist_browser__show_entry(struct hist_browser *browser,
                struct perf_hpp hpp = {
                        .buf            = s,
                        .size           = sizeof(s),
-                       .total_period   = browser->hists->stats.total_period,
                };
 
                ui_browser__gotorc(&browser->b, row, 0);
@@ -982,7 +982,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
                folded_sign = hist_entry__folded(he);
 
        hist_entry__sort_snprintf(he, s, sizeof(s), browser->hists);
-       percent = (he->period * 100.0) / browser->hists->stats.total_period;
+       percent = (he->stat.period * 100.0) / browser->hists->stats.total_period;
 
        if (symbol_conf.use_callchain)
                printed += fprintf(fp, "%c ", folded_sign);
@@ -990,10 +990,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
        printed += fprintf(fp, " %5.2f%%", percent);
 
        if (symbol_conf.show_nr_samples)
-               printed += fprintf(fp, " %11u", he->nr_events);
+               printed += fprintf(fp, " %11u", he->stat.nr_events);
 
        if (symbol_conf.show_total_period)
-               printed += fprintf(fp, " %12" PRIu64, he->period);
+               printed += fprintf(fp, " %12" PRIu64, he->stat.period);
 
        printed += fprintf(fp, "%s\n", rtrim(s));
 
index 7ff99ec1d95e9e15dccd4d787192d1a23cb3dc97..4125c6284114c8b347bd6118f2b5a33430aebf90 100644 (file)
@@ -49,7 +49,8 @@ static const char *perf_gtk__get_percent_color(double percent)
 static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp,                 \
                                         struct hist_entry *he)                 \
 {                                                                              \
-       double percent = 100.0 * he->_field / hpp->total_period;                \
+       struct hists *hists = he->hists;                                        \
+       double percent = 100.0 * he->stat._field / hists->stats.total_period;   \
        const char *markup;                                                     \
        int ret = 0;                                                            \
                                                                                \
@@ -73,7 +74,7 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)
 
 void perf_gtk__init_hpp(void)
 {
-       perf_hpp__init(false, false);
+       perf_hpp__init();
 
        perf_hpp__format[PERF_HPP__OVERHEAD].color =
                                perf_gtk__hpp_color_overhead;
@@ -102,7 +103,6 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
        struct perf_hpp hpp = {
                .buf            = s,
                .size           = sizeof(s),
-               .total_period   = hists->stats.total_period,
        };
 
        nr_cols = 0;
index 8aada5b3c04ce52843b1eb5e62425bd6e1e5724e..ccb046aac98b70a677b4a0592ca63ee1232dd8b4 100644 (file)
@@ -116,7 +116,7 @@ struct perf_error_ops perf_gtk_eops = {
  * FIXME: Functions below should be implemented properly.
  *        For now, just add stubs for NO_NEWT=1 build.
  */
-#ifdef NO_NEWT_SUPPORT
+#ifndef NEWT_SUPPORT
 void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused,
                         const char *title __maybe_unused)
 {
index 2b667ee454c31cea35b58c900ce2028218cae377..baa28a4d16b94dedafb02cf1f86fe821605fdf1d 100644 (file)
@@ -23,25 +23,25 @@ void ui_helpline__puts(const char *msg);
 
 extern char ui_helpline__current[512];
 
-#ifdef NO_NEWT_SUPPORT
+#ifdef NEWT_SUPPORT
+extern char ui_helpline__last_msg[];
+int ui_helpline__show_help(const char *format, va_list ap);
+#else
 static inline int ui_helpline__show_help(const char *format __maybe_unused,
                                         va_list ap __maybe_unused)
 {
        return 0;
 }
-#else
-extern char ui_helpline__last_msg[];
-int ui_helpline__show_help(const char *format, va_list ap);
-#endif /* NO_NEWT_SUPPORT */
+#endif /* NEWT_SUPPORT */
 
-#ifdef NO_GTK2_SUPPORT
+#ifdef GTK2_SUPPORT
+int perf_gtk__show_helpline(const char *format, va_list ap);
+#else
 static inline int perf_gtk__show_helpline(const char *format __maybe_unused,
                                          va_list ap __maybe_unused)
 {
        return 0;
 }
-#else
-int perf_gtk__show_helpline(const char *format, va_list ap);
-#endif /* NO_GTK2_SUPPORT */
+#endif /* GTK2_SUPPORT */
 
 #endif /* _PERF_UI_HELPLINE_H_ */
index e3f8cd46e7d753258b4044635c5f030a31ab5632..f5a1e4f65263fa0c03468bde22e49364b0ba2c2f 100644 (file)
@@ -8,9 +8,7 @@
 /* hist period print (hpp) functions */
 static int hpp__header_overhead(struct perf_hpp *hpp)
 {
-       const char *fmt = hpp->ptr ? "Baseline" : "Overhead";
-
-       return scnprintf(hpp->buf, hpp->size, fmt);
+       return scnprintf(hpp->buf, hpp->size, "Overhead");
 }
 
 static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
@@ -20,38 +18,18 @@ static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
 
 static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
 {
-       double percent = 100.0 * he->period / hpp->total_period;
-
-       if (hpp->ptr) {
-               struct hists *old_hists = hpp->ptr;
-               u64 total_period = old_hists->stats.total_period;
-               u64 base_period = he->pair ? he->pair->period : 0;
-
-               if (total_period)
-                       percent = 100.0 * base_period / total_period;
-               else
-                       percent = 0.0;
-       }
+       struct hists *hists = he->hists;
+       double percent = 100.0 * he->stat.period / hists->stats.total_period;
 
        return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
 }
 
 static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
 {
-       double percent = 100.0 * he->period / hpp->total_period;
+       struct hists *hists = he->hists;
+       double percent = 100.0 * he->stat.period / hists->stats.total_period;
        const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
 
-       if (hpp->ptr) {
-               struct hists *old_hists = hpp->ptr;
-               u64 total_period = old_hists->stats.total_period;
-               u64 base_period = he->pair ? he->pair->period : 0;
-
-               if (total_period)
-                       percent = 100.0 * base_period / total_period;
-               else
-                       percent = 0.0;
-       }
-
        return scnprintf(hpp->buf, hpp->size, fmt, percent);
 }
 
@@ -69,13 +47,16 @@ static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused)
 
 static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
 {
-       double percent = 100.0 * he->period_sys / hpp->total_period;
+       struct hists *hists = he->hists;
+       double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
+
        return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
 }
 
 static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
 {
-       double percent = 100.0 * he->period_sys / hpp->total_period;
+       struct hists *hists = he->hists;
+       double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
        const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
 
        return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -95,13 +76,16 @@ static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused)
 
 static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
 {
-       double percent = 100.0 * he->period_us / hpp->total_period;
+       struct hists *hists = he->hists;
+       double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
+
        return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
 }
 
 static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
 {
-       double percent = 100.0 * he->period_us / hpp->total_period;
+       struct hists *hists = he->hists;
+       double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
        const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
 
        return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -120,14 +104,17 @@ static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused)
 static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
                                         struct hist_entry *he)
 {
-       double percent = 100.0 * he->period_guest_sys / hpp->total_period;
+       struct hists *hists = he->hists;
+       double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
+
        return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
 }
 
 static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
                                         struct hist_entry *he)
 {
-       double percent = 100.0 * he->period_guest_sys / hpp->total_period;
+       struct hists *hists = he->hists;
+       double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
        const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
 
        return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -146,19 +133,63 @@ static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused)
 static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
                                        struct hist_entry *he)
 {
-       double percent = 100.0 * he->period_guest_us / hpp->total_period;
+       struct hists *hists = he->hists;
+       double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
+
        return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
 }
 
 static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
                                        struct hist_entry *he)
 {
-       double percent = 100.0 * he->period_guest_us / hpp->total_period;
+       struct hists *hists = he->hists;
+       double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
        const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
 
        return scnprintf(hpp->buf, hpp->size, fmt, percent);
 }
 
+static int hpp__header_baseline(struct perf_hpp *hpp)
+{
+       return scnprintf(hpp->buf, hpp->size, "Baseline");
+}
+
+static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused)
+{
+       return 8;
+}
+
+static double baseline_percent(struct hist_entry *he)
+{
+       struct hist_entry *pair = he->pair;
+       struct hists *pair_hists = pair ? pair->hists : NULL;
+       double percent = 0.0;
+
+       if (pair) {
+               u64 total_period = pair_hists->stats.total_period;
+               u64 base_period  = pair->stat.period;
+
+               percent = 100.0 * base_period / total_period;
+       }
+
+       return percent;
+}
+
+static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
+{
+       double percent = baseline_percent(he);
+
+       return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
+}
+
+static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
+{
+       double percent = baseline_percent(he);
+       const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
+
+       return scnprintf(hpp->buf, hpp->size, fmt, percent);
+}
+
 static int hpp__header_samples(struct perf_hpp *hpp)
 {
        const char *fmt = symbol_conf.field_sep ? "%s" : "%11s";
@@ -175,7 +206,7 @@ static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he)
 {
        const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64;
 
-       return scnprintf(hpp->buf, hpp->size, fmt, he->nr_events);
+       return scnprintf(hpp->buf, hpp->size, fmt, he->stat.nr_events);
 }
 
 static int hpp__header_period(struct perf_hpp *hpp)
@@ -194,7 +225,7 @@ static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
 {
        const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
 
-       return scnprintf(hpp->buf, hpp->size, fmt, he->period);
+       return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period);
 }
 
 static int hpp__header_delta(struct perf_hpp *hpp)
@@ -211,20 +242,22 @@ static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)
 
 static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
 {
-       struct hists *pair_hists = hpp->ptr;
+       struct hist_entry *pair = he->pair;
+       struct hists *pair_hists = pair ? pair->hists : NULL;
+       struct hists *hists = he->hists;
        u64 old_total, new_total;
        double old_percent = 0, new_percent = 0;
        double diff;
        const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
        char buf[32] = " ";
 
-       old_total = pair_hists->stats.total_period;
-       if (old_total > 0 && he->pair)
-               old_percent = 100.0 * he->pair->period / old_total;
+       old_total = pair_hists ? pair_hists->stats.total_period : 0;
+       if (old_total > 0 && pair)
+               old_percent = 100.0 * pair->stat.period / old_total;
 
-       new_total = hpp->total_period;
+       new_total = hists->stats.total_period;
        if (new_total > 0)
-               new_percent = 100.0 * he->period / new_total;
+               new_percent = 100.0 * he->stat.period / new_total;
 
        diff = new_percent - old_percent;
        if (fabs(diff) >= 0.01)
@@ -244,13 +277,15 @@ static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused)
 }
 
 static int hpp__entry_displ(struct perf_hpp *hpp,
-                           struct hist_entry *he __maybe_unused)
+                           struct hist_entry *he)
 {
+       struct hist_entry *pair = he->pair;
+       long displacement = pair ? pair->position - he->position : 0;
        const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
        char buf[32] = " ";
 
-       if (hpp->displacement)
-               scnprintf(buf, sizeof(buf), "%+4ld", hpp->displacement);
+       if (displacement)
+               scnprintf(buf, sizeof(buf), "%+4ld", displacement);
 
        return scnprintf(hpp->buf, hpp->size, fmt, buf);
 }
@@ -267,6 +302,7 @@ static int hpp__entry_displ(struct perf_hpp *hpp,
        .entry  = hpp__entry_ ## _name
 
 struct perf_hpp_fmt perf_hpp__format[] = {
+       { .cond = false, HPP__COLOR_PRINT_FNS(baseline) },
        { .cond = true,  HPP__COLOR_PRINT_FNS(overhead) },
        { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) },
        { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) },
@@ -281,7 +317,7 @@ struct perf_hpp_fmt perf_hpp__format[] = {
 #undef HPP__COLOR_PRINT_FNS
 #undef HPP__PRINT_FNS
 
-void perf_hpp__init(bool need_pair, bool show_displacement)
+void perf_hpp__init(void)
 {
        if (symbol_conf.show_cpu_utilization) {
                perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true;
@@ -298,13 +334,12 @@ void perf_hpp__init(bool need_pair, bool show_displacement)
 
        if (symbol_conf.show_total_period)
                perf_hpp__format[PERF_HPP__PERIOD].cond = true;
+}
 
-       if (need_pair) {
-               perf_hpp__format[PERF_HPP__DELTA].cond = true;
-
-               if (show_displacement)
-                       perf_hpp__format[PERF_HPP__DISPL].cond = true;
-       }
+void perf_hpp__column_enable(unsigned col, bool enable)
+{
+       BUG_ON(col >= PERF_HPP__MAX_INDEX);
+       perf_hpp__format[col].cond = enable;
 }
 
 static inline void advance_hpp(struct perf_hpp *hpp, int inc)
@@ -319,6 +354,7 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
        const char *sep = symbol_conf.field_sep;
        char *start = hpp->buf;
        int i, ret;
+       bool first = true;
 
        if (symbol_conf.exclude_other && !he->parent)
                return 0;
@@ -327,9 +363,10 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
                if (!perf_hpp__format[i].cond)
                        continue;
 
-               if (!sep || i > 0) {
+               if (!sep || !first) {
                        ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: "  ");
                        advance_hpp(hpp, ret);
+                       first = false;
                }
 
                if (color && perf_hpp__format[i].color)
index bd7d460f844c2cb4d4035076a2a8bca6a864de60..ebb4cc10787625aca596f6a41a14d56efd9e60d8 100644 (file)
@@ -30,7 +30,7 @@ void setup_browser(bool fallback_to_pager)
                if (fallback_to_pager)
                        setup_pager();
 
-               perf_hpp__init(false, false);
+               perf_hpp__init();
                break;
        }
 }
index 882461a428306ea764c4417a668385c5956b9d2f..fbd4e32d07437280623cf913acfbb35583fdc1be 100644 (file)
@@ -271,7 +271,7 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
 {
        switch (callchain_param.mode) {
        case CHAIN_GRAPH_REL:
-               return callchain__fprintf_graph(fp, &he->sorted_chain, he->period,
+               return callchain__fprintf_graph(fp, &he->sorted_chain, he->stat.period,
                                                left_margin);
                break;
        case CHAIN_GRAPH_ABS:
@@ -292,9 +292,10 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
 
 static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
                                            struct hists *hists,
-                                           u64 total_period, FILE *fp)
+                                           FILE *fp)
 {
        int left_margin = 0;
+       u64 total_period = hists->stats.total_period;
 
        if (sort__first_dimension == SORT_COMM) {
                struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
@@ -307,17 +308,13 @@ static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
 }
 
 static int hist_entry__fprintf(struct hist_entry *he, size_t size,
-                              struct hists *hists, struct hists *pair_hists,
-                              long displacement, u64 total_period, FILE *fp)
+                              struct hists *hists, FILE *fp)
 {
        char bf[512];
        int ret;
        struct perf_hpp hpp = {
                .buf            = bf,
                .size           = size,
-               .total_period   = total_period,
-               .displacement   = displacement,
-               .ptr            = pair_hists,
        };
        bool color = !symbol_conf.field_sep;
 
@@ -330,22 +327,17 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
        ret = fprintf(fp, "%s\n", bf);
 
        if (symbol_conf.use_callchain)
-               ret += hist_entry__callchain_fprintf(he, hists,
-                                                    total_period, fp);
+               ret += hist_entry__callchain_fprintf(he, hists, fp);
 
        return ret;
 }
 
-size_t hists__fprintf(struct hists *hists, struct hists *pair,
-                     bool show_displacement, bool show_header, int max_rows,
+size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
                      int max_cols, FILE *fp)
 {
        struct sort_entry *se;
        struct rb_node *nd;
        size_t ret = 0;
-       u64 total_period;
-       unsigned long position = 1;
-       long displacement = 0;
        unsigned int width;
        const char *sep = symbol_conf.field_sep;
        const char *col_width = symbol_conf.col_width_list_str;
@@ -354,8 +346,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
        struct perf_hpp dummy_hpp = {
                .buf    = bf,
                .size   = sizeof(bf),
-               .ptr    = pair,
        };
+       bool first = true;
 
        init_rem_hits();
 
@@ -367,8 +359,10 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
                if (!perf_hpp__format[idx].cond)
                        continue;
 
-               if (idx)
+               if (!first)
                        fprintf(fp, "%s", sep ?: "  ");
+               else
+                       first = false;
 
                perf_hpp__format[idx].header(&dummy_hpp);
                fprintf(fp, "%s", bf);
@@ -403,6 +397,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
        if (sep)
                goto print_entries;
 
+       first = true;
+
        fprintf(fp, "# ");
        for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
                unsigned int i;
@@ -410,8 +406,10 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
                if (!perf_hpp__format[idx].cond)
                        continue;
 
-               if (idx)
+               if (!first)
                        fprintf(fp, "%s", sep ?: "  ");
+               else
+                       first = false;
 
                width = perf_hpp__format[idx].width(&dummy_hpp);
                for (i = 0; i < width; i++)
@@ -441,24 +439,13 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
                goto out;
 
 print_entries:
-       total_period = hists->stats.total_period;
-
        for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
                struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
 
                if (h->filtered)
                        continue;
 
-               if (show_displacement) {
-                       if (h->pair != NULL)
-                               displacement = ((long)h->pair->position -
-                                               (long)position);
-                       else
-                               displacement = 0;
-                       ++position;
-               }
-               ret += hist_entry__fprintf(h, max_cols, hists, pair, displacement,
-                                          total_period, fp);
+               ret += hist_entry__fprintf(h, max_cols, hists, fp);
 
                if (max_rows && ++nr_rows >= max_rows)
                        goto out;
index 9b5b21e7b0328ee2229c25dfb2cdf9548f853c04..39242dcee8f20bd5160bf8d1ea34f1a4ca79ff29 100644 (file)
@@ -138,7 +138,10 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
                         bool print_lines, bool full_paths, int min_pcnt,
                         int max_lines);
 
-#ifdef NO_NEWT_SUPPORT
+#ifdef NEWT_SUPPORT
+int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
+                        void(*timer)(void *arg), void *arg, int delay_secs);
+#else
 static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
                                       struct map *map __maybe_unused,
                                       int evidx __maybe_unused,
@@ -148,9 +151,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
 {
        return 0;
 }
-#else
-int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
-                        void(*timer)(void *arg), void *arg, int delay_secs);
 #endif
 
 extern const char      *disassembler_style;
index ab17694265412793c3c170a32670ecae2f4b9515..2bd51370ad28867bec442ab2cb72c49e9652dc36 100644 (file)
@@ -33,39 +33,41 @@ extern int pager_use_color;
 
 extern int use_browser;
 
-#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
-static inline void setup_browser(bool fallback_to_pager)
-{
-       if (fallback_to_pager)
-               setup_pager();
-}
-static inline void exit_browser(bool wait_for_ok __maybe_unused) {}
-#else
+#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
 void setup_browser(bool fallback_to_pager);
 void exit_browser(bool wait_for_ok);
 
-#ifdef NO_NEWT_SUPPORT
+#ifdef NEWT_SUPPORT
+int ui__init(void);
+void ui__exit(bool wait_for_ok);
+#else
 static inline int ui__init(void)
 {
        return -1;
 }
 static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
-#else
-int ui__init(void);
-void ui__exit(bool wait_for_ok);
 #endif
 
-#ifdef NO_GTK2_SUPPORT
+#ifdef GTK2_SUPPORT
+int perf_gtk__init(void);
+void perf_gtk__exit(bool wait_for_ok);
+#else
 static inline int perf_gtk__init(void)
 {
        return -1;
 }
 static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {}
-#else
-int perf_gtk__init(void);
-void perf_gtk__exit(bool wait_for_ok);
 #endif
-#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
+
+#else /* NEWT_SUPPORT || GTK2_SUPPORT */
+
+static inline void setup_browser(bool fallback_to_pager)
+{
+       if (fallback_to_pager)
+               setup_pager();
+}
+static inline void exit_browser(bool wait_for_ok __maybe_unused) {}
+#endif /* NEWT_SUPPORT || GTK2_SUPPORT */
 
 char *alias_lookup(const char *alias);
 int split_cmdline(char *cmdline, const char ***argv);
@@ -105,7 +107,7 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
 extern char *perf_pathdup(const char *fmt, ...)
        __attribute__((format (printf, 1, 2)));
 
-#ifdef NO_STRLCPY
+#ifndef HAVE_STRLCPY
 extern size_t strlcpy(char *dest, const char *src, size_t size);
 #endif
 
index 66eb3828ceb5ec4b2df31147274cc767be09856a..03f830b48148a7b41f0c4bb1b59b7f1614db035c 100644 (file)
@@ -49,7 +49,7 @@ int dump_printf(const char *fmt, ...)
        return ret;
 }
 
-#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
+#if !defined(NEWT_SUPPORT) && !defined(GTK2_SUPPORT)
 int ui__warning(const char *format, ...)
 {
        va_list args;
index bb2e7d1007ab0eb1b5850a2d79e1a4b0a519e85b..dec98750b48472ab4f34b7dc1b0856c6ae895909 100644 (file)
@@ -15,7 +15,14 @@ void trace_event(union perf_event *event);
 struct ui_progress;
 struct perf_error_ops;
 
-#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
+#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
+
+#include "../ui/progress.h"
+int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
+#include "../ui/util.h"
+
+#else
+
 static inline void ui_progress__update(u64 curr __maybe_unused,
                                       u64 total __maybe_unused,
                                       const char *title __maybe_unused) {}
@@ -34,13 +41,7 @@ perf_error__unregister(struct perf_error_ops *eops __maybe_unused)
        return 0;
 }
 
-#else /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
-
-#include "../ui/progress.h"
-int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
-#include "../ui/util.h"
-
-#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
+#endif /* NEWT_SUPPORT || GTK2_SUPPORT */
 
 int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
 int ui__error_paranoid(void);
index ae89686102f4a7224d0f425fb26ad3712f17c616..186b87730396712d6fbfcbc95837168b81287ca4 100644 (file)
@@ -154,8 +154,8 @@ error:
        return -ENOMEM;
 }
 
-int perf_evlist__add_attrs(struct perf_evlist *evlist,
-                          struct perf_event_attr *attrs, size_t nr_attrs)
+static int perf_evlist__add_attrs(struct perf_evlist *evlist,
+                                 struct perf_event_attr *attrs, size_t nr_attrs)
 {
        struct perf_evsel *evsel, *n;
        LIST_HEAD(head);
@@ -189,60 +189,6 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
        return perf_evlist__add_attrs(evlist, attrs, nr_attrs);
 }
 
-static int trace_event__id(const char *evname)
-{
-       char *filename, *colon;
-       int err = -1, fd;
-
-       if (asprintf(&filename, "%s/%s/id", tracing_events_path, evname) < 0)
-               return -1;
-
-       colon = strrchr(filename, ':');
-       if (colon != NULL)
-               *colon = '/';
-
-       fd = open(filename, O_RDONLY);
-       if (fd >= 0) {
-               char id[16];
-               if (read(fd, id, sizeof(id)) > 0)
-                       err = atoi(id);
-               close(fd);
-       }
-
-       free(filename);
-       return err;
-}
-
-int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
-                                const char *tracepoints[],
-                                size_t nr_tracepoints)
-{
-       int err;
-       size_t i;
-       struct perf_event_attr *attrs = zalloc(nr_tracepoints * sizeof(*attrs));
-
-       if (attrs == NULL)
-               return -1;
-
-       for (i = 0; i < nr_tracepoints; i++) {
-               err = trace_event__id(tracepoints[i]);
-
-               if (err < 0)
-                       goto out_free_attrs;
-
-               attrs[i].type          = PERF_TYPE_TRACEPOINT;
-               attrs[i].config        = err;
-               attrs[i].sample_type   = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
-                                         PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD);
-               attrs[i].sample_period = 1;
-       }
-
-       err = perf_evlist__add_attrs(evlist, attrs, nr_tracepoints);
-out_free_attrs:
-       free(attrs);
-       return err;
-}
-
 struct perf_evsel *
 perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
 {
@@ -257,32 +203,18 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
        return NULL;
 }
 
-int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
-                                         const struct perf_evsel_str_handler *assocs,
-                                         size_t nr_assocs)
+int perf_evlist__add_newtp(struct perf_evlist *evlist,
+                          const char *sys, const char *name, void *handler)
 {
        struct perf_evsel *evsel;
-       int err;
-       size_t i;
-
-       for (i = 0; i < nr_assocs; i++) {
-               err = trace_event__id(assocs[i].name);
-               if (err < 0)
-                       goto out;
-
-               evsel = perf_evlist__find_tracepoint_by_id(evlist, err);
-               if (evsel == NULL)
-                       continue;
 
-               err = -EEXIST;
-               if (evsel->handler.func != NULL)
-                       goto out;
-               evsel->handler.func = assocs[i].handler;
-       }
+       evsel = perf_evsel__newtp(sys, name, evlist->nr_entries);
+       if (evsel == NULL)
+               return -1;
 
-       err = 0;
-out:
-       return err;
+       evsel->handler.func = handler;
+       perf_evlist__add(evlist, evsel);
+       return 0;
 }
 
 void perf_evlist__disable(struct perf_evlist *evlist)
index 3f1fb66be02203e925d8f01b38338d90b66d344a..56003f779e601d181eec34fd38de5bb66c30bc5c 100644 (file)
@@ -51,26 +51,14 @@ void perf_evlist__delete(struct perf_evlist *evlist);
 
 void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
 int perf_evlist__add_default(struct perf_evlist *evlist);
-int perf_evlist__add_attrs(struct perf_evlist *evlist,
-                          struct perf_event_attr *attrs, size_t nr_attrs);
 int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
                                     struct perf_event_attr *attrs, size_t nr_attrs);
-int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
-                                const char *tracepoints[], size_t nr_tracepoints);
-int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
-                                         const struct perf_evsel_str_handler *assocs,
-                                         size_t nr_assocs);
-
-#define perf_evlist__add_attrs_array(evlist, array) \
-       perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array))
+
 #define perf_evlist__add_default_attrs(evlist, array) \
        __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array))
 
-#define perf_evlist__add_tracepoints_array(evlist, array) \
-       perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array))
-
-#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
-       perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
+int perf_evlist__add_newtp(struct perf_evlist *evlist,
+                          const char *sys, const char *name, void *handler);
 
 int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
 
index 389590c1ad21741b6eb8f6dac3db8c84551800db..3ac38031d53400337815560562a52093aaeee9e2 100755 (executable)
@@ -22,7 +22,7 @@ do
      }' "Documentation/perf-$cmd.txt"
 done
 
-echo "#ifndef NO_LIBELF_SUPPORT"
+echo "#ifdef LIBELF_SUPPORT"
 sed -n -e 's/^perf-\([^        ]*\)[   ].* full.*/\1/p' command-list.txt |
 sort |
 while read cmd
@@ -35,5 +35,5 @@ do
            p
      }' "Documentation/perf-$cmd.txt"
 done
-echo "#endif /* NO_LIBELF_SUPPORT */"
+echo "#endif /* LIBELF_SUPPORT */"
 echo "};"
index 236bc9d98ff267ab598c1de35073a4bca39f3f8f..277947a669b24cca255538c558f56bbcd14d4437 100644 (file)
@@ -135,31 +135,47 @@ static void hist_entry__add_cpumode_period(struct hist_entry *he,
 {
        switch (cpumode) {
        case PERF_RECORD_MISC_KERNEL:
-               he->period_sys += period;
+               he->stat.period_sys += period;
                break;
        case PERF_RECORD_MISC_USER:
-               he->period_us += period;
+               he->stat.period_us += period;
                break;
        case PERF_RECORD_MISC_GUEST_KERNEL:
-               he->period_guest_sys += period;
+               he->stat.period_guest_sys += period;
                break;
        case PERF_RECORD_MISC_GUEST_USER:
-               he->period_guest_us += period;
+               he->stat.period_guest_us += period;
                break;
        default:
                break;
        }
 }
 
+static void he_stat__add_period(struct he_stat *he_stat, u64 period)
+{
+       he_stat->period         += period;
+       he_stat->nr_events      += 1;
+}
+
+static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
+{
+       dest->period            += src->period;
+       dest->period_sys        += src->period_sys;
+       dest->period_us         += src->period_us;
+       dest->period_guest_sys  += src->period_guest_sys;
+       dest->period_guest_us   += src->period_guest_us;
+       dest->nr_events         += src->nr_events;
+}
+
 static void hist_entry__decay(struct hist_entry *he)
 {
-       he->period = (he->period * 7) / 8;
-       he->nr_events = (he->nr_events * 7) / 8;
+       he->stat.period = (he->stat.period * 7) / 8;
+       he->stat.nr_events = (he->stat.nr_events * 7) / 8;
 }
 
 static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
 {
-       u64 prev_period = he->period;
+       u64 prev_period = he->stat.period;
 
        if (prev_period == 0)
                return true;
@@ -167,9 +183,9 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
        hist_entry__decay(he);
 
        if (!he->filtered)
-               hists->stats.total_period -= prev_period - he->period;
+               hists->stats.total_period -= prev_period - he->stat.period;
 
-       return he->period == 0;
+       return he->stat.period == 0;
 }
 
 static void __hists__decay_entries(struct hists *hists, bool zap_user,
@@ -223,7 +239,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
 
        if (he != NULL) {
                *he = *template;
-               he->nr_events = 1;
+
                if (he->ms.map)
                        he->ms.map->referenced = true;
                if (symbol_conf.use_callchain)
@@ -238,7 +254,7 @@ static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
        if (!h->filtered) {
                hists__calc_col_len(hists, h);
                ++hists->nr_entries;
-               hists->stats.total_period += h->period;
+               hists->stats.total_period += h->stat.period;
        }
 }
 
@@ -270,8 +286,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
                cmp = hist_entry__cmp(entry, he);
 
                if (!cmp) {
-                       he->period += period;
-                       ++he->nr_events;
+                       he_stat__add_period(&he->stat, period);
 
                        /* If the map of an existing hist_entry has
                         * become out-of-date due to an exec() or
@@ -321,10 +336,14 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self,
                .cpu    = al->cpu,
                .ip     = bi->to.addr,
                .level  = al->level,
-               .period = period,
+               .stat = {
+                       .period = period,
+                       .nr_events = 1,
+               },
                .parent = sym_parent,
                .filtered = symbol__parent_filter(sym_parent),
                .branch_info = bi,
+               .hists  = self,
        };
 
        return add_hist_entry(self, &entry, al, period);
@@ -343,9 +362,13 @@ struct hist_entry *__hists__add_entry(struct hists *self,
                .cpu    = al->cpu,
                .ip     = al->addr,
                .level  = al->level,
-               .period = period,
+               .stat = {
+                       .period = period,
+                       .nr_events = 1,
+               },
                .parent = sym_parent,
                .filtered = symbol__parent_filter(sym_parent),
+               .hists  = self,
        };
 
        return add_hist_entry(self, &entry, al, period);
@@ -410,12 +433,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
                cmp = hist_entry__collapse(iter, he);
 
                if (!cmp) {
-                       iter->period            += he->period;
-                       iter->period_sys        += he->period_sys;
-                       iter->period_us         += he->period_us;
-                       iter->period_guest_sys  += he->period_guest_sys;
-                       iter->period_guest_us   += he->period_guest_us;
-                       iter->nr_events         += he->nr_events;
+                       he_stat__add_stat(&iter->stat, &he->stat);
 
                        if (symbol_conf.use_callchain) {
                                callchain_cursor_reset(&callchain_cursor);
@@ -518,7 +536,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
                parent = *p;
                iter = rb_entry(parent, struct hist_entry, rb_node);
 
-               if (he->period > iter->period)
+               if (he->stat.period > iter->stat.period)
                        p = &(*p)->rb_left;
                else
                        p = &(*p)->rb_right;
@@ -579,8 +597,8 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
        if (h->ms.unfolded)
                hists->nr_entries += h->nr_rows;
        h->row_offset = 0;
-       hists->stats.total_period += h->period;
-       hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->nr_events;
+       hists->stats.total_period += h->stat.period;
+       hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->stat.nr_events;
 
        hists__calc_col_len(hists, h);
 }
index f011ad4756e84f202fedf15b1037413a51edde88..66cb31fe81d2a7c3b7a45e925a5fc6d3cb7a4e63 100644 (file)
@@ -98,9 +98,8 @@ void hists__output_recalc_col_len(struct hists *hists, int max_rows);
 void hists__inc_nr_events(struct hists *self, u32 type);
 size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);
 
-size_t hists__fprintf(struct hists *self, struct hists *pair,
-                     bool show_displacement, bool show_header,
-                     int max_rows, int max_cols, FILE *fp);
+size_t hists__fprintf(struct hists *self, bool show_header, int max_rows,
+                     int max_cols, FILE *fp);
 
 int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
 int hist_entry__annotate(struct hist_entry *self, size_t privsize);
@@ -118,9 +117,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
 struct perf_hpp {
        char *buf;
        size_t size;
-       u64 total_period;
        const char *sep;
-       long displacement;
        void *ptr;
 };
 
@@ -135,6 +132,7 @@ struct perf_hpp_fmt {
 extern struct perf_hpp_fmt perf_hpp__format[];
 
 enum {
+       PERF_HPP__BASELINE,
        PERF_HPP__OVERHEAD,
        PERF_HPP__OVERHEAD_SYS,
        PERF_HPP__OVERHEAD_US,
@@ -148,13 +146,22 @@ enum {
        PERF_HPP__MAX_INDEX
 };
 
-void perf_hpp__init(bool need_pair, bool show_displacement);
+void perf_hpp__init(void);
+void perf_hpp__column_enable(unsigned col, bool enable);
 int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
                                bool color);
 
 struct perf_evlist;
 
-#ifdef NO_NEWT_SUPPORT
+#ifdef NEWT_SUPPORT
+#include "../ui/keysyms.h"
+int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
+                            void(*timer)(void *arg), void *arg, int delay_secs);
+
+int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
+                                 void(*timer)(void *arg), void *arg,
+                                 int refresh);
+#else
 static inline
 int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
                                  const char *help __maybe_unused,
@@ -177,17 +184,13 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self
 }
 #define K_LEFT -1
 #define K_RIGHT -2
-#else
-#include "../ui/keysyms.h"
-int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
-                            void(*timer)(void *arg), void *arg, int delay_secs);
+#endif
 
-int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
+#ifdef GTK2_SUPPORT
+int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
                                  void(*timer)(void *arg), void *arg,
                                  int refresh);
-#endif
-
-#ifdef NO_GTK2_SUPPORT
+#else
 static inline
 int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
                                  const char *help __maybe_unused,
@@ -197,11 +200,6 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
 {
        return 0;
 }
-
-#else
-int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
-                                 void(*timer)(void *arg), void *arg,
-                                 int refresh);
 #endif
 
 unsigned int hists__sort_list_width(struct hists *self);
index 9bcdc844b330b2c4f9af7435b054caa7d759dcf0..2a030c5af3aa2062082d87b1604b9980a1006844 100644 (file)
@@ -1,3 +1,2 @@
 #include <stdbool.h>
-#include <stdbool.h>
 #include "../../../../include/linux/rbtree.h"
diff --git a/tools/perf/util/include/linux/rbtree_augmented.h b/tools/perf/util/include/linux/rbtree_augmented.h
new file mode 100644 (file)
index 0000000..9d6fcdf
--- /dev/null
@@ -0,0 +1,2 @@
+#include <stdbool.h>
+#include "../../../../include/linux/rbtree_augmented.h"
index ead5316b3f89299f0ff372cd7ba06a96b4fd0184..6109fa4d14cd79a5fc87e39e93df6bda46daa66c 100644 (file)
@@ -162,7 +162,7 @@ int map__load(struct map *self, symbol_filter_t filter)
                pr_warning(", continuing without symbols\n");
                return -1;
        } else if (nr == 0) {
-#ifndef NO_LIBELF_SUPPORT
+#ifdef LIBELF_SUPPORT
                const size_t len = strlen(name);
                const size_t real_len = len - sizeof(DSO__DELETED);
 
index 443fc116512bc37bdbc4ba61ee2e942e9ab00c89..2bc9e70df7e2552ecc14857d1f26c2311bb2fde7 100644 (file)
@@ -384,6 +384,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
                        return usage_with_options_internal(usagestr, options, 1);
                if (internal_help && !strcmp(arg + 2, "help"))
                        return parse_options_usage(usagestr, options);
+               if (!strcmp(arg + 2, "list-opts"))
+                       return PARSE_OPT_LIST;
                switch (parse_long_opt(ctx, arg + 2, options)) {
                case -1:
                        return parse_options_usage(usagestr, options);
@@ -422,6 +424,12 @@ int parse_options(int argc, const char **argv, const struct option *options,
                exit(129);
        case PARSE_OPT_DONE:
                break;
+       case PARSE_OPT_LIST:
+               while (options->type != OPTION_END) {
+                       printf("--%s ", options->long_name);
+                       options++;
+               }
+               exit(130);
        default: /* PARSE_OPT_UNKNOWN */
                if (ctx.argv[0][1] == '-') {
                        error("unknown option `%s'", ctx.argv[0] + 2);
index abc31a1dac1a738c5791512032c5a9337af84b9a..7bb5999940ca925f60482bbfa10aea1a6e685b10 100644 (file)
@@ -140,6 +140,7 @@ extern NORETURN void usage_with_options(const char * const *usagestr,
 enum {
        PARSE_OPT_HELP = -1,
        PARSE_OPT_DONE,
+       PARSE_OPT_LIST,
        PARSE_OPT_UNKNOWN,
 };
 
index bd74977114242ff465af39a291d30aa7d463f3b2..a8c49548ca48f5bc4f7ae14134ee57d7779b46e8 100644 (file)
@@ -22,7 +22,7 @@ static const char *get_perf_dir(void)
        return ".";
 }
 
-#ifdef NO_STRLCPY
+#ifndef HAVE_STRLCPY
 size_t strlcpy(char *dest, const char *src, size_t size)
 {
        size_t ret = strlen(src);
index 316dbe7f86ed2444cdb616cf940f91da22bfc176..5a4f2b6f3738c1966b180484dcfb71f70d0e0afd 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __PERF_REGS_H
 #define __PERF_REGS_H
 
-#ifndef NO_PERF_REGS
+#ifdef HAVE_PERF_REGS
 #include <perf_regs.h>
 #else
 #define PERF_REGS_MASK 0
@@ -10,5 +10,5 @@ static inline const char *perf_reg_name(int id __maybe_unused)
 {
        return NULL;
 }
-#endif /* NO_PERF_REGS */
+#endif /* HAVE_PERF_REGS */
 #endif /* __PERF_REGS_H */
index 12d634792de511051decb3cfa7caf6458d60560c..5786f323b597226a4668f1342ec0f06f5e8ec38c 100644 (file)
@@ -43,6 +43,15 @@ extern struct sort_entry sort_sym_from;
 extern struct sort_entry sort_sym_to;
 extern enum sort_type sort__first_dimension;
 
+struct he_stat {
+       u64                     period;
+       u64                     period_sys;
+       u64                     period_us;
+       u64                     period_guest_sys;
+       u64                     period_guest_us;
+       u32                     nr_events;
+};
+
 /**
  * struct hist_entry - histogram entry
  *
@@ -52,16 +61,11 @@ extern enum sort_type sort__first_dimension;
 struct hist_entry {
        struct rb_node          rb_node_in;
        struct rb_node          rb_node;
-       u64                     period;
-       u64                     period_sys;
-       u64                     period_us;
-       u64                     period_guest_sys;
-       u64                     period_guest_us;
+       struct he_stat          stat;
        struct map_symbol       ms;
        struct thread           *thread;
        u64                     ip;
        s32                     cpu;
-       u32                     nr_events;
 
        /* XXX These two should move to some tree widget lib */
        u16                     row_offset;
@@ -73,12 +77,13 @@ struct hist_entry {
        u8                      filtered;
        char                    *srcline;
        struct symbol           *parent;
+       unsigned long           position;
        union {
-               unsigned long     position;
                struct hist_entry *pair;
                struct rb_root    sorted_chain;
        };
        struct branch_info      *branch_info;
+       struct hists            *hists;
        struct callchain_root   callchain[0];
 };
 
index b441b07172b7ea9d4a5bd9cf0b1b1a6bd0ed5aba..8b6ef7fac745824b6844c2b9462742bd28460d61 100644 (file)
@@ -12,7 +12,7 @@
 #include <byteswap.h>
 #include <libgen.h>
 
-#ifndef NO_LIBELF_SUPPORT
+#ifdef LIBELF_SUPPORT
 #include <libelf.h>
 #include <gelf.h>
 #include <elf.h>
@@ -46,10 +46,10 @@ char *strxfrchar(char *s, char from, char to);
  * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
  * for newer versions we can use mmap to reduce memory usage:
  */
-#ifdef LIBELF_NO_MMAP
-# define PERF_ELF_C_READ_MMAP ELF_C_READ
-#else
+#ifdef LIBELF_MMAP
 # define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP
+#else
+# define PERF_ELF_C_READ_MMAP ELF_C_READ
 #endif
 
 #ifndef DMGL_PARAMS
@@ -233,7 +233,7 @@ struct symsrc {
        int fd;
        enum dso_binary_type type;
 
-#ifndef NO_LIBELF_SUPPORT
+#ifdef LIBELF_SUPPORT
        Elf *elf;
        GElf_Ehdr ehdr;
 
index a78c8b303bb5dd6c3d2cba7df8b367f4f18b66c1..cb6bc503a792413dd701fec8dafbf60d9e921ed6 100644 (file)
@@ -13,7 +13,7 @@ struct unwind_entry {
 
 typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
 
-#ifndef NO_LIBUNWIND_SUPPORT
+#ifdef LIBUNWIND_SUPPORT
 int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
                        struct machine *machine,
                        struct thread *thread,
@@ -31,5 +31,5 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
 {
        return 0;
 }
-#endif /* NO_LIBUNWIND_SUPPORT */
+#endif /* LIBUNWIND_SUPPORT */
 #endif /* __UNWIND_H */
index 2055cf38041ce24e071c4f5b95af42f6237bc8d7..99664598bc1acfa3d03e0aaa1b0a44834be5f2d8 100644 (file)
@@ -1,7 +1,7 @@
 #include "../perf.h"
 #include "util.h"
 #include <sys/mman.h>
-#ifndef NO_BACKTRACE
+#ifdef BACKTRACE_SUPPORT
 #include <execinfo.h>
 #endif
 #include <stdio.h>
@@ -165,7 +165,7 @@ size_t hex_width(u64 v)
 }
 
 /* Obtain a backtrace and print it to stdout. */
-#ifndef NO_BACKTRACE
+#ifdef BACKTRACE_SUPPORT
 void dump_stack(void)
 {
        void *array[16];
index c05bcd293d8c636798b21207027c925a335d7cea..b51d787176d323bb3a2d6f0016b2d2cf4db16d3d 100755 (executable)
@@ -1873,10 +1873,10 @@ sub make_oldconfig {
        apply_min_config;
     }
 
-    if (!run_command "$make oldnoconfig") {
-       # Perhaps oldnoconfig doesn't exist in this version of the kernel
+    if (!run_command "$make olddefconfig") {
+       # Perhaps olddefconfig doesn't exist in this version of the kernel
        # try a yes '' | oldconfig
-       doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
+       doprint "olddefconfig failed, trying yes '' | make oldconfig\n";
        run_command "yes '' | $make oldconfig" or
            dodie "failed make config oldconfig";
     }
@@ -1929,7 +1929,7 @@ sub build {
 
     # old config can ask questions
     if ($type eq "oldconfig") {
-       $type = "oldnoconfig";
+       $type = "olddefconfig";
 
        # allow for empty configs
        run_command "touch $output_config";
@@ -1959,7 +1959,7 @@ sub build {
        load_force_config($minconfig);
     }
 
-    if ($type ne "oldnoconfig") {
+    if ($type ne "olddefconfig") {
        run_command "$make $type" or
            dodie "failed make config";
     }
@@ -2458,8 +2458,7 @@ my %config_set;
 
 # config_off holds the set of configs that the bad config had disabled.
 # We need to record them and set them in the .config when running
-# oldnoconfig, because oldnoconfig does not turn off new symbols, but
-# instead just keeps the defaults.
+# olddefconfig, because olddefconfig keeps the defaults.
 my %config_off;
 
 # config_off_tmp holds a set of configs to turn off for now
@@ -3250,7 +3249,7 @@ sub test_this_config {
     }
 
     # Remove this config from the list of configs
-    # do a make oldnoconfig and then read the resulting
+    # do a make olddefconfig and then read the resulting
     # .config to make sure it is missing the config that
     # we had before
     my %configs = %min_configs;